X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/049908c57372c671516be6f1a853d35761327e81..edd6813c826edc2311548da53eb83e7f1bc18d2b:/src/common/toplvcmn.cpp diff --git a/src/common/toplvcmn.cpp b/src/common/toplvcmn.cpp index 77cbec0582..bcfd529105 100644 --- a/src/common/toplvcmn.cpp +++ b/src/common/toplvcmn.cpp @@ -59,7 +59,7 @@ wxTopLevelWindowBase::wxTopLevelWindowBase() { // Unlike windows, top level windows are created hidden by default. m_isShown = false; - m_winDefault = NULL; + m_winDefault = m_winTmpDefault = NULL; WX_INIT_CONTROL_CONTAINER(); @@ -67,7 +67,8 @@ wxTopLevelWindowBase::wxTopLevelWindowBase() wxTopLevelWindowBase::~wxTopLevelWindowBase() { - m_winDefault = m_winTmpDefault = NULL; + m_winDefault = + m_winTmpDefault = NULL; // don't let wxTheApp keep any stale pointers to us if ( wxTheApp && wxTheApp->GetTopWindow() == this ) @@ -75,6 +76,34 @@ wxTopLevelWindowBase::~wxTopLevelWindowBase() wxTopLevelWindows.DeleteObject(this); + // delete any our top level children which are still pending for deletion + // immediately: this could happen if a child (e.g. a temporary dialog + // created with this window as parent) was Destroy()'d) while this window + // was deleted directly (with delete, or maybe just because it was created + // on the stack) immediately afterwards and before the child TLW was really + // destroyed -- not destroying it now would leave it alive with a dangling + // parent pointer and result in a crash later + for ( wxObjectList::iterator i = wxPendingDelete.begin(); + i != wxPendingDelete.end(); + ) + { + wxWindow * const win = wxDynamicCast(*i, wxWindow); + if ( win && win->GetParent() == this ) + { + wxPendingDelete.erase(i); + + delete win; + + // deleting it invalidated the list (and not only one node because + // it could have resulted in deletion of other objects to) + i = wxPendingDelete.begin(); + } + else + { + ++i; + } + } + if ( IsLastBeforeExit() ) { // no other (important) windows left, quit the app @@ -89,15 +118,26 @@ bool wxTopLevelWindowBase::Destroy() if ( !wxPendingDelete.Member(this) ) wxPendingDelete.Append(this); - if (wxTopLevelWindows.GetCount() > 1) + // normally we want to hide the window immediately so that it doesn't get + // stuck on the screen while it's being destroyed, however we shouldn't + // hide the last visible window as then we might not get any idle events + // any more as no events will be sent to the hidden window and without idle + // events we won't prune wxPendingDelete list and the application won't + // terminate + for ( wxWindowList::const_iterator i = wxTopLevelWindows.begin(), + end = wxTopLevelWindows.end(); + i != end; + ++i ) { - // Hide it immediately. This should - // not be done if this TLW is the - // only one left since we then would - // risk not to get any idle events - // at all anymore during which we - // could delete any pending events. - Hide(); + wxTopLevelWindow * const win = wx_static_cast(wxTopLevelWindow *, *i); + if ( win != this && win->IsShown() ) + { + // there remains at least one other visible TLW, we can hide this + // one + Hide(); + + break; + } } return true;