X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/49c9d05986415e8f4f2139f112d7a320b48c07e8..0bbe61b8c18a1795189f0cf73cc61c14a0fb846d:/src/common/toplvcmn.cpp diff --git a/src/common/toplvcmn.cpp b/src/common/toplvcmn.cpp index e72953cf7e..bcfd529105 100644 --- a/src/common/toplvcmn.cpp +++ b/src/common/toplvcmn.cpp @@ -40,8 +40,11 @@ BEGIN_EVENT_TABLE(wxTopLevelWindowBase, wxWindow) EVT_CLOSE(wxTopLevelWindowBase::OnCloseWindow) EVT_SIZE(wxTopLevelWindowBase::OnSize) EVT_WINDOW_DESTROY(wxTopLevelWindowBase::OnChildDestroy) + WX_EVENT_TABLE_CONTROL_CONTAINER(wxTopLevelWindowBase) END_EVENT_TABLE() +WX_DELEGATE_TO_CONTROL_CONTAINER(wxTopLevelWindowBase, wxWindow) + // ============================================================================ // implementation // ============================================================================ @@ -56,18 +59,51 @@ 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(); } wxTopLevelWindowBase::~wxTopLevelWindowBase() { + m_winDefault = + m_winTmpDefault = NULL; + // don't let wxTheApp keep any stale pointers to us if ( wxTheApp && wxTheApp->GetTopWindow() == this ) wxTheApp->SetTopWindow(NULL); 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 @@ -82,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; @@ -412,14 +459,3 @@ void wxTopLevelWindowBase::RequestUserAttention(int WXUNUSED(flags)) // it's probably better than do nothing, isn't it? Raise(); } - -void wxTopLevelWindowBase::RemoveChild(wxWindowBase *child) -{ - if ( child == m_winDefault ) - m_winDefault = NULL; - - if ( child == m_winTmpDefault ) - m_winTmpDefault = NULL; - - wxWindow::RemoveChild(child); -}