From 1329e6faca24888c8276c708877bb0f1d12d687f Mon Sep 17 00:00:00 2001 From: Axel Spoerl Date: Tue, 20 Aug 2024 15:56:51 +0200 Subject: [PATCH] QWindowsWindow: Work around offset bug in GetWindowPlacement() GetWindowPlacement() stores wrong positions in the &WINDOWPLACEMENT argument's ptMaxPosition member on Windows 10. (1) Each time a fixed height window is maximized, ptMaxPosition moves - down by the task bar's height, if the task bar is on top - right by the task bar's width, if the task bar is on the left (2) The frame margins' left offset (typically -8) is not respected. On Windows 10, set ptMaxPosition to {0, 0} adjusted by the frame margins' left offset. Fixes: QTBUG-123752 Pick-to: 6.7 6.5 6.2 Change-Id: I8bbd63d93a7648921b703ff6f3e09c4cf2999be2 Reviewed-by: Oliver Wolff (cherry picked from commit 33874a9424cd03c21ca9986a39c383b3689f03d2) Reviewed-by: Qt Cherry-pick Bot --- .../platforms/windows/qwindowswindow.cpp | 22 +++++++++++++++++++ .../platforms/windows/qwindowswindow.h | 1 + 2 files changed, 23 insertions(+) diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 2b9091f079a..eb8cf6e9137 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -36,6 +36,7 @@ #include #include +#include #include @@ -2462,6 +2463,12 @@ QWindowsWindowData QWindowsWindow::setWindowFlags_sys(Qt::WindowFlags wt, return result; } +inline bool QWindowsBaseWindow::hasMaximumSize() const +{ + const auto maximumSize = window()->maximumSize(); + return maximumSize.width() != QWINDOWSIZE_MAX || maximumSize.height() != QWINDOWSIZE_MAX; +} + void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state) { qCDebug(lcQpaWindow) << __FUNCTION__ << this << window() @@ -2478,6 +2485,21 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state) GetWindowPlacement(m_data.hwnd, &windowPlacement); const RECT geometry = RECTfromQRect(m_data.restoreGeometry); windowPlacement.rcNormalPosition = geometry; + + // A bug in windows 10 grows + // - ptMaxPosition.x by the task bar's width, if it's on the left + // - ptMaxPosition.y by the task bar's height, if it's on the top + // each time GetWindowPlacement() is called. + // The offset of the screen's left edge (as per frameMargins_sys().left()) is ignored. + // => Check for windows 10 and correct. + static const auto windows11 = QOperatingSystemVersion::Windows11_21H2; + static const bool isWindows10 = QOperatingSystemVersion::current() < windows11; + if (isWindows10 && hasMaximumSize()) { + const QMargins margins = frameMargins_sys(); + const QPoint topLeft = window()->screen()->geometry().topLeft(); + windowPlacement.ptMaxPosition = POINT{ topLeft.x() - margins.left(), topLeft.y() }; + } + // Even if the window is hidden, windowPlacement's showCmd is not SW_HIDE, so change it // manually to avoid unhiding a hidden window with the subsequent call to // SetWindowPlacement(). diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index b3cddc11d87..f2e5c735920 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -128,6 +128,7 @@ public: protected: HWND parentHwnd() const { return GetAncestor(handle(), GA_PARENT); } bool isTopLevel_sys() const; + inline bool hasMaximumSize() const; QRect frameGeometry_sys() const; QRect geometry_sys() const; void setGeometry_sys(const QRect &rect) const;