From e81c7386943db2b8c51a3fb833279c0e1518b926 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 19 Mar 2019 19:11:16 +0100 Subject: [PATCH] Fix spurious assert in wxMSW when destroying a TLW with buttons This commit partially reverts 17055fb8c6fdbba5fb92b6519b801da7a7e77491 which resulted in asserts when destroying dialogs with buttons, one of which had focus, see https://github.com/wxWidgets/wxWidgets/pull/1245 This happened because wxGetTopLevelParent() returns NULL when the parent TLW was already half-destructed, resulting in an assert, while the original code still returned NULL in this case, but did it silently, which is the right thing to do here as we can't avoid being called during the parent TLW destruction. Closes https://github.com/wxWidgets/wxWidgets/pull/1268 --- src/msw/button.cpp | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/msw/button.cpp b/src/msw/button.cpp index ae3cf19601..c9df03a590 100644 --- a/src/msw/button.cpp +++ b/src/msw/button.cpp @@ -252,14 +252,26 @@ wxWindow *wxButton::SetDefault() // return NULL static wxTopLevelWindow *GetTLWParentIfNotBeingDeleted(wxWindow *win) { - wxWindow* const parent = wxGetTopLevelParent(win); - wxASSERT_MSG( parent, wxT("button without top level parent?") ); + for ( ;; ) + { + // IsTopLevel() will return false for a wxTLW being deleted, so we also + // need the parent test for this case + wxWindow * const parent = win->GetParent(); + if ( !parent || win->IsTopLevel() ) + { + if ( win->IsBeingDeleted() ) + return NULL; - if ( parent->IsBeingDeleted() ) - return NULL; + break; + } + + win = parent; + } + + wxASSERT_MSG( win, wxT("button without top level parent?") ); // Note that this may still return null for a button inside wxPopupWindow. - return wxDynamicCast(parent, wxTopLevelWindow); + return wxDynamicCast(win, wxTopLevelWindow); } // set this button as being currently default