Once more into the depths of hell... er, I mean fix a focus issue.

So the new steals-focus protection stuff works well when there's a
focused control, but not as well when there's a modal dialog up which
happens not to have a focused control (or worse, a focusable control).

This adds a second mechanism for also checking to see if a modal dialog
is up (something that wxWidgets, true to form, makes very difficult).

Fixes https://gitlab.com/kicad/code/kicad/issues/6520
This commit is contained in:
Jeff Young 2020-11-26 15:43:48 +00:00
parent 2a87980d45
commit fc2bdc49de
11 changed files with 65 additions and 20 deletions

View File

@ -27,7 +27,6 @@
#include <kiway_player.h>
#include <pgm_base.h>
#include <tool/tool_manager.h>
#include <kiplatform/ui.h>
#include <wx/display.h>
@ -320,9 +319,9 @@ void DIALOG_SHIM::OnPaint( wxPaintEvent &event )
selectAllInTextCtrls( GetChildren() );
if( m_initialFocusTarget )
m_initialFocusTarget->SetFocus();
KIPLATFORM::UI::ForceFocus( m_initialFocusTarget );
else
SetFocus(); // Focus the dialog itself
KIPLATFORM::UI::ForceFocus( this ); // Focus the dialog itself
m_firstPaintEvent = false;
}

View File

@ -501,7 +501,9 @@ bool EDA_DRAW_PANEL_GAL::SwitchBackend( GAL_TYPE aGalType )
void EDA_DRAW_PANEL_GAL::OnEvent( wxEvent& aEvent )
{
bool shouldSetFocus = m_lostFocus && m_stealsFocus && !KIUI::IsInputControlFocused();
bool shouldSetFocus = m_lostFocus && m_stealsFocus
&& !KIUI::IsInputControlFocused()
&& !KIUI::IsModalDialogFocused();
#if defined( _WIN32 )
// Ensure we are the active foreground window before we attempt to steal focus
@ -523,7 +525,9 @@ void EDA_DRAW_PANEL_GAL::OnEvent( wxEvent& aEvent )
void EDA_DRAW_PANEL_GAL::onEnter( wxMouseEvent& aEvent )
{
bool shouldSetFocus = m_stealsFocus && !KIUI::IsInputControlFocused();
bool shouldSetFocus = m_stealsFocus
&& !KIUI::IsInputControlFocused()
&& !KIUI::IsModalDialogFocused();
#if defined( _WIN32 )
// Ensure we are the active foreground window before we attempt to steal focus

View File

@ -101,6 +101,7 @@ PGM_BASE::PGM_BASE()
m_pgm_checker = NULL;
m_locale = NULL;
m_Printing = false;
m_ModalDialogCount = 0;
m_show_env_var_dialog = true;

View File

@ -226,6 +226,19 @@ struct APP_SINGLE_TOP : public wxApp
return ret;
}
int FilterEvent( wxEvent& aEvent ) override
{
if( aEvent.GetEventType() == wxEVT_SHOW )
{
wxShowEvent& event = static_cast<wxShowEvent&>( aEvent );
wxDialog* dialog = dynamic_cast<wxDialog*>( event.GetEventObject() );
if( dialog && dialog->IsModal() )
Pgm().m_ModalDialogCount += event.IsShown() ? 1 : -1;
}
return Event_Skip;
}
#if defined( DEBUG )
/**

View File

@ -23,7 +23,8 @@
#include <widgets/ui_common.h>
#include <algorithm>
#include <gal/color4d.h>
#include <dialog_shim.h>
#include <pgm_base.h>
int KIUI::GetStdMargin()
{
@ -142,4 +143,10 @@ bool KIUI::IsInputControlFocused()
wxDataViewCtrl* dataViewCtrl = dynamic_cast<wxDataViewCtrl*>( focus );
return ( textEntry || styledText || listBox || dataViewCtrl );
}
bool KIUI::IsModalDialogFocused()
{
return Pgm().m_ModalDialogCount > 0;
}

View File

@ -159,6 +159,9 @@ void DIALOG_UPDATE_FROM_PCB::OnUpdateClick( wxCommandEvent& event )
if( m_cbRelinkFootprints->GetValue() )
backAnno.PushNewLinksToPCB();
m_sdbSizerCancel->SetDefault();
m_sdbSizerOK->Enable( false );
}
m_messagePanel->Flush( false );

View File

@ -340,6 +340,8 @@ public:
*/
bool m_Printing;
int m_ModalDialogCount;
protected:
/// Loads internal settings from COMMON_SETTINGS

View File

@ -74,6 +74,8 @@ void SelectReferenceNumber( wxTextEntry* aTextEntry );
*/
bool IsInputControlFocused();
bool IsModalDialogFocused();
}
// Note: On windows, SEVERITY_ERROR collides with a system declaration,

