Possible fix for GTK bug differentiating hotkeys from menu picks.

Fixes: lp:1835672
* https://bugs.launchpad.net/kicad/+bug/1835672
This commit is contained in:
Jeff Young 2019-07-08 10:40:44 +01:00
parent 772dff7a01
commit 4852c91b42
3 changed files with 43 additions and 29 deletions

View File

@ -243,18 +243,20 @@ void EDA_BASE_FRAME::OnCharHook( wxKeyEvent& event )
void EDA_BASE_FRAME::OnMenuOpen( wxMenuEvent& event )
{
// On wxWidgets 3.0.x Windows, EVT_MENU_OPEN and EVT_MENU_HIGHLIGHT events are not
// captured by the ACTON_MENU menus. While it is fixed in wxWidgets 3.1.x, we still
// need a solution for the earlier verions.
//
// This could be made conditional, but for now I'm going to use the same strategy
// everywhere so it gets wider testing.
// Note that if the conditional compilation is reactivated, the Connect() lines in
// ACTION_MENU::setupEvents() will need to be re-enabled.
//#if defined( __WINDOWS__ ) && wxCHECK_VERSION( 3, 0, 0 ) && !wxCHECK_VERSION( 3, 1, 0 )
// wxWidgets has several issues that we have to work around:
//
// 1) wxWidgets 3.0.x Windows has a bug where wxEVT_MENU_OPEN and wxEVT_MENU_HIGHLIGHT
// events are not captured by the ACTON_MENU menus. So we forward them here.
// (FWIW, this one is fixed in wxWidgets 3.1.x.)
//
// 2) wxWidgets doesn't pass the menu pointer for wxEVT_MENU_HIGHLIGHT events. So we
// store the menu pointer from the wxEVT_MENU_OPEN call.
//
// 3) wxWidgets has no way to tell whether a command is from a menu selection or a
// hotkey. So we keep track of menu highlighting so we can differentiate.
//
// As if things weren't bad enough, wxWidgets doesn't pass the menu pointer when the
// event is a wxEVT_MENU_HIGHLIGHT, so we store the menu from the EVT_MENU_OPEN call.
static ACTION_MENU* currentMenu;
if( event.GetEventType() == wxEVT_MENU_OPEN )
@ -269,11 +271,13 @@ void EDA_BASE_FRAME::OnMenuOpen( wxMenuEvent& event )
if( currentMenu )
currentMenu->OnMenuEvent( event );
}
else // if( event.GetEventType() == wxEVT_MENU_CLOSE )
else if( event.GetEventType() == wxEVT_MENU_CLOSE )
{
if( currentMenu )
currentMenu->OnMenuEvent( event );
currentMenu = nullptr;
}
//#endif
event.Skip();
}

View File

@ -74,8 +74,10 @@ void ACTION_MENU::setupEvents()
// See wxWidgets hack in EDA_BASE_FRAME::OnMenuOpen().
// Connect( wxEVT_MENU_OPEN, wxMenuEventHandler( ACTION_MENU::OnMenuEvent ), NULL, this );
// Connect( wxEVT_MENU_HIGHLIGHT, wxMenuEventHandler( ACTION_MENU::OnMenuEvent ), NULL, this );
// Connect( wxEVT_MENU_CLOSE, wxMenuEventHandler( ACTION_MENU::OnMenuEvent ), NULL, this );
Connect( wxEVT_COMMAND_MENU_SELECTED, wxMenuEventHandler( ACTION_MENU::OnMenuEvent ), NULL, this );
Connect( wxEVT_IDLE, wxIdleEventHandler( ACTION_MENU::OnIdle ), NULL, this );
}
@ -326,33 +328,41 @@ void ACTION_MENU::updateHotKeys()
}
// wxWidgets doesn't tell us when a menu command was generated from a hotkey or from
// a menu selection. It's important to us because a hotkey can be an immediate action
// while the menu selection can not (as it has no associated position).
//
// We get around this by storing the last highlighted menuId. If it matches the command
// id then we know this is a menu selection. (You might think we could use the menuOpen
// menuClose events, but these are actually generated for hotkeys as well.)
static int g_last_menu_highlighted_id = 0;
void ACTION_MENU::OnIdle( wxIdleEvent& event )
{
g_last_menu_highlighted_id = 0;
}
void ACTION_MENU::OnMenuEvent( wxMenuEvent& aEvent )
{
// wxWidgets doesn't tell us when a menu command was generated from a hotkey or from
// a menu selection. It's important to us because a hotkey can be an immediate action
// while the menu selection can not (as it has no associated position).
//
// We get around this by storing the last highlighted menuId. If it matches the command
// id then we know this is a menu selection. (You might think we could use the menuOpen
// menuClose events, but these are actually generated for hotkeys as well.)
static int highlightId = 0;
OPT_TOOL_EVENT evt;
wxString menuText;
wxEventType type = aEvent.GetEventType();
wxString menuText;
wxEventType type = aEvent.GetEventType();
if( type == wxEVT_MENU_OPEN )
{
if( m_dirty && m_tool )
getToolManager()->RunAction( ACTIONS::updateMenu, true, this );
highlightId = 0;
aEvent.Skip();
g_last_menu_highlighted_id = 0;
}
else if( type == wxEVT_MENU_HIGHLIGHT )
{
highlightId = aEvent.GetId();
if( aEvent.GetId() > 0 )
g_last_menu_highlighted_id = aEvent.GetId();
evt = TOOL_EVENT( TC_COMMAND, TA_CHOICE_MENU_UPDATE, aEvent.GetId() );
}
else if( type == wxEVT_COMMAND_MENU_SELECTED )
@ -425,7 +435,7 @@ void ACTION_MENU::OnMenuEvent( wxMenuEvent& aEvent )
// clients that don't supply a tool will have to check GetSelected() themselves
if( evt && m_tool )
{
if( highlightId == aEvent.GetId() && !m_isContextMenu )
if( g_last_menu_highlighted_id == aEvent.GetId() && !m_isContextMenu )
evt->SetHasPosition( false );
//aEvent.StopPropagation();

View File

@ -147,8 +147,8 @@ public:
*/
ACTION_MENU* Clone() const;
///> The default menu event handler.
void OnMenuEvent( wxMenuEvent& aEvent );
void OnIdle( wxIdleEvent& event );
protected:
///> Returns an instance of this class. It has to be overridden in inheriting classes.