From c372a77d6c753d4de3675bc71962e09f830e9a62 Mon Sep 17 00:00:00 2001 From: Marek Roszko Date: Fri, 16 Oct 2020 22:54:36 -0400 Subject: [PATCH] Fix focus theft, Windows sends mouse events to windows regardless of focus. We need to check if the window is foreground before fight over focus which will make the window foreground if it wasn't. Fixes #4099 Fixes #5958 --- common/draw_panel_gal.cpp | 33 +++++++++++++++++++------------- common/view/wx_view_controls.cpp | 13 +++++++++++++ include/class_draw_panel_gal.h | 2 +- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/common/draw_panel_gal.cpp b/common/draw_panel_gal.cpp index 120703fa30..51630f55ff 100644 --- a/common/draw_panel_gal.cpp +++ b/common/draw_panel_gal.cpp @@ -94,7 +94,7 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin EnableScrolling( false, false ); // otherwise Zoom Auto disables GAL canvas Connect( wxEVT_SIZE, wxSizeEventHandler( EDA_DRAW_PANEL_GAL::onSize ), NULL, this ); - Connect( wxEVT_ENTER_WINDOW, wxEventHandler( EDA_DRAW_PANEL_GAL::onEnter ), NULL, this ); + Connect( wxEVT_ENTER_WINDOW, wxMouseEventHandler( EDA_DRAW_PANEL_GAL::onEnter ), NULL, this ); Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( EDA_DRAW_PANEL_GAL::onLostFocus ), NULL, this ); Connect( wxEVT_SET_CURSOR, wxSetCursorEventHandler( EDA_DRAW_PANEL_GAL::onSetCursor ), NULL, this ); @@ -148,15 +148,6 @@ EDA_DRAW_PANEL_GAL::~EDA_DRAW_PANEL_GAL() void EDA_DRAW_PANEL_GAL::SetFocus() { -// Windows has a strange manner on bringing up and activating windows -// containing a GAL canvas just after moving the mouse cursor into its area. -// Feel free to uncomment or extend the following #ifdef if you experience -// similar problems on your platform. -#ifdef __WINDOWS__ - if( !GetParent()->IsDescendant( wxWindow::FindFocus() ) ) - return; -#endif - wxScrolledCanvas::SetFocus(); m_lostFocus = false; } @@ -506,7 +497,15 @@ bool EDA_DRAW_PANEL_GAL::SwitchBackend( GAL_TYPE aGalType ) void EDA_DRAW_PANEL_GAL::OnEvent( wxEvent& aEvent ) { - if( m_lostFocus && m_stealsFocus ) + bool shouldSetFocus = m_lostFocus && m_stealsFocus; + +#if defined( _WIN32 ) + // Ensure we are the active foreground window before we attempt to steal focus + // mouse events are generated on Win32 regardless if window is active + shouldSetFocus = shouldSetFocus && ( m_edaFrame->GetHWND() == GetForegroundWindow() ); +#endif + + if( shouldSetFocus ) SetFocus(); if( !m_eventDispatcher ) @@ -518,10 +517,18 @@ void EDA_DRAW_PANEL_GAL::OnEvent( wxEvent& aEvent ) } -void EDA_DRAW_PANEL_GAL::onEnter( wxEvent& aEvent ) +void EDA_DRAW_PANEL_GAL::onEnter( wxMouseEvent& aEvent ) { + bool shouldSetFocus = m_stealsFocus; + +#if defined( _WIN32 ) + // Ensure we are the active foreground window before we attempt to steal focus + // mouse events are generated on Win32 regardless if window is active + shouldSetFocus = shouldSetFocus && ( m_edaFrame->GetHWND() == GetForegroundWindow() ); +#endif + // Getting focus is necessary in order to receive key events properly - if( m_stealsFocus ) + if( shouldSetFocus ) SetFocus(); aEvent.Skip(); diff --git a/common/view/wx_view_controls.cpp b/common/view/wx_view_controls.cpp index 165488401d..9959f61d9e 100644 --- a/common/view/wx_view_controls.cpp +++ b/common/view/wx_view_controls.cpp @@ -331,7 +331,20 @@ void WX_VIEW_CONTROLS::onButton( wxMouseEvent& aEvent ) void WX_VIEW_CONTROLS::onEnter( wxMouseEvent& aEvent ) { +#if defined( _WIN32 ) + // Win32 transmits mouse move and wheel events to all controls below the mouse regardless of focus + // Forcing the focus here will cause the EDA FRAMES to immediately become the top level active window + if( m_parentPanel->GetParent() != nullptr ) + { + // this assumes the parent panel's parent is the eda window + if( GetForegroundWindow() == m_parentPanel->GetParent()->GetHWND() ) + { + m_parentPanel->SetFocus(); + } + } +#else m_parentPanel->SetFocus(); +#endif } diff --git a/include/class_draw_panel_gal.h b/include/class_draw_panel_gal.h index d04363ac85..3bc0df6678 100644 --- a/include/class_draw_panel_gal.h +++ b/include/class_draw_panel_gal.h @@ -236,7 +236,7 @@ protected: virtual void onPaint( wxPaintEvent& WXUNUSED( aEvent ) ); void onSize( wxSizeEvent& aEvent ); - void onEnter( wxEvent& aEvent ); + void onEnter( wxMouseEvent& aEvent ); void onLostFocus( wxFocusEvent& aEvent ); void onRefreshTimer( wxTimerEvent& aEvent ); void onShowTimer( wxTimerEvent& aEvent );