From 588a6dc63c836880cb2527915ff99aae159fd8fb Mon Sep 17 00:00:00 2001 From: David Capello Date: Fri, 23 Apr 2021 15:35:27 -0300 Subject: [PATCH] Fix destruction order of native windows to avoid crashing We've to send kCloseMessage first, and then destroy the native window (so children native window are destroyed correctly when kCloseMessage is received, e.g. ComboBox popup must destroy its native window when it receives a kCloseMessage of the parent window). --- src/ui/manager.cpp | 64 +++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/ui/manager.cpp b/src/ui/manager.cpp index 8d0a2579e..499ea0819 100644 --- a/src/ui/manager.cpp +++ b/src/ui/manager.cpp @@ -1384,38 +1384,6 @@ void Manager::_openWindow(Window* window, bool center) void Manager::_closeWindow(Window* window, bool redraw_background) { - Display* windowDisplay = window->display(); - Display* parentDisplay; - - if (// The display can be nullptr if the window was not opened or - // was closed before. - window->ownDisplay()) { - parentDisplay = windowDisplay->parentDisplay(); - ASSERT(parentDisplay); - ASSERT(windowDisplay); - ASSERT(windowDisplay != this->display()); - - // Remove all messages for this display. - removeMessagesForDisplay(windowDisplay); - - window->setDisplay(nullptr, false); - windowDisplay->nativeWindow()->setUserData(nullptr); - - // Remove the mouse cursor from the display that we are going to - // delete. - _internal_set_mouse_display(parentDisplay); - - // The ui::Display should destroy the os::Window - delete windowDisplay; - - // Activate main windows - parentDisplay->nativeWindow()->activate(); - } - else { - parentDisplay = windowDisplay; - window->setDisplay(nullptr, false); - } - if (!hasChild(window)) return; @@ -1460,6 +1428,38 @@ void Manager::_closeWindow(Window* window, bool redraw_background) window->sendMessage(msg.get()); } + // Destroy native window associated with this window's display if needed + Display* windowDisplay = window->display(); + Display* parentDisplay; + if (// The display can be nullptr if the window was not opened or + // was closed before. + window->ownDisplay()) { + parentDisplay = windowDisplay->parentDisplay(); + ASSERT(parentDisplay); + ASSERT(windowDisplay); + ASSERT(windowDisplay != this->display()); + + // Remove all messages for this display. + removeMessagesForDisplay(windowDisplay); + + // Remove the mouse cursor from the display that we are going to + // delete. + _internal_set_mouse_display(parentDisplay); + + window->setDisplay(nullptr, false); + windowDisplay->nativeWindow()->setUserData(nullptr); + + // The ui::Display should destroy the os::Window + delete windowDisplay; + + // Activate main windows + parentDisplay->nativeWindow()->activate(); + } + else { + parentDisplay = windowDisplay; + window->setDisplay(nullptr, false); + } + // Update manager list stuff. removeChild(window);