From: Vadim Zeitlin Date: Sat, 9 May 2009 12:26:15 +0000 (+0000) Subject: remove wxMSW-specific FindSuitableParent() and use GetParentForModalDialog() everywhe... X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/8bda0ec6a3b0a7852eb0056f20a0dba7b07ea593?ds=sidebyside remove wxMSW-specific FindSuitableParent() and use GetParentForModalDialog() everywhere; extend it with additional checks and remove redundant ones elsewhere git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@60559 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/dialog.h b/include/wx/dialog.h index 36bcb643db..4951bc72b2 100644 --- a/include/wx/dialog.h +++ b/include/wx/dialog.h @@ -91,7 +91,7 @@ public: int GetEscapeId() const { return m_escapeId; } // Returns the parent to use for modal dialogs if the user did not specify it - // explicitly + // explicitly. If parent argument is NULL, use GetParent() by default. wxWindow *GetParentForModalDialog(wxWindow *parent = NULL) const; #if wxUSE_STATTEXT // && wxUSE_TEXTCTRL @@ -211,6 +211,10 @@ private: // common part of all ctors void Init(); + // 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; + // handle Esc key presses void OnCharHook(wxKeyEvent& event); diff --git a/include/wx/msw/dialog.h b/include/wx/msw/dialog.h index 51edf8c071..e0274ff14a 100644 --- a/include/wx/msw/dialog.h +++ b/include/wx/msw/dialog.h @@ -108,12 +108,6 @@ public: WXLRESULT MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam); protected: - // find the window to use as parent for this dialog if none has been - // specified explicitly by the user - // - // may return NULL - wxWindow *FindSuitableParent() const; - // common part of all ctors void Init(); diff --git a/include/wx/os2/dialog.h b/include/wx/os2/dialog.h index 5555122df4..c4497ef466 100644 --- a/include/wx/os2/dialog.h +++ b/include/wx/os2/dialog.h @@ -95,14 +95,6 @@ public: #endif // WXWIN_COMPATIBILITY_2_6 protected: - // - // find the window to use as parent for this dialog if none has been - // specified explicitly by the user - // - // may return NULL - // - wxWindow *FindSuitableParent() const; - // // Common part of all ctors // diff --git a/include/wx/palmos/dialog.h b/include/wx/palmos/dialog.h index e8f66f58c0..717c30132d 100644 --- a/include/wx/palmos/dialog.h +++ b/include/wx/palmos/dialog.h @@ -64,12 +64,6 @@ public: virtual void Raise(); protected: - // find the window to use as parent for this dialog if none has been - // specified explicitly by the user - // - // may return NULL - wxWindow *FindSuitableParent() const; - // common part of all ctors void Init(); diff --git a/src/common/dlgcmn.cpp b/src/common/dlgcmn.cpp index eb33b068ee..18288235be 100644 --- a/src/common/dlgcmn.cpp +++ b/src/common/dlgcmn.cpp @@ -78,32 +78,63 @@ void wxDialogBase::Init() SetExtraStyle(GetExtraStyle() | wxWS_EX_BLOCK_EVENTS); } -// helper of GetParentForModalDialog() -static bool CanBeUsedAsParent(wxWindow *parent) +wxWindow *wxDialogBase::CheckIfCanBeUsedAsParent(wxWindow *parent) const { extern WXDLLIMPEXP_DATA_CORE(wxList) wxPendingDelete; - return !parent->HasExtraStyle(wxWS_EX_TRANSIENT) && - parent->IsShownOnScreen() && - !wxPendingDelete.Member(parent) && - !parent->IsBeingDeleted(); + if ( wxPendingDelete.Member(parent) || parent->IsBeingDeleted() ) + { + // this window is being deleted and we shouldn't create any children + // under it + return NULL; + } + + if ( parent->HasExtraStyle(wxWS_EX_TRANSIENT) ) + { + // this window is not being deleted yet but it's going to disappear + // soon so still don't parent this window under it + return NULL; + } + + if ( !parent->IsShownOnScreen() ) + { + // using hidden parent won't work correctly neither + return NULL; + } + + if ( parent == this ) + { + // not sure if this can really happen but it doesn't hurt to guard + // against this clearly invalid situation + return NULL; + } + + return parent; } wxWindow *wxDialogBase::GetParentForModalDialog(wxWindow *parent) 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: + // in an unfocused dialog, so try to find a valid parent for it unless we + // were explicitly asked not to + if ( HasFlag(wxDIALOG_NO_PARENT) ) + return NULL; + + // by default, use the parent specified in the ctor + if ( !parent ) + parent = GetParent(); + + // first try the given parent if ( parent ) - parent = wxGetTopLevelParent(parent); + parent = CheckIfCanBeUsedAsParent(wxGetTopLevelParent(parent)); - if ( !parent || !CanBeUsedAsParent(parent) ) - parent = wxTheApp->GetTopWindow(); + // then the currently active window + if ( !parent ) + parent = CheckIfCanBeUsedAsParent(wxGetActiveWindow()); - if ( parent && !CanBeUsedAsParent(parent) ) - { - // can't use this one, it's going to disappear - parent = NULL; - } + // and finally the application main window + if ( !parent ) + parent = CheckIfCanBeUsedAsParent(wxTheApp->GetTopWindow()); return parent; } diff --git a/src/gtk/dialog.cpp b/src/gtk/dialog.cpp index 2a2e83a0e0..0d05469ff8 100644 --- a/src/gtk/dialog.cpp +++ b/src/gtk/dialog.cpp @@ -111,16 +111,11 @@ int wxDialog::ShowModal() if ( win ) win->GTKReleaseMouseAndNotify(); - // use the apps top level window as parent if none given unless explicitly - // forbidden - if ( !GetParent() && !(GetWindowStyleFlag() & wxDIALOG_NO_PARENT) ) + wxWindow * const parent = GetParentForModalDialog(); + if ( parent ) { - wxWindow * const parent = GetParentForModalDialog(); - if ( parent && parent != this ) - { - gtk_window_set_transient_for( GTK_WINDOW(m_widget), - GTK_WINDOW(parent->m_widget) ); - } + gtk_window_set_transient_for( GTK_WINDOW(m_widget), + GTK_WINDOW(parent->m_widget) ); } wxBusyCursorSuspender cs; // temporarily suppress the busy cursor diff --git a/src/msw/dialog.cpp b/src/msw/dialog.cpp index 49a1997784..cc22686d7f 100644 --- a/src/msw/dialog.cpp +++ b/src/msw/dialog.cpp @@ -208,28 +208,6 @@ wxDialog::~wxDialog() // showing the dialogs // ---------------------------------------------------------------------------- -wxWindow *wxDialog::FindSuitableParent() const -{ - // first try to use the currently active window - HWND hwndFg = ::GetForegroundWindow(); - wxWindow *parent = hwndFg ? wxFindWinFromHandle((WXHWND)hwndFg) - : NULL; - if ( !parent ) - { - // next try the main app window - parent = wxTheApp->GetTopWindow(); - } - - // finally, check if the parent we found is really suitable - if ( !parent || parent == (wxWindow *)this || !parent->IsShown() ) - { - // don't use this one - parent = NULL; - } - - return parent; -} - bool wxDialog::Show(bool show) { if ( show == IsShown() ) diff --git a/src/msw/msgdlg.cpp b/src/msw/msgdlg.cpp index fcc722cb35..6166b125a4 100644 --- a/src/msw/msgdlg.cpp +++ b/src/msw/msgdlg.cpp @@ -442,7 +442,7 @@ int wxMessageDialog::ShowModal() // use the top level window as parent if none specified if ( !m_parent ) - m_parent = FindSuitableParent(); + m_parent = GetParentForModalDialog(); HWND hWnd = m_parent ? GetHwndOf(m_parent) : NULL; // translate wx style in MSW diff --git a/src/msw/toplevel.cpp b/src/msw/toplevel.cpp index 41c488a625..a803576060 100644 --- a/src/msw/toplevel.cpp +++ b/src/msw/toplevel.cpp @@ -373,29 +373,9 @@ bool wxTopLevelWindowMSW::CreateDialog(const void *dlgTemplate, // no dialogs support under MicroWin yet return CreateFrame(title, pos, size); #else // !__WXMICROWIN__ - wxWindow *parent = GetParent(); - - // for the dialogs without wxDIALOG_NO_PARENT style, use the top level - // app window as parent - this avoids creating modal dialogs without - // parent - if ( !parent && !(GetWindowStyleFlag() & wxDIALOG_NO_PARENT) ) - { - parent = wxTheApp->GetTopWindow(); - - if ( parent ) - { - // don't use transient windows as parents, this is dangerous as it - // can lead to a crash if the parent is destroyed before the child - // - // also don't use the window which is currently hidden as then the - // dialog would be hidden as well - if ( (parent->GetExtraStyle() & wxWS_EX_TRANSIENT) || - !parent->IsShown() ) - { - parent = NULL; - } - } - } + // static cast is valid as we're only ever called for dialogs + wxWindow * const + parent = static_cast(this)->GetParentForModalDialog(); m_hWnd = (WXHWND)::CreateDialogIndirect ( diff --git a/src/os2/dialog.cpp b/src/os2/dialog.cpp index d7da58b468..5115230049 100644 --- a/src/os2/dialog.cpp +++ b/src/os2/dialog.cpp @@ -166,28 +166,6 @@ bool wxDialog::IsModalShowing() const #endif // WXWIN_COMPATIBILITY_2_6 -wxWindow *wxDialog::FindSuitableParent() const -{ - // first try to use the currently active window - HWND hwndFg = ::WinQueryActiveWindow(HWND_DESKTOP); - wxWindow *parent = hwndFg ? wxFindWinFromHandle((WXHWND)hwndFg) - : NULL; - if ( !parent ) - { - // next try the main app window - parent = wxTheApp->GetTopWindow(); - } - - // finally, check if the parent we found is really suitable - if ( !parent || parent == (wxWindow *)this || !parent->IsShown() ) - { - // don't use this one - parent = NULL; - } - - return parent; -} - bool wxDialog::Show( bool bShow ) { if ( bShow == IsShown() ) diff --git a/src/palmos/dialog.cpp b/src/palmos/dialog.cpp index 32989e6eef..4358cfef5f 100644 --- a/src/palmos/dialog.cpp +++ b/src/palmos/dialog.cpp @@ -161,11 +161,6 @@ wxDialog::~wxDialog() // showing the dialogs // ---------------------------------------------------------------------------- -wxWindow *wxDialog::FindSuitableParent() const -{ - return NULL; -} - bool wxDialog::Show(bool show) { if (show && CanDoLayoutAdaptation())