From a90d99d8da9b2be2e6b8e981cd9dabfb1641e985 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 30 Aug 2024 16:40:31 +0200 Subject: [PATCH] Windows: Set window style in correct order when reparenting foreign windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SetParent() documentation notes that when making a window a child window the window style should be set before calling SetParent(), while the opposite order should be used when making a window top level. We were exclusively doing the latter, which resulted in child windows getting activated and focused as part of the reparenting. Being the active window was resulting in the child window receiving WM_CLOSE and being destroyed if the user pressed Alt+F4, which was very surprising. The child window can still be focused later on, via e.g. an explicit call to SetFocus(), so it can receive keyboard input. The QWindowsWindow::setParent_sys() logic, used for non-foreign windows has the same fundamental issue with not respecting the order of the style update, but the interactions with the drop site logic makes it harder to update in similar fashion as this patch does for QWindowsForeignWindow. Pick-to: 6.8 6.8.0 Change-Id: Id88f5981daaf121a39aba9319d02aebefb6aa07b Reviewed-by: Jøger Hansegård Reviewed-by: Oliver Wolff --- .../platforms/windows/qwindowswindow.cpp | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 330c456a1d3..e1b9cfdcda1 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1357,10 +1357,12 @@ void QWindowsForeignWindow::setParent(const QPlatformWindow *newParentWindow) const HWND newParent = newParentWindow ? reinterpret_cast(newParentWindow->winId()) : HWND(nullptr); const bool isTopLevel = !newParent; const DWORD oldStyle = style(); + qCDebug(lcQpaWindow) << __FUNCTION__ << window() << "newParent=" << newParentWindow << newParent << "oldStyle=" << debugWinStyle(oldStyle); - SetParent(m_hwnd, newParent); - if (wasTopLevel != isTopLevel) { // Top level window flags need to be set/cleared manually. + + auto updateWindowFlags = [=]{ + // Top level window flags need to be set/cleared manually. DWORD newStyle = oldStyle; if (isTopLevel) { newStyle = m_topLevelStyle; @@ -1370,6 +1372,20 @@ void QWindowsForeignWindow::setParent(const QPlatformWindow *newParentWindow) newStyle |= WS_CHILD; } SetWindowLongPtr(m_hwnd, GWL_STYLE, newStyle); + }; + + if (wasTopLevel && !isTopLevel) { + // Becoming a child window requires the style + // flags to be updated before reparenting. + updateWindowFlags(); + } + + SetParent(m_hwnd, newParent); + + if (!wasTopLevel && isTopLevel) { + // Becoming a top level window requires the style + // flags to be updated after reparenting. + updateWindowFlags(); } }