From f21faceb7463ac413ee6d875cf90629cc2d4e555 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Sun, 19 May 2019 21:59:28 +0100 Subject: [PATCH] A hack to work around wxWidgets failure to capture WX_MENU_OPEN events See the comments. It's not pretty, but it works. Fixes: lp:1829640 * https://bugs.launchpad.net/kicad/+bug/1829640 Fixes: lp:1829307 * https://bugs.launchpad.net/kicad/+bug/1829307 Fixes: lp:1594029 * https://bugs.launchpad.net/kicad/+bug/1594029 --- common/legacy_gal/eda_draw_frame.cpp | 37 ++++++++++++++++++++++++-- common/legacy_wx/eda_draw_frame.cpp | 39 +++++++++++++++++++++++----- common/tool/action_menu.cpp | 10 ++++--- include/tool/action_menu.h | 6 ++--- 4 files changed, 77 insertions(+), 15 deletions(-) diff --git a/common/legacy_gal/eda_draw_frame.cpp b/common/legacy_gal/eda_draw_frame.cpp index 0c398b79ea..90507c02b2 100644 --- a/common/legacy_gal/eda_draw_frame.cpp +++ b/common/legacy_gal/eda_draw_frame.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -79,7 +80,8 @@ static const wxString MaxUndoItemsEntry(wxT( "DevelMaxUndoItems" ) ); BEGIN_EVENT_TABLE( EDA_DRAW_FRAME, KIWAY_PLAYER ) EVT_CHAR_HOOK( EDA_DRAW_FRAME::OnCharHook ) - + EVT_MENU_OPEN( EDA_DRAW_FRAME::OnMenuOpen ) + EVT_MENU_HIGHLIGHT_ALL( EDA_DRAW_FRAME::OnMenuOpen ) EVT_MOUSEWHEEL( EDA_DRAW_FRAME::OnMouseEvent ) END_EVENT_TABLE() @@ -276,7 +278,38 @@ void EDA_DRAW_FRAME::OnActivate( wxActivateEvent& event ) void EDA_DRAW_FRAME::OnMenuOpen( wxMenuEvent& event ) { - // TODO Obsolete! + // 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 ) + + // 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 ) + { + currentMenu = dynamic_cast( event.GetMenu() ); + + if( currentMenu ) + currentMenu->OnMenuEvent( event ); + } + else if( event.GetEventType() == wxEVT_MENU_HIGHLIGHT ) + { + if( currentMenu ) + currentMenu->OnMenuEvent( event ); + } + else if( event.GetEventType() == wxEVT_MENU_CLOSE ) + { + currentMenu = nullptr; + } +//#endif + event.Skip(); } diff --git a/common/legacy_wx/eda_draw_frame.cpp b/common/legacy_wx/eda_draw_frame.cpp index 1bf083848d..10a94c8365 100644 --- a/common/legacy_wx/eda_draw_frame.cpp +++ b/common/legacy_wx/eda_draw_frame.cpp @@ -46,7 +46,6 @@ #include #include #include - #include #include #include @@ -55,8 +54,6 @@ #include #include #include - - #include #include #include @@ -65,7 +62,7 @@ #include #include #include - +#include #include #include #include @@ -105,6 +102,7 @@ BEGIN_EVENT_TABLE( EDA_DRAW_FRAME, KIWAY_PLAYER ) EVT_MOUSEWHEEL( EDA_DRAW_FRAME::OnMouseEvent ) EVT_MENU_OPEN( EDA_DRAW_FRAME::OnMenuOpen ) + EVT_MENU_HIGHLIGHT_ALL( EDA_DRAW_FRAME::OnMenuOpen ) EVT_ACTIVATE( EDA_DRAW_FRAME::OnActivate ) EVT_MENU_RANGE( ID_ZOOM_BEGIN, ID_ZOOM_END, EDA_DRAW_FRAME::OnZoom ) @@ -306,8 +304,37 @@ void EDA_DRAW_FRAME::OnActivate( wxActivateEvent& event ) void EDA_DRAW_FRAME::OnMenuOpen( wxMenuEvent& event ) { - if( m_canvas ) - m_canvas->SetCanStartBlock( -1 ); + // On wxWidgets 3.0.x Windows, EVT_MENU_OPEN ( and other EVT_MENU_xx) 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 ) + + // 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 ) + { + currentMenu = dynamic_cast( event.GetMenu() ); + + if( currentMenu ) + currentMenu->OnMenuEvent( event ); + } + else if( event.GetEventType() == wxEVT_MENU_HIGHLIGHT ) + { + if( currentMenu ) + currentMenu->OnMenuEvent( event ); + } + else if( event.GetEventType() == wxEVT_MENU_CLOSE ) + { + currentMenu = nullptr; + } +//#endif event.Skip(); } diff --git a/common/tool/action_menu.cpp b/common/tool/action_menu.cpp index 27e819e33e..a9af5e5d95 100644 --- a/common/tool/action_menu.cpp +++ b/common/tool/action_menu.cpp @@ -87,9 +87,11 @@ void ACTION_MENU::SetIcon( const BITMAP_OPAQUE* aIcon ) void ACTION_MENU::setupEvents() { - Connect( wxEVT_MENU_OPEN, wxMenuEventHandler( ACTION_MENU::onMenuEvent ), NULL, this ); - Connect( wxEVT_MENU_HIGHLIGHT, wxMenuEventHandler( ACTION_MENU::onMenuEvent ), NULL, this ); - Connect( wxEVT_COMMAND_MENU_SELECTED, wxMenuEventHandler( ACTION_MENU::onMenuEvent ), NULL, this ); +// See wxWidgets hack in EDA_DRAW_FRAME::OnMenuOpen(). +// Connect( wxEVT_MENU_OPEN, wxMenuEventHandler( ACTION_MENU::OnMenuEvent ), NULL, this ); +// Connect( wxEVT_MENU_HIGHLIGHT, wxMenuEventHandler( ACTION_MENU::OnMenuEvent ), NULL, this ); + + Connect( wxEVT_COMMAND_MENU_SELECTED, wxMenuEventHandler( ACTION_MENU::OnMenuEvent ), NULL, this ); } @@ -322,7 +324,7 @@ void ACTION_MENU::updateHotKeys() } -void ACTION_MENU::onMenuEvent( wxMenuEvent& aEvent ) +void ACTION_MENU::OnMenuEvent( wxMenuEvent& aEvent ) { OPT_TOOL_EVENT evt; wxString menuText; diff --git a/include/tool/action_menu.h b/include/tool/action_menu.h index 623e60dd21..82ac272ce6 100644 --- a/include/tool/action_menu.h +++ b/include/tool/action_menu.h @@ -144,6 +144,9 @@ public: ///> Menu requires updating before display. bool m_Dirty; + ///> The default menu event handler. + void OnMenuEvent( wxMenuEvent& aEvent ); + protected: ///> Returns an instance of this class. It has to be overridden in inheriting classes. virtual ACTION_MENU* create() const; @@ -190,9 +193,6 @@ protected: ///> Initializes handlers for events. void setupEvents(); - ///> The default menu event handler. - void onMenuEvent( wxMenuEvent& aEvent ); - ///> Updates hot key settings for TOOL_ACTIONs in this menu. void updateHotKeys();