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
This commit is contained in:
Maciej Suminski 2018-01-26 15:53:28 +01:00
parent 3aafa2b574
commit b8ecc95d9c
3 changed files with 21 additions and 9 deletions

View File

@ -510,20 +510,24 @@ OPT<TOOL_EVENT> TOOL_MANAGER::ScheduleWait( TOOL_BASE* aTool,
void TOOL_MANAGER::dispatchInternal( const TOOL_EVENT& aEvent ) 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 // iterate over all registered tools
for( auto it = m_activeTools.begin(); it != m_activeTools.end(); ++it ) for( auto it = m_activeTools.begin(); it != m_activeTools.end(); ++it )
{ {
TOOL_STATE* st = m_toolIdIndex[*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) // the tool state handler is waiting for events (i.e. called Wait() method)
if( st->pendingWait ) if( st->pendingWait )
{ {
if( st->waitEvents.Matches( aEvent ) ) 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 ); m_passEvent = ( aEvent.Category() == TC_MESSAGE );
// got matching event? clear wait list and wake up the coroutine // 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 ) if( finished )
break; // only the first tool gets the event 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 // Run update handlers on the created copy
menu->UpdateAll(); menu->UpdateAll();
m_menuOwner = toolId;
m_menuActive = true; m_menuActive = true;
auto frame = dynamic_cast<wxFrame*>( m_editFrame ); auto frame = dynamic_cast<wxFrame*>( m_editFrame );
@ -677,8 +680,6 @@ void TOOL_MANAGER::dispatchContextMenu( const TOOL_EVENT& aEvent )
frame->PopupMenu( menu.get() ); frame->PopupMenu( menu.get() );
} }
m_menuActive = false;
// Warp the cursor as long as the menu wasn't clicked out of // Warp the cursor as long as the menu wasn't clicked out of
if( menu->GetSelected() >= 0 ) if( menu->GetSelected() >= 0 )
m_viewControls->WarpCursor( cursor, true, false ); m_viewControls->WarpCursor( cursor, true, false );
@ -695,6 +696,9 @@ void TOOL_MANAGER::dispatchContextMenu( const TOOL_EVENT& aEvent )
evt.SetParameter( m ); evt.SetParameter( m );
dispatchInternal( evt ); dispatchInternal( evt );
m_menuActive = false;
m_menuOwner = -1;
// Restore the cursor settings if the tool is still active // Restore the cursor settings if the tool is still active
if( activeTool == GetCurrentToolId() ) if( activeTool == GetCurrentToolId() )
{ {

View File

@ -307,6 +307,11 @@ public:
return m_actions & ( TA_UNDO_REDO_PRE | TA_UNDO_REDO_POST ); 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.) ///> Returns information about key modifiers state (Ctrl, Alt, etc.)
int Modifier( int aMask = MD_MODIFIER_MASK ) const int Modifier( int aMask = MD_MODIFIER_MASK ) const
{ {

View File

@ -515,8 +515,11 @@ private:
/// Flag saying if the currently processed event should be passed to other tools. /// Flag saying if the currently processed event should be passed to other tools.
bool m_passEvent; bool m_passEvent;
/// Flag indicating whether a context menu is currently displayed /// Flag indicating whether a context menu is currently displayed.
bool m_menuActive; bool m_menuActive;
/// Tool currently displaying a popup menu. It is negative when there is no menu displayed.
TOOL_ID m_menuOwner;
}; };
#endif #endif