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
This commit is contained in:
Marek Roszko 2020-10-16 22:54:36 -04:00
parent a3172d643f
commit 2d25d37112
3 changed files with 34 additions and 14 deletions

View File

@ -76,7 +76,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 );
const wxEventType events[] =
@ -132,15 +132,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;
}
@ -457,7 +448,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 )
@ -469,10 +468,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();

View File

@ -273,7 +273,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
}

View File

@ -253,7 +253,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 );