diff --git a/common/draw_panel_gal.cpp b/common/draw_panel_gal.cpp index 51630f55ff..6840f78818 100644 --- a/common/draw_panel_gal.cpp +++ b/common/draw_panel_gal.cpp @@ -497,7 +497,7 @@ bool EDA_DRAW_PANEL_GAL::SwitchBackend( GAL_TYPE aGalType ) void EDA_DRAW_PANEL_GAL::OnEvent( wxEvent& aEvent ) { - bool shouldSetFocus = m_lostFocus && m_stealsFocus; + bool shouldSetFocus = m_lostFocus && m_stealsFocus && !KIUI::IsInputControlFocused(); #if defined( _WIN32 ) // Ensure we are the active foreground window before we attempt to steal focus @@ -519,7 +519,7 @@ void EDA_DRAW_PANEL_GAL::OnEvent( wxEvent& aEvent ) void EDA_DRAW_PANEL_GAL::onEnter( wxMouseEvent& aEvent ) { - bool shouldSetFocus = m_stealsFocus; + bool shouldSetFocus = m_stealsFocus && !KIUI::IsInputControlFocused(); #if defined( _WIN32 ) // Ensure we are the active foreground window before we attempt to steal focus diff --git a/common/tool/tool_dispatcher.cpp b/common/tool/tool_dispatcher.cpp index 1aa1240ae5..c699b38faf 100644 --- a/common/tool/tool_dispatcher.cpp +++ b/common/tool/tool_dispatcher.cpp @@ -299,6 +299,16 @@ static bool isKeyModifierOnly( int aKeyCode ) return isInList; } + +static bool isMouseClick( wxEventType type ) +{ + return type == wxEVT_LEFT_DOWN || type == wxEVT_LEFT_UP || type == wxEVT_MIDDLE_DOWN + || type == wxEVT_MIDDLE_UP || type == wxEVT_RIGHT_DOWN || type == wxEVT_RIGHT_UP + || type == wxEVT_LEFT_DCLICK || type == wxEVT_MIDDLE_DCLICK + || type == wxEVT_RIGHT_DCLICK; +} + + /* A helper class that convert some special key codes to an equivalent. * WXK_NUMPAD_UP to WXK_UP, * WXK_NUMPAD_DOWN to WXK_DOWN, @@ -422,7 +432,9 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent ) // Or else we may stall them out entirely and never get them during actions like rapid mouse moves KIPLATFORM::APP::ForceTimerMessagesToBeCreatedIfNecessary(); - int type = aEvent.GetEventType(); + wxEventType type = aEvent.GetEventType(); + + wxWindow* holderWindow = dynamic_cast( m_toolMgr->GetToolHolder() ); // Sometimes there is no window that has the focus (it happens when another PCB_BASE_FRAME // is opened and is iconized on Windows). @@ -430,30 +442,32 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent ) // focus when iconized for some obscure reason) if( focus == nullptr ) { - wxWindow* window = dynamic_cast( m_toolMgr->GetToolHolder() ); #if defined( _WIN32 ) // Mouse events may trigger regardless of window status (windows feature) // However we need to avoid focus fighting (especially modals) - if( window && window->GetHWND() == GetForegroundWindow() ) + if( holderWindow && holderWindow->GetHWND() == GetForegroundWindow() ) #else - if( window ) + if( holderWindow ) #endif { - window->SetFocus(); + holderWindow->SetFocus(); } } + if( isMouseClick( type ) ) + { + if( holderWindow ) + holderWindow->SetFocus(); + } + // Mouse handling // Note: wxEVT_LEFT_DOWN event must always be skipped. if( type == wxEVT_MOTION || type == wxEVT_MOUSEWHEEL || #if wxCHECK_VERSION( 3, 1, 0 ) || defined( USE_OSX_MAGNIFY_EVENT ) type == wxEVT_MAGNIFY || #endif - type == wxEVT_LEFT_DOWN || type == wxEVT_LEFT_UP || - type == wxEVT_MIDDLE_DOWN || type == wxEVT_MIDDLE_UP || - type == wxEVT_RIGHT_DOWN || type == wxEVT_RIGHT_UP || - type == wxEVT_LEFT_DCLICK || type == wxEVT_MIDDLE_DCLICK || type == wxEVT_RIGHT_DCLICK || + isMouseClick( type ) || // Event issued when mouse retains position in screen coordinates, // but changes in world coordinates (e.g. autopanning) type == KIGFX::WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE ) diff --git a/common/view/wx_view_controls.cpp b/common/view/wx_view_controls.cpp index 9959f61d9e..3f902dba84 100644 --- a/common/view/wx_view_controls.cpp +++ b/common/view/wx_view_controls.cpp @@ -35,6 +35,7 @@ #include #include #include // for KiROUND +#include using namespace KIGFX; @@ -331,6 +332,14 @@ void WX_VIEW_CONTROLS::onButton( wxMouseEvent& aEvent ) void WX_VIEW_CONTROLS::onEnter( wxMouseEvent& aEvent ) { + // Avoid stealing focus from text controls + // This is particularly important for users using On-Screen-Keyboards + // They may move the mouse over the canvas to reach the keyboard + if( KIUI::IsInputControlFocused() ) + { + return; + } + #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 diff --git a/common/widgets/ui_common.cpp b/common/widgets/ui_common.cpp index b69ed7d50d..cf0e4e5f80 100644 --- a/common/widgets/ui_common.cpp +++ b/common/widgets/ui_common.cpp @@ -18,6 +18,8 @@ */ #include +#include +#include #include #include @@ -124,4 +126,16 @@ void KIUI::SelectReferenceNumber( wxTextEntry* aTextEntry ) if( num.IsEmpty() ) aTextEntry->SetSelection( -1, -1 ); } +} + + +bool KIUI::IsInputControlFocused() +{ + wxWindow* focus = wxWindow::FindFocus(); + wxTextEntry* textEntry = dynamic_cast( focus ); + wxStyledTextCtrl* styledText = dynamic_cast( focus ); + wxListBox* listBox = dynamic_cast( focus ); + wxDataViewCtrl* dataViewCtrl = dynamic_cast( focus ); + + return ( textEntry || styledText || listBox || dataViewCtrl ); } \ No newline at end of file diff --git a/include/widgets/ui_common.h b/include/widgets/ui_common.h index 87052b2929..24647fe204 100644 --- a/include/widgets/ui_common.h +++ b/include/widgets/ui_common.h @@ -69,6 +69,11 @@ bool EnsureTextCtrlWidth( wxTextCtrl* aCtrl, const wxString* aString = NULL ); */ void SelectReferenceNumber( wxTextEntry* aTextEntry ); +/** + * Checks if a input control has focus + */ +bool IsInputControlFocused(); + } // Note: On windows, SEVERITY_ERROR collides with a system declaration,