From 8dbc4824895ea9f87d1f6406fe2d22336b6253ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Keller?= Date: Tue, 25 Jul 2023 16:47:08 +0200 Subject: [PATCH] Windows QPA: Adjust margins for Windows App SDK compatibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If using the ExtendsContentIntoTitleBar() method from the Windows App SDK, the top margin becomes zero. The current approach does not account for this, since it relies on the AdjustWindowRectExForDpi function. Do a manual check after and correct if necessary, by comparing the window and client sizes. Fixes: QTBUG-113736 Pick-to: 6.6 6.5 Change-Id: I62e0338b3ff7af47f5525dcccd0f9acfe9691819 Reviewed-by: Oliver Wolff Reviewed-by: Wladimir Leuschner Reviewed-by: Tor Arne Vestbø --- .../platforms/windows/qwindowswindow.cpp | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 3a04a28efa..295ee936c8 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1981,7 +1981,7 @@ void QWindowsWindow::handleDpiScaledSize(WPARAM wParam, LPARAM lParam, LRESULT * // add the margins for the new DPI to the window size. const UINT dpi = UINT(wParam); const qreal scale = dpiRelativeScale(dpi); - const QMargins margins = QWindowsGeometryHint::frame(window(), style(), exStyle(), dpi); + const QMargins margins = fullFrameMargins(); if (!(m_data.flags & Qt::FramelessWindowHint)) { // We need to update the custom margins to match the current DPI, because // we don't want our users manually hook into this message just to set a @@ -1991,7 +1991,7 @@ void QWindowsWindow::handleDpiScaledSize(WPARAM wParam, LPARAM lParam, LRESULT * m_data.customMargins *= scale; } - const QSize windowSize = (geometry().size() * scale).grownBy(margins + customMargins()); + const QSize windowSize = (geometry().size() * scale).grownBy((margins * scale) + customMargins()); SIZE *size = reinterpret_cast(lParam); size->cx = windowSize.width(); size->cy = windowSize.height(); @@ -2310,6 +2310,7 @@ void QWindowsWindow::handleGeometryChange() { const QRect previousGeometry = m_data.geometry; m_data.geometry = geometry_sys(); + updateFullFrameMargins(); QWindowSystemInterface::handleGeometryChange(window(), m_data.geometry); // QTBUG-32121: OpenGL/normal windows (with exception of ANGLE // which we no longer support in Qt 6) do not receive expose @@ -2816,7 +2817,29 @@ void QWindowsWindow::calculateFullFrameMargins() const auto systemMargins = testFlag(DisableNonClientScaling) ? QWindowsGeometryHint::frameOnPrimaryScreen(window(), m_data.hwnd) : frameMargins_sys(); - setFullFrameMargins(systemMargins + customMargins()); + + // QTBUG-113736: systemMargins depends on AdjustWindowRectExForDpi. This doesn't take into + // account possible external modifications to the titlebar, as with ExtendsContentIntoTitleBar() + // from the Windows App SDK. We can fix this by comparing the WindowRect (which includes the + // frame) to the ClientRect. If a 'typical' frame is detected, i.e. only the titlebar has been + // modified, we can safely adjust the frame by deducting the bottom margin to the total Y + // difference between the two rects, to get the actual size of the titlebar and prevent + // unwanted client area slicing. + + RECT windowRect{}; + RECT clientRect{}; + GetWindowRect(handle(), &windowRect); + GetClientRect(handle(), &clientRect); + const int yDiff = (windowRect.bottom - windowRect.top) - clientRect.bottom; + const bool typicalFrame = (systemMargins.left() == systemMargins.right()) + && (systemMargins.right() == systemMargins.bottom()); + + const QMargins adjustedMargins = typicalFrame ? + QMargins(systemMargins.left(), yDiff - systemMargins.bottom(), + systemMargins.right(), systemMargins.bottom()) + : systemMargins; + + setFullFrameMargins(adjustedMargins + customMargins()); } QMargins QWindowsWindow::frameMargins() const