From 046cc59aee45ec37a0f864b91801393330dd00cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 28 Aug 2024 15:06:22 +0200 Subject: [PATCH] XCB/Windows: Decouple foreign window from QWindow parent on destroy Qt's foreign windows do not take (full) ownership of the native handle, so our platform window implementations take care to not fully destroy the native handle in their destructors. But if the foreign window had a QWindow parent at the time of destruction, and we fail to decouple the native handle from its native handle parent, the destruction of the QWindow parent may bring down the foreign window native handle as well, as part of deleting the parent QWindow's native handle. We take care to selectively do this decoupling on macOS, iOS, and Android, but were failing to do so on XCB and Windows. This has now been corrected, which allows us to remove the workaround in QWindow, which was also in the wrong place (before setVisible(false) on the foreign window child). Note that we do not unconditionally reparent the foreign window, as it might be a foreign window used for containing other QWindows, in which case we don't want to mess with the native view hierarchy. Change-Id: Ic526ca63fbf72dae5013ae9e44cb5cddf61c944b Reviewed-by: Liang Qi (cherry picked from commit 8f8ce8d7a7e029e62a4f9b5b209dcc37f61410cb) Reviewed-by: Qt Cherry-pick Bot --- src/gui/kernel/qwindow.cpp | 10 ---------- src/plugins/platforms/windows/qwindowswindow.cpp | 6 ++++++ src/plugins/platforms/windows/qwindowswindow.h | 1 + src/plugins/platforms/xcb/qxcbwindow.cpp | 3 +++ 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index f2e44e886b7..f698113ed29 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -2083,16 +2083,6 @@ void QWindowPrivate::destroy() QObject *object = childrenWindows.at(i); if (object->isWindowType()) { QWindow *w = static_cast(object); - auto *childPlatformWindow = w->handle(); - if (!childPlatformWindow) - continue; - - // Decouple the foreign window from this window, - // so that destroying our native handle doesn't - // bring down the foreign window as well. - if (childPlatformWindow->isForeignWindow()) - childPlatformWindow->setParent(nullptr); - qt_window_private(w)->destroy(); } } diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index eb8cf6e9137..c7033a74c43 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1364,6 +1364,12 @@ QWindowsForeignWindow::QWindowsForeignWindow(QWindow *window, HWND hwnd) setParent(QPlatformWindow::parent()); } +QWindowsForeignWindow::~QWindowsForeignWindow() +{ + if (QPlatformWindow::parent()) + setParent(nullptr); +} + void QWindowsForeignWindow::setParent(const QPlatformWindow *newParentWindow) { const bool wasTopLevel = isTopLevel_sys(); diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index f2e5c735920..687ade1d921 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -160,6 +160,7 @@ class QWindowsForeignWindow : public QWindowsBaseWindow { public: explicit QWindowsForeignWindow(QWindow *window, HWND hwnd); + ~QWindowsForeignWindow(); void setParent(const QPlatformWindow *window) override; void setGeometry(const QRect &rect) override { setGeometry_sys(rect); } diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 7fd6fc0c4e3..5caf4b21acf 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -530,6 +530,9 @@ QXcbForeignWindow::QXcbForeignWindow(QWindow *window, WId nativeHandle) QXcbForeignWindow::~QXcbForeignWindow() { + if (QPlatformWindow::parent()) + setParent(nullptr); + // Clear window so that destroy() does not affect it m_window = 0;