Fix event blocker on GTK

We block events when a modal window is active.  But detecting when the
modal window is closed is harder on GTK than just counting modal closes
because the modal flag can sometimes be unset before the wxEVT_SHOW
event fires.  Instead, we track the stack of modal windows opened and
close the window and subsequent windows when the object pointer matches

Fixes https://gitlab.com/kicad/code/kicad/issues/13372
This commit is contained in:
Seth Hillbrand 2023-01-12 11:51:02 -08:00
parent cbfbd3a0de
commit fa91d906d0
6 changed files with 61 additions and 10 deletions

View File

@ -123,7 +123,6 @@ PGM_BASE::PGM_BASE()
m_locale = nullptr;
m_Printing = false;
m_Quitting = false;
m_ModalDialogCount = 0;
m_argcUtf8 = 0;
m_argvUtf8 = nullptr;

View File

@ -215,8 +215,25 @@ struct APP_SINGLE_TOP : public wxApp
wxShowEvent& event = static_cast<wxShowEvent&>( aEvent );
wxDialog* dialog = dynamic_cast<wxDialog*>( event.GetEventObject() );
if( dialog && dialog->IsModal() )
Pgm().m_ModalDialogCount += event.IsShown() ? 1 : -1;
std::vector<void*>& dlgs = Pgm().m_ModalDialogs;
if( dialog )
{
if( event.IsShown() && dialog->IsModal() )
{
dlgs.push_back( dialog );
}
// Under GTK, sometimes the modal flag is cleared before hiding
else if( !event.IsShown() )
{
// If we close the expected dialog, remove it from our stack
if( dlgs.back() == dialog )
dlgs.pop_back();
// If an out-of-order, remove all dialogs added after the closed one
else if( auto it = std::find( dlgs.begin(), dlgs.end(), dialog ) ; it != dlgs.end() )
dlgs.erase( it, dlgs.end() );
}
}
}
return Event_Skip;

View File

@ -314,7 +314,7 @@ bool KIUI::IsInputControlEditable( wxWindow* aFocus )
bool KIUI::IsModalDialogFocused()
{
return Pgm().m_ModalDialogCount > 0;
return !Pgm().m_ModalDialogs.empty();
}

View File

@ -32,6 +32,7 @@
#define PGM_BASE_H_
#include <map>
#include <vector>
#include <memory>
#include <search_stack.h>
#include <settings/environment.h>
@ -302,7 +303,7 @@ public:
*/
bool m_Printing;
int m_ModalDialogCount;
std::vector<void*> m_ModalDialogs;
bool m_Quitting;

View File

@ -476,8 +476,25 @@ struct APP_KICAD : public wxApp
wxShowEvent& event = static_cast<wxShowEvent&>( aEvent );
wxDialog* dialog = dynamic_cast<wxDialog*>( event.GetEventObject() );
if( dialog && dialog->IsModal() )
Pgm().m_ModalDialogCount += event.IsShown() ? 1 : -1;
std::vector<void*>& dlgs = Pgm().m_ModalDialogs;
if( dialog )
{
if( event.IsShown() && dialog->IsModal() )
{
dlgs.push_back( dialog );
}
// Under GTK, sometimes the modal flag is cleared before hiding
else if( !event.IsShown() )
{
// If we close the expected dialog, remove it from our stack
if( dlgs.back() == dialog )
dlgs.pop_back();
// If an out-of-order, remove all dialogs added after the closed one
else if( auto it = std::find( dlgs.begin(), dlgs.end(), dialog ) ; it != dlgs.end() )
dlgs.erase( it, dlgs.end() );
}
}
}
return Event_Skip;

View File

@ -503,8 +503,25 @@ struct APP_KICAD_CLI : public wxAppConsole
wxShowEvent& event = static_cast<wxShowEvent&>( aEvent );
wxDialog* dialog = dynamic_cast<wxDialog*>( event.GetEventObject() );
if( dialog && dialog->IsModal() )
Pgm().m_ModalDialogCount += event.IsShown() ? 1 : -1;
std::vector<void*>& dlgs = Pgm().m_ModalDialogs;
if( dialog )
{
if( event.IsShown() && dialog->IsModal() )
{
dlgs.push_back( dialog );
}
// Under GTK, sometimes the modal flag is cleared before hiding
else if( !event.IsShown() )
{
// If we close the expected dialog, remove it from our stack
if( dlgs.back() == dialog )
dlgs.pop_back();
// If an out-of-order, remove all dialogs added after the closed one
else if( auto it = std::find( dlgs.begin(), dlgs.end(), dialog ) ; it != dlgs.end() )
dlgs.erase( it, dlgs.end() );
}
}
}
return Event_Skip;