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 <oliver.wolff@qt.io>
(cherry picked from commit 33874a9424cd03c21ca9986a39c383b3689f03d2)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Axel Spoerl 2024-08-20 15:56:51 +02:00 committed by Qt Cherry-pick Bot
parent 322e55ff45
commit 1329e6faca
2 changed files with 23 additions and 0 deletions

View File

@ -36,6 +36,7 @@
#include <QtCore/qdebug.h>
#include <QtCore/qlibraryinfo.h>
#include <QtCore/qoperatingsystemversion.h>
#include <dwmapi.h>
@ -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().

View File

@ -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;