From b8ecc95d9c0c4e8d0a1fc563c4c5b9b8826802f1 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 26 Jan 2018 15:53:28 +0100 Subject: [PATCH] Forward context menu events to the tool that created the menu It fixes the case when a tool sets up a menu and starts its event loop waiting exclusively for menu events. If none arrived, the tool was stuck in the loop forever. Fixes: lp:1744915 * https://bugs.launchpad.net/kicad/+bug/1744915 --- common/tool/tool_manager.cpp | 20 ++++++++++++-------- include/tool/tool_event.h | 5 +++++ include/tool/tool_manager.h | 5 ++++- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/common/tool/tool_manager.cpp b/common/tool/tool_manager.cpp index bfc6282009..e88cb8d302 100644 --- a/common/tool/tool_manager.cpp +++ b/common/tool/tool_manager.cpp @@ -510,20 +510,24 @@ OPT TOOL_MANAGER::ScheduleWait( TOOL_BASE* aTool, void TOOL_MANAGER::dispatchInternal( const TOOL_EVENT& aEvent ) { - // Save current settings before overwriting with the dispatched tool - auto vc_settings = m_viewControls->GetSettings(); - // iterate over all registered tools for( auto it = m_activeTools.begin(); it != m_activeTools.end(); ++it ) { TOOL_STATE* st = m_toolIdIndex[*it]; + // forward context menu events to the tool that created the menu + if( aEvent.IsMenu() ) + { + if( *it != m_menuOwner ) + continue; + } + // the tool state handler is waiting for events (i.e. called Wait() method) if( st->pendingWait ) { if( st->waitEvents.Matches( aEvent ) ) { - // By default, only messages are passed further + // By default only messages are passed further m_passEvent = ( aEvent.Category() == TC_MESSAGE ); // got matching event? clear wait list and wake up the coroutine @@ -594,8 +598,6 @@ void TOOL_MANAGER::dispatchInternal( const TOOL_EVENT& aEvent ) if( finished ) break; // only the first tool gets the event } - - m_viewControls->ApplySettings( vc_settings ); } @@ -668,6 +670,7 @@ void TOOL_MANAGER::dispatchContextMenu( const TOOL_EVENT& aEvent ) // Run update handlers on the created copy menu->UpdateAll(); + m_menuOwner = toolId; m_menuActive = true; auto frame = dynamic_cast( m_editFrame ); @@ -677,8 +680,6 @@ void TOOL_MANAGER::dispatchContextMenu( const TOOL_EVENT& aEvent ) frame->PopupMenu( menu.get() ); } - m_menuActive = false; - // Warp the cursor as long as the menu wasn't clicked out of if( menu->GetSelected() >= 0 ) m_viewControls->WarpCursor( cursor, true, false ); @@ -695,6 +696,9 @@ void TOOL_MANAGER::dispatchContextMenu( const TOOL_EVENT& aEvent ) evt.SetParameter( m ); dispatchInternal( evt ); + m_menuActive = false; + m_menuOwner = -1; + // Restore the cursor settings if the tool is still active if( activeTool == GetCurrentToolId() ) { diff --git a/include/tool/tool_event.h b/include/tool/tool_event.h index a2feeae9a3..adbd0d060f 100644 --- a/include/tool/tool_event.h +++ b/include/tool/tool_event.h @@ -307,6 +307,11 @@ public: return m_actions & ( TA_UNDO_REDO_PRE | TA_UNDO_REDO_POST ); } + bool IsMenu() const + { + return m_actions & TA_CONTEXT_MENU; + } + ///> Returns information about key modifiers state (Ctrl, Alt, etc.) int Modifier( int aMask = MD_MODIFIER_MASK ) const { diff --git a/include/tool/tool_manager.h b/include/tool/tool_manager.h index b87165db61..b7c89b0619 100644 --- a/include/tool/tool_manager.h +++ b/include/tool/tool_manager.h @@ -515,8 +515,11 @@ private: /// Flag saying if the currently processed event should be passed to other tools. bool m_passEvent; - /// Flag indicating whether a context menu is currently displayed + /// Flag indicating whether a context menu is currently displayed. bool m_menuActive; + + /// Tool currently displaying a popup menu. It is negative when there is no menu displayed. + TOOL_ID m_menuOwner; }; #endif