Avoid stealing focus from text controls when hovering over canvas

Fix #4879
Fix #4888
This commit is contained in:
Marek Roszko 2020-11-04 21:06:36 -05:00
parent ded0aaceda
commit 262bb06d91
5 changed files with 53 additions and 11 deletions

View File

@ -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

View File

@ -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<wxWindow*>( 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<wxWindow*>( 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 )

View File

@ -35,6 +35,7 @@
#include <trace_helpers.h>
#include <settings/common_settings.h>
#include <math/util.h> // for KiROUND
#include <widgets/ui_common.h>
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

View File

@ -18,6 +18,8 @@
*/
#include <wx/wx.h>
#include <wx/dataview.h>
#include <wx/stc/stc.h>
#include <widgets/ui_common.h>
#include <algorithm>
@ -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<wxTextEntry*>( focus );
wxStyledTextCtrl* styledText = dynamic_cast<wxStyledTextCtrl*>( focus );
wxListBox* listBox = dynamic_cast<wxListBox*>( focus );
wxDataViewCtrl* dataViewCtrl = dynamic_cast<wxDataViewCtrl*>( focus );
return ( textEntry || styledText || listBox || dataViewCtrl );
}

View File

@ -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,