diff --git a/common/eda_base_frame.cpp b/common/eda_base_frame.cpp index d62ace1655..a4ab27d7c0 100644 --- a/common/eda_base_frame.cpp +++ b/common/eda_base_frame.cpp @@ -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(); } diff --git a/common/tool/action_menu.cpp b/common/tool/action_menu.cpp index 4f41495775..7a6782a892 100644 --- a/common/tool/action_menu.cpp +++ b/common/tool/action_menu.cpp @@ -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(); diff --git a/include/tool/action_menu.h b/include/tool/action_menu.h index 9bd35bd5f5..e318b3cb65 100644 --- a/include/tool/action_menu.h +++ b/include/tool/action_menu.h @@ -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.