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
This commit is contained in:
Jeff Young 2020-05-02 14:36:29 +01:00
parent 5acee1962e
commit 73eda91ec7
11 changed files with 87 additions and 75 deletions

View File

@ -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<EDA_BASE_FRAME*>( kiwayHolder )->GetToolManager();
m_parentFrame = static_cast<EDA_BASE_FRAME*>( 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() ) )
{

View File

@ -193,6 +193,16 @@ void EDA_DRAW_FRAME::unitsChangeRefresh()
}
void EDA_DRAW_FRAME::DispatchBehindModalDialog( wxKeyEvent& aEvent )
{
static std::set<const TOOL_ACTION*> whiteList = { &ACTIONS::toggleUnits,
&ACTIONS::imperialUnits,
&ACTIONS::metricUnits };
m_toolDispatcher->DispatchWxEvent( aEvent, &whiteList );
}
void EDA_DRAW_FRAME::CommonSettingsChanged( bool aEnvVarsChanged )
{
EDA_BASE_FRAME::CommonSettingsChanged( aEnvVarsChanged );

View File

@ -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<const TOOL_ACTION*>* 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;
}

View File

@ -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<const TOOL_ACTION*>* 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 )

View File

@ -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<const TOOL_ACTION*>* 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<const TOOL_ACTION*>* 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<const TOOL_ACTION*>* 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 )
{

View File

@ -207,6 +207,8 @@ protected:
bool m_qmodal_showing;
WDO_ENABLE_DISABLE* m_qmodal_parent_disabler;
EDA_BASE_FRAME* m_parentFrame;
std::vector<wxWindow*> m_tabOrder;
private:

View File

@ -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; }

View File

@ -122,6 +122,8 @@ protected:
void unitsChangeRefresh() override;
void DispatchBehindModalDialog( wxKeyEvent& aEvent ) override;
void CommonSettingsChanged( bool aEnvVarsChanged ) override;
/**

View File

@ -28,6 +28,7 @@
#include <list>
#include <map>
#include <string>
#include <set>
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<const TOOL_ACTION*>* aWhiteList ) const;
/**
* Function GetHotKey()

View File

@ -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<const TOOL_ACTION*>* aWhiteList );
/**
* Function DispatchWxCommand()
* Processes wxCommands (mostly menu related events) and runs appropriate actions (eg. run the

View File

@ -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<const TOOL_ACTION*>* 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<const TOOL_ACTION*>* 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 <class Parameters>
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<const TOOL_ACTION*>* aWhiteList = nullptr );
/**
* Saves the previous active state and sets a new one.