From 73eda91ec739fe5cf893f7a1dbe56c58292c4604 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Sat, 2 May 2020 14:36:29 +0100 Subject: [PATCH] Allow some events to run behind a modal dialog. Right now this is just unit switching. Fixes https://gitlab.com/kicad/code/kicad/issues/2344 --- common/dialog_shim.cpp | 14 +++++++++-- common/eda_draw_frame.cpp | 10 ++++++++ common/tool/action_manager.cpp | 27 +++++++++++++-------- common/tool/tool_dispatcher.cpp | 8 +++++- common/tool/tool_manager.cpp | 43 +++++++-------------------------- include/dialog_shim.h | 2 ++ include/eda_base_frame.h | 2 ++ include/eda_draw_frame.h | 2 ++ include/tool/action_manager.h | 3 ++- include/tool/tool_dispatcher.h | 11 +++++++++ include/tool/tool_manager.h | 40 ++++++++++-------------------- 11 files changed, 87 insertions(+), 75 deletions(-) diff --git a/common/dialog_shim.cpp b/common/dialog_shim.cpp index 8eba14f6c6..bc2fc06913 100644 --- a/common/dialog_shim.cpp +++ b/common/dialog_shim.cpp @@ -74,7 +74,8 @@ DIALOG_SHIM::DIALOG_SHIM( wxWindow* aParent, wxWindowID id, const wxString& titl m_initialFocusTarget( nullptr ), m_qmodal_loop( nullptr ), m_qmodal_showing( false ), - m_qmodal_parent_disabler( nullptr ) + m_qmodal_parent_disabler( nullptr ), + m_parentFrame( nullptr ) { KIWAY_HOLDER* kiwayHolder = nullptr; @@ -98,7 +99,8 @@ DIALOG_SHIM::DIALOG_SHIM( wxWindow* aParent, wxWindowID id, const wxString& titl // Don't mouse-warp after a dialog run from the context menu if( kiwayHolder && kiwayHolder->GetType() == KIWAY_HOLDER::FRAME ) { - TOOL_MANAGER* toolMgr = static_cast( kiwayHolder )->GetToolManager(); + m_parentFrame = static_cast( kiwayHolder ); + TOOL_MANAGER* toolMgr = m_parentFrame->GetToolManager(); if( toolMgr && toolMgr->IsContextMenuActive() ) toolMgr->VetoContextMenuMouseWarp(); @@ -509,6 +511,14 @@ void DIALOG_SHIM::OnButton( wxCommandEvent& aEvent ) void DIALOG_SHIM::OnCharHook( wxKeyEvent& aEvt ) { + if( m_parentFrame ) + { + m_parentFrame->DispatchBehindModalDialog( aEvt ); + + if( !aEvt.GetSkipped() ) + return; + } + // shift-return (Mac default) or Ctrl-Return (GTK) for OK if( aEvt.GetKeyCode() == WXK_RETURN && ( aEvt.ShiftDown() || aEvt.ControlDown() ) ) { diff --git a/common/eda_draw_frame.cpp b/common/eda_draw_frame.cpp index a6b3633591..071d488112 100644 --- a/common/eda_draw_frame.cpp +++ b/common/eda_draw_frame.cpp @@ -193,6 +193,16 @@ void EDA_DRAW_FRAME::unitsChangeRefresh() } +void EDA_DRAW_FRAME::DispatchBehindModalDialog( wxKeyEvent& aEvent ) +{ + static std::set whiteList = { &ACTIONS::toggleUnits, + &ACTIONS::imperialUnits, + &ACTIONS::metricUnits }; + + m_toolDispatcher->DispatchWxEvent( aEvent, &whiteList ); +} + + void EDA_DRAW_FRAME::CommonSettingsChanged( bool aEnvVarsChanged ) { EDA_BASE_FRAME::CommonSettingsChanged( aEnvVarsChanged ); diff --git a/common/tool/action_manager.cpp b/common/tool/action_manager.cpp index 4049f7fea8..34b7d15097 100644 --- a/common/tool/action_manager.cpp +++ b/common/tool/action_manager.cpp @@ -85,7 +85,7 @@ TOOL_ACTION* ACTION_MANAGER::FindAction( const std::string& aActionName ) const } -bool ACTION_MANAGER::RunHotKey( int aHotKey ) const +bool ACTION_MANAGER::RunHotKey( int aHotKey, std::set* aWhiteList ) const { int key = aHotKey & ~MD_MODIFIER_MASK; int mod = aHotKey & MD_MODIFIER_MASK; @@ -94,7 +94,7 @@ bool ACTION_MANAGER::RunHotKey( int aHotKey ) const key = std::toupper( key ); wxLogTrace( kicadTraceToolStack, "ACTION_MANAGER::RunHotKey Key: %s", - KeyNameFromKeyCode( aHotKey ) ); + KeyNameFromKeyCode( aHotKey ) ); HOTKEY_LIST::const_iterator it = m_actionHotKeys.find( key | mod ); @@ -105,8 +105,9 @@ bool ACTION_MANAGER::RunHotKey( int aHotKey ) const if( it == m_actionHotKeys.end() ) { wxLogTrace( kicadTraceToolStack, - "ACTION_MANAGER::RunHotKey No actions found, searching with key: %s", - KeyNameFromKeyCode( key | ( mod & ~MD_SHIFT ) ) ); + "ACTION_MANAGER::RunHotKey No actions found, searching with key: %s", + KeyNameFromKeyCode( key | ( mod & ~MD_SHIFT ) ) ); + it = m_actionHotKeys.find( key | ( mod & ~MD_SHIFT ) ); if( it == m_actionHotKeys.end() ) @@ -124,6 +125,9 @@ bool ACTION_MANAGER::RunHotKey( int aHotKey ) const for( const TOOL_ACTION* action : actions ) { + if( aWhiteList && !aWhiteList->count( action ) ) + continue; + if( action->GetScope() == AS_GLOBAL ) { // Store the global action in case there are no context actions to run @@ -150,8 +154,9 @@ bool ACTION_MANAGER::RunHotKey( int aHotKey ) const if( context ) { wxLogTrace( kicadTraceToolStack, - "ACTION_MANAGER::RunHotKey Running context action %s for hotkey %s", context->GetName(), - KeyNameFromKeyCode( aHotKey ) ); + "ACTION_MANAGER::RunHotKey Running context action %s for hotkey %s", + context->GetName(), + KeyNameFromKeyCode( aHotKey ) ); return m_toolMgr->RunAction( *context, true ); } @@ -160,16 +165,18 @@ bool ACTION_MANAGER::RunHotKey( int aHotKey ) const for( auto act : global ) { wxLogTrace( kicadTraceToolStack, - "ACTION_MANAGER::RunHotKey Running global action: %s for hotkey %s", act->GetName(), - KeyNameFromKeyCode( aHotKey ) ); + "ACTION_MANAGER::RunHotKey Running global action: %s for hotkey %s", + act->GetName(), + KeyNameFromKeyCode( aHotKey ) ); if( m_toolMgr->RunAction( *act, true ) ) return true; } } - wxLogTrace( kicadTraceToolStack, "ACTION_MANAGER::RunHotKey No action found for key %s", - KeyNameFromKeyCode( aHotKey ) ); + wxLogTrace( kicadTraceToolStack, + "ACTION_MANAGER::RunHotKey No action found for key %s", + KeyNameFromKeyCode( aHotKey ) ); return false; } diff --git a/common/tool/tool_dispatcher.cpp b/common/tool/tool_dispatcher.cpp index 675e10edd1..f75f9630e4 100644 --- a/common/tool/tool_dispatcher.cpp +++ b/common/tool/tool_dispatcher.cpp @@ -326,6 +326,12 @@ int translateSpecialCode( int aKeyCode ) void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent ) +{ + DispatchWxEvent( aEvent, nullptr ); +} + + +void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent, std::set* aWhiteList ) { bool motion = false; bool buttonEvents = false; @@ -523,7 +529,7 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent ) { wxLogTrace( kicadTraceToolStack, "TOOL_DISPATCHER::DispatchWxEvent %s", evt->Format() ); - handled = m_toolMgr->ProcessEvent( *evt ); + handled = m_toolMgr->ProcessEvent( *evt, aWhiteList ); // ESC is the special key for canceling tools, and is therefore seen as handled if( key == WXK_ESCAPE ) diff --git a/common/tool/tool_manager.cpp b/common/tool/tool_manager.cpp index 2f101b21b1..a1984ca1ae 100644 --- a/common/tool/tool_manager.cpp +++ b/common/tool/tool_manager.cpp @@ -377,34 +377,6 @@ bool TOOL_MANAGER::invokeTool( TOOL_BASE* aTool ) } -bool TOOL_MANAGER::runTool( TOOL_ID aToolId ) -{ - TOOL_BASE* tool = FindTool( aToolId ); - - if( tool && tool->GetType() == INTERACTIVE ) - return runTool( tool ); - - wxLogTrace( kicadTraceToolStack, - "TOOL_MANAGER::runTool - No interactive tool with ID %d", aToolId ); - - return false; // there is no tool with the given id -} - - -bool TOOL_MANAGER::runTool( const std::string& aToolName ) -{ - TOOL_BASE* tool = FindTool( aToolName ); - - if( tool && tool->GetType() == INTERACTIVE ) - return runTool( tool ); - - wxLogTrace( kicadTraceToolStack, - "TOOL_MANAGER::runTool - No interactive tool with name %s", aToolName ); - - return false; // there is no tool with the given name -} - - bool TOOL_MANAGER::runTool( TOOL_BASE* aTool ) { wxASSERT( aTool != NULL ); @@ -795,10 +767,11 @@ bool TOOL_MANAGER::dispatchInternal( const TOOL_EVENT& aEvent ) } -bool TOOL_MANAGER::dispatchHotKey( const TOOL_EVENT& aEvent ) +bool TOOL_MANAGER::dispatchHotKey( const TOOL_EVENT& aEvent, + std::set* aWhiteList ) { if( aEvent.Action() == TA_KEY_PRESSED ) - return m_actionMgr->RunHotKey( aEvent.Modifier() | aEvent.KeyCode() ); + return m_actionMgr->RunHotKey( aEvent.Modifier() | aEvent.KeyCode(), aWhiteList ); return false; } @@ -952,9 +925,10 @@ TOOL_MANAGER::ID_LIST::iterator TOOL_MANAGER::finishTool( TOOL_STATE* aState ) } -bool TOOL_MANAGER::ProcessEvent( const TOOL_EVENT& aEvent ) +bool TOOL_MANAGER::ProcessEvent( const TOOL_EVENT& aEvent, + std::set* aWhiteList ) { - bool handled = processEvent( aEvent ); + bool handled = processEvent( aEvent, aWhiteList ); TOOL_STATE* activeTool = GetCurrentToolState(); @@ -1105,12 +1079,13 @@ void TOOL_MANAGER::applyViewControls( TOOL_STATE* aState ) } -bool TOOL_MANAGER::processEvent( const TOOL_EVENT& aEvent ) +bool TOOL_MANAGER::processEvent( const TOOL_EVENT& aEvent, + std::set* aWhiteList ) { wxLogTrace( kicadTraceToolStack, "TOOL_MANAGER::processEvent - %s", aEvent.Format() ); // First try to dispatch the action associated with the event if it is a key press event - bool handled = dispatchHotKey( aEvent ); + bool handled = dispatchHotKey( aEvent, aWhiteList ); if( !handled ) { diff --git a/include/dialog_shim.h b/include/dialog_shim.h index 300ab6f275..6bc13af044 100644 --- a/include/dialog_shim.h +++ b/include/dialog_shim.h @@ -207,6 +207,8 @@ protected: bool m_qmodal_showing; WDO_ENABLE_DISABLE* m_qmodal_parent_disabler; + EDA_BASE_FRAME* m_parentFrame; + std::vector m_tabOrder; private: diff --git a/include/eda_base_frame.h b/include/eda_base_frame.h index 35afc1e88c..0b3c477915 100644 --- a/include/eda_base_frame.h +++ b/include/eda_base_frame.h @@ -217,6 +217,8 @@ public: void ChangeUserUnits( EDA_UNITS aUnits ); + virtual void DispatchBehindModalDialog( wxKeyEvent& aEvent ) { } + SETTINGS_MANAGER* GetSettingsManager() const { return m_settingsManager; } virtual int GetSeverity( int aErrorCode ) const { return RPT_SEVERITY_UNDEFINED; } diff --git a/include/eda_draw_frame.h b/include/eda_draw_frame.h index cbf9fab050..9b917059ce 100644 --- a/include/eda_draw_frame.h +++ b/include/eda_draw_frame.h @@ -122,6 +122,8 @@ protected: void unitsChangeRefresh() override; + void DispatchBehindModalDialog( wxKeyEvent& aEvent ) override; + void CommonSettingsChanged( bool aEnvVarsChanged ) override; /** diff --git a/include/tool/action_manager.h b/include/tool/action_manager.h index e82d243aa4..bf64bd3961 100644 --- a/include/tool/action_manager.h +++ b/include/tool/action_manager.h @@ -28,6 +28,7 @@ #include #include #include +#include class TOOL_BASE; class TOOL_MANAGER; @@ -86,7 +87,7 @@ public: * @param aHotKey is the hotkey to be handled. * @return True if there was an action associated with the hotkey, false otherwise. */ - bool RunHotKey( int aHotKey ) const; + bool RunHotKey( int aHotKey, std::set* aWhiteList ) const; /** * Function GetHotKey() diff --git a/include/tool/tool_dispatcher.h b/include/tool/tool_dispatcher.h index 582b898cf8..da56a1292e 100644 --- a/include/tool/tool_dispatcher.h +++ b/include/tool/tool_dispatcher.h @@ -72,9 +72,20 @@ public: * Processes wxEvents (mostly UI events), translates them to TOOL_EVENTs, and makes tools * handle those. * @param aEvent is the wxWidgets event to be processed. + * @param aWhiteList an optional list of allowed TOOL_ACTIONs */ virtual void DispatchWxEvent( wxEvent& aEvent ); + /** + * Function DispatchWxEvent() + * Processes wxEvents (mostly UI events), translates them to TOOL_EVENTs, and makes tools + * handle those. + * @param aEvent is the wxWidgets event to be processed. + * @param aWhiteList a list of allowable TOOL_ACTIONs. Those not appearing on the list + * will not be dispatched. + */ + virtual void DispatchWxEvent( wxEvent& aEvent, std::set* aWhiteList ); + /** * Function DispatchWxCommand() * Processes wxCommands (mostly menu related events) and runs appropriate actions (eg. run the diff --git a/include/tool/tool_manager.h b/include/tool/tool_manager.h index 1349c58d0c..8e7afcfec4 100644 --- a/include/tool/tool_manager.h +++ b/include/tool/tool_manager.h @@ -256,9 +256,11 @@ public: /** * Propagates an event to tools that requested events of matching type(s). * @param aEvent is the event to be processed. + * @param aWhiteList an optional list of allowed TOOL_ACTIONs * @return true if the event is a managed hotkey */ - bool ProcessEvent( const TOOL_EVENT& aEvent ); + bool ProcessEvent( const TOOL_EVENT& aEvent, + std::set* aWhiteList = nullptr ); /** * Puts an event to the event queue to be processed at the end of event processing cycle. @@ -429,12 +431,13 @@ private: bool dispatchInternal( const TOOL_EVENT& aEvent ); /** - * Function dispatchStandardEvents() + * Function dispatchHotKey() * Handles specific events, that are intended for TOOL_MANAGER rather than tools. * @param aEvent is the event to be processed. * @return true if the event was processed and should not go any further. */ - bool dispatchHotKey( const TOOL_EVENT& aEvent ); + bool dispatchHotKey( const TOOL_EVENT& aEvent, + std::set* aWhiteList = nullptr ); /** * Function dispatchActivation() @@ -452,24 +455,6 @@ private: */ bool invokeTool( TOOL_BASE* aTool ); - /** - * Function runTool() - * Makes a tool active, so it can receive events and react to them. Activated tool is pushed - * on the active tools stack, so the last activated tool receives events first. - * - * @param aToolId is the ID number of tool to be run. - */ - bool runTool( TOOL_ID aToolId ); - - /** - * Function runTool() - * Makes a tool active, so it can receive events and react to them. Activated tool is pushed - * on the active tools stack, so the last activated tool receives events first. - * - * @param aName is the name of tool to be run. - */ - bool runTool( const std::string& aName ); - /** * Function runTool() * Makes a tool active, so it can receive events and react to them. Activated tool is pushed @@ -479,9 +464,6 @@ private: */ bool runTool( TOOL_BASE* aTool ); - template - void invokeTool( const std::string& aName, const Parameters& aToolParams ); - /** * Function finishTool() * Deactivates a tool and does the necessary clean up. @@ -526,9 +508,13 @@ private: */ void applyViewControls( TOOL_STATE* aState ); - ///> Main function for event processing. - ///> @return true if a hotkey was handled - bool processEvent( const TOOL_EVENT& aEvent ); + /** + * Main function for event processing. + * @param aWhiteList an optional list of allowed TOOL_ACTIONs + * @return true if a hotkey was handled + */ + bool processEvent( const TOOL_EVENT& aEvent, + std::set* aWhiteList = nullptr ); /** * Saves the previous active state and sets a new one.