Fix incorrect ordering of mouse click and escape key events
When pressing escape soon after left clicking (within ~60ms), KiCad was processing the escape key before the mouse button release event due to wxWidgets event queue ordering. This caused operations to be canceled instead of completed. The fix adds flushPendingClicks() which checks button state via polling when an escape key event arrives. If a button was logically pressed but has been physically released, the click event is generated before the escape event is processed, maintaining proper ordering. Fixes https://gitlab.com/kicad/code/kicad/-/issues/20527
This commit is contained in:
@@ -474,6 +474,28 @@ std::optional<TOOL_EVENT> TOOL_DISPATCHER::GetToolEvent( wxKeyEvent* aKeyEvent,
|
||||
}
|
||||
|
||||
|
||||
void TOOL_DISPATCHER::flushPendingClicks()
|
||||
{
|
||||
// When an escape key event arrives, keyboard events can be processed before mouse button
|
||||
// events due to wxWidgets event queue ordering. If a mouse button was pressed and has since
|
||||
// been released (detected via polling), we need to process that click before handling the
|
||||
// escape to maintain proper event ordering.
|
||||
for( BUTTON_STATE* st : m_buttons )
|
||||
{
|
||||
if( st->pressed && !st->GetState() )
|
||||
{
|
||||
st->pressed = false;
|
||||
|
||||
TOOL_EVENT clickEvt( TC_MOUSE, TA_MOUSE_CLICK, st->button );
|
||||
clickEvt.SetMousePosition( st->downPosition );
|
||||
m_toolMgr->ProcessEvent( clickEvt );
|
||||
|
||||
st->dragging = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
|
||||
{
|
||||
bool motion = false;
|
||||
@@ -592,6 +614,12 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
|
||||
|
||||
keyIsEscape = ( ke->GetKeyCode() == WXK_ESCAPE );
|
||||
|
||||
// When escape is pressed shortly after a mouse click, the keyboard event can be
|
||||
// processed before the mouse button release event. Flush any pending clicks first
|
||||
// to ensure proper event ordering.
|
||||
if( keyIsEscape )
|
||||
flushPendingClicks();
|
||||
|
||||
if( KIUI::IsInputControlFocused( focus ) )
|
||||
{
|
||||
bool enabled = KIUI::IsInputControlEditable( focus );
|
||||
|
||||
@@ -81,6 +81,11 @@ private:
|
||||
/// Handles mouse related events (click, motion, dragging).
|
||||
bool handleMouseButton( wxEvent& aEvent, int aIndex, bool aMotion );
|
||||
|
||||
/// Processes any pending mouse clicks that have been physically completed but not yet
|
||||
/// dispatched. This ensures clicks are processed before cancel events when both happen
|
||||
/// in quick succession.
|
||||
void flushPendingClicks();
|
||||
|
||||
/// Returns the instance of VIEW, used by the application.
|
||||
KIGFX::VIEW* getView();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user