View File

@ -307,6 +307,20 @@ struct APP_KICAD : public wxApp
return -1;
}
int FilterEvent( wxEvent& aEvent ) override
{
if( aEvent.GetEventType() == wxEVT_SHOW )
{
wxShowEvent& event = static_cast<wxShowEvent&>( aEvent );
wxDialog* dialog = dynamic_cast<wxDialog*>( event.GetEventObject() );
if( dialog && dialog->IsModal() )
Pgm().m_ModalDialogCount += event.IsShown() ? 1 : -1;
}
return Event_Skip;
}
/**
* Set MacOS file associations.
*

View File

@ -142,30 +142,24 @@ void DIALOG_NETLIST::OnOpenNetlistClick( wxCommandEvent& event )
void DIALOG_NETLIST::OnUpdatePCB( wxCommandEvent& event )
{
BOARD* pcb = m_parent->GetBoard();
wxFileName fn = m_NetlistFilenameCtrl->GetValue();
if( !fn.IsOk() )
{
wxMessageBox( _("Please, choose a valid netlist file.") );
wxMessageBox( _( "Please, choose a valid netlist file." ) );
return;
}
if( !fn.FileExists() )
{
wxMessageBox( _("The netlist file does not exist.") );
wxMessageBox( _( "The netlist file does not exist." ) );
return;
}
// Give the user a chance to bail out when making changes from a netlist.
if( pcb->IsEmpty() || IsOK( this, _( "The changes made cannot be undone. "
"Are you sure you want to update the PCB?" ) ) )
{
m_MessageWindow->SetLabel( _( "Changes Applied To PCB" ) );
loadNetlist( false );
m_MessageWindow->SetLabel( _( "Changes Applied to PCB" ) );
loadNetlist( false );
m_sdbSizer1Cancel->SetDefault();
}
m_sdbSizer1Cancel->SetDefault();
}

View File

@ -24,7 +24,6 @@
#include <pcb_edit_frame.h>
#include <pcbnew_settings.h>
#include <dialog_update_pcb.h>
#include <ratsnest/ratsnest_data.h>
#include <wx_html_report_panel.h>
#include <netlist_reader/pcb_netlist.h>
@ -33,7 +32,7 @@
#include <tools/pcb_actions.h>
#include <tools/selection_tool.h>
#include <kiface_i.h>
#include <kiplatform/ui.h>
bool DIALOG_UPDATE_PCB::m_warnForNoNetPads = false;
@ -129,13 +128,20 @@ void DIALOG_UPDATE_PCB::PerformUpdate( bool aDryRun )
void DIALOG_UPDATE_PCB::OnOptionChanged( wxCommandEvent& event )
{
if( m_initialized )
{
PerformUpdate( true );
m_sdbSizer1OK->Enable( true );
m_sdbSizer1OK->SetDefault();
}
}
void DIALOG_UPDATE_PCB::OnUpdateClick( wxCommandEvent& event )
{
m_messagePanel->SetLabel( _( "Changes Applied To PCB" ) );
m_messagePanel->SetLabel( _( "Changes Applied to PCB" ) );
PerformUpdate( false );
m_sdbSizer1Cancel->SetDefault();
// Widgets has a tendency to keep both buttons highlighted without the following:
m_sdbSizer1OK->Enable( false );
}