Fix the effective parent of wxGenericFindReplaceDialog

This dialog is non-modal and so using GetParentForModalDialog() for it
is not quite right, because this function checks that the candidate
parent window is visible, which may not be the case for a modeless
dialog parent, as the dialog isn't necessarily going to be shown
immediately, but may well be shown later, after showing its parent.

And not allowing to use the not yet shown parent was also inconsistent
with the native MSW version which didn't have any problem with this.

So fix this by adding new GetParentForModelessDialog() function and
using it for this modeless dialog instead. This required slightly
refactoring wxDialog code to allow reusing most of it between the old
GetParentForModalDialog() and the new function.
This commit is contained in:
Vadim Zeitlin
2021-08-23 17:53:03 +01:00
parent 8bbcf0af09
commit ce92055f3a
3 changed files with 47 additions and 13 deletions

View File

@@ -105,7 +105,10 @@ public:
// check whether it contains wxDIALOG_NO_PARENT bit.
//
// This function always returns a valid top level window or NULL.
wxWindow *GetParentForModalDialog(wxWindow *parent, long style) const;
wxWindow *GetParentForModalDialog(wxWindow *parent, long style) const
{
return DoGetParentForDialog(wxDIALOG_MODALITY_APP_MODAL, parent, style);
}
// This overload can only be used for already initialized windows, i.e. not
// from the ctor. It uses the current window parent and style.
@@ -114,6 +117,16 @@ public:
return GetParentForModalDialog(GetParent(), GetWindowStyle());
}
// This function is similar to GetParentForModalDialog() but should be used
// for modeless dialogs and skips the checks irrelevant for them (currently
// just the one checking that the candidate parent window is visible, as it
// is possible to create a modeless dialog before its parent is shown if it
// is only shown later, after showing the parent).
wxWindow *GetParentForModelessDialog(wxWindow *parent, long style) const
{
return DoGetParentForDialog(wxDIALOG_MODALITY_NONE, parent, style);
}
#if wxUSE_STATTEXT // && wxUSE_TEXTCTRL
// splits text up at newlines and places the lines into a vertical
// wxBoxSizer, with the given maximum width, lines will not be wrapped
@@ -243,9 +256,15 @@ protected:
static bool sm_layoutAdaptation;
private:
// helper of GetParentForModalDialog(): returns the passed in window if it
// can be used as our parent or NULL if it can't
wxWindow *CheckIfCanBeUsedAsParent(wxWindow *parent) const;
// Common implementation of GetParentFor{Modal,Modeless}Dialog().
wxWindow *DoGetParentForDialog(wxDialogModality modality,
wxWindow *parent,
long style) const;
// helper of DoGetParentForDialog(): returns the passed in window if it
// can be used as parent for this kind of dialog or NULL if it can't
wxWindow *CheckIfCanBeUsedAsParent(wxDialogModality modality,
wxWindow *parent) const;
// Helper of OnCharHook() and OnCloseWindow(): find the appropriate button
// for closing the dialog and send a click event for it.

View File

@@ -128,7 +128,9 @@ wxDialogBase::wxDialogBase()
SetExtraStyle(GetExtraStyle() | wxWS_EX_BLOCK_EVENTS);
}
wxWindow *wxDialogBase::CheckIfCanBeUsedAsParent(wxWindow *parent) const
wxWindow *
wxDialogBase::CheckIfCanBeUsedAsParent(wxDialogModality modality,
wxWindow *parent) const
{
if ( !parent )
return NULL;
@@ -148,10 +150,21 @@ wxWindow *wxDialogBase::CheckIfCanBeUsedAsParent(wxWindow *parent) const
return NULL;
}
if ( !parent->IsShownOnScreen() )
// This check is done for modal dialogs only because modeless dialogs can
// be created before their parent is shown and only shown later.
switch ( modality )
{
// using hidden parent won't work correctly neither
return NULL;
case wxDIALOG_MODALITY_NONE:
break;
case wxDIALOG_MODALITY_APP_MODAL:
case wxDIALOG_MODALITY_WINDOW_MODAL:
if ( !parent->IsShownOnScreen() )
{
// using hidden parent won't work correctly neither
return NULL;
}
break;
}
if ( parent == this )
@@ -165,7 +178,9 @@ wxWindow *wxDialogBase::CheckIfCanBeUsedAsParent(wxWindow *parent) const
}
wxWindow *
wxDialogBase::GetParentForModalDialog(wxWindow *parent, long style) const
wxDialogBase::DoGetParentForDialog(wxDialogModality modality,
wxWindow *parent,
long style) const
{
// creating a parent-less modal dialog will result (under e.g. wxGTK2)
// in an unfocused dialog, so try to find a valid parent for it unless we
@@ -175,16 +190,16 @@ wxDialogBase::GetParentForModalDialog(wxWindow *parent, long style) const
// first try the given parent
if ( parent )
parent = CheckIfCanBeUsedAsParent(wxGetTopLevelParent(parent));
parent = CheckIfCanBeUsedAsParent(modality, wxGetTopLevelParent(parent));
// then the currently active window
if ( !parent )
parent = CheckIfCanBeUsedAsParent(
parent = CheckIfCanBeUsedAsParent(modality,
wxGetTopLevelParent(wxGetActiveWindow()));
// and finally the application main window
if ( !parent )
parent = CheckIfCanBeUsedAsParent(wxApp::GetMainTopWindow());
parent = CheckIfCanBeUsedAsParent(modality, wxApp::GetMainTopWindow());
return parent;
}

View File

@@ -83,7 +83,7 @@ bool wxGenericFindReplaceDialog::Create(wxWindow *parent,
const wxString& title,
int style)
{
parent = GetParentForModalDialog(parent, style);
parent = GetParentForModelessDialog(parent, style);
if ( !wxDialog::Create(parent, wxID_ANY, title,
wxDefaultPosition, wxDefaultSize,