diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 925b70ffb25..2b48e920033 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -2485,12 +2485,6 @@ 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() @@ -2507,20 +2501,7 @@ 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() }; - } + correctWindowPlacement(windowPlacement); // 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 @@ -2552,6 +2533,65 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state) } } +// Apply corrections to window placement in Windows 10 +// Related to task bar on top or left. + +inline bool QWindowsBaseWindow::hasMaximumHeight() const +{ + return window()->maximumHeight() != QWINDOWSIZE_MAX; +} + +inline bool QWindowsBaseWindow::hasMaximumWidth() const +{ + return window()->maximumWidth() != QWINDOWSIZE_MAX; +} + +inline bool QWindowsBaseWindow::hasMaximumSize() const +{ + return hasMaximumHeight() || hasMaximumWidth(); +} + +void QWindowsWindow::correctWindowPlacement(WINDOWPLACEMENT &windowPlacement) +{ + static const auto windows11 = QOperatingSystemVersion::Windows11_21H2; + static const bool isWindows10 = QOperatingSystemVersion::current() < windows11; + if (!isWindows10) + return; + + // Correct normal position by placement offset on Windows 10 + // (where task bar can be on any side of the screen) + const QPoint offset = windowPlacementOffset(m_data.hwnd, m_data.restoreGeometry.topLeft()); + windowPlacement.rcNormalPosition = RECTfromQRect(m_data.restoreGeometry.translated(-offset)); + qCDebug(lcQpaWindow) << "Corrected normal position by" << -offset; + + // 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. + if (hasMaximumSize()) { + const QMargins margins = frameMargins_sys(); + const QPoint topLeft = window()->screen()->geometry().topLeft(); + windowPlacement.ptMaxPosition = POINT{ topLeft.x() - margins.left(), topLeft.y() }; + qCDebug(lcQpaWindow) << "Window has maximum size. Corrected topLeft by" + << -margins.left(); + + // If there is a placement offset correct width/height unless restricted, + // in order to fit window onto the screen. + if (offset.x() > 0 && !hasMaximumWidth()) { + const int adjust = offset.x() / window()->devicePixelRatio(); + window()->setWidth(window()->width() - adjust); + qCDebug(lcQpaWindow) << "Width shortened by" << adjust << "logical pixels."; + } + if (offset.y() > 0 && !hasMaximumHeight()) { + const int adjust = offset.y() / window()->devicePixelRatio(); + window()->setHeight(window()->height() - adjust); + qCDebug(lcQpaWindow) << "Height shortened by" << adjust << "logical pixels."; + } + } +} + void QWindowsWindow::updateRestoreGeometry() { m_data.restoreGeometry = normalFrameGeometry(m_data.hwnd); diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index 687ade1d921..bebd068f1a5 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -128,6 +128,8 @@ public: protected: HWND parentHwnd() const { return GetAncestor(handle(), GA_PARENT); } bool isTopLevel_sys() const; + inline bool hasMaximumHeight() const; + inline bool hasMaximumWidth() const; inline bool hasMaximumSize() const; QRect frameGeometry_sys() const; QRect geometry_sys() const; @@ -368,6 +370,7 @@ private: void fireExpose(const QRegion ®ion, bool force=false); void fireFullExpose(bool force=false); void calculateFullFrameMargins(); + void correctWindowPlacement(WINDOWPLACEMENT &windowPlacement); mutable QWindowsWindowData m_data; QPointer m_menuBar;