diff options
author | Morten Johan Sørvig <morten.sorvig@qt.io> | 2021-09-29 11:42:43 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2021-10-12 16:37:41 +0000 |
commit | a398961e53145b17e2cabc751923f4e3fd840501 (patch) | |
tree | 0ce7aaa401702caa2eb51cfca8ff06a0aeb34b4a /src | |
parent | 64148e8d363adcea59ee15cc7b726ead21574d0c (diff) |
Fix programatic geometry change to different DPI
The event flow for programatic window geometry change
(e.g. from MoveWindow()) differs from user-interactive
geometry change: We still get WM_DPICHANGED, but this
event is not preceded by WM_GETDPISCALEDSIZE, so we don’t
get to override the window size.
However, Qt has already scaled the window size for the
new DPI in this case (the scaled size is provided to
QWindowsWindow::setGeometry()), so we can omit making
second native set-geometry call.
Change-Id: Ia7d42d7fee49adf757e7fe75d77f1731405ad519
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
(cherry picked from commit 81707951fe251d9c9074a5b8ca6211900a23d235)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/platforms/windows/qwindowswindow.cpp | 34 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowswindow.h | 1 |
2 files changed, 27 insertions, 8 deletions
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index bbe19e4fcc..f167847a59 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1345,6 +1345,7 @@ void QWindowCreationContext::applyToMinMaxInfo(MINMAXINFO *mmi) const const char *QWindowsWindow::embeddedNativeParentHandleProperty = "_q_embedded_native_parent_handle"; const char *QWindowsWindow::hasBorderInFullScreenProperty = "_q_has_border_in_fullscreen"; bool QWindowsWindow::m_borderInFullScreenDefault = false; +bool QWindowsWindow::m_inSetgeometry = false; QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data) : QWindowsBaseWindow(aWindow), @@ -1842,14 +1843,29 @@ void QWindowsWindow::handleDpiChanged(HWND hwnd, WPARAM wParam, LPARAM lParam) // Send screen change first, so that the new sceen is set during any following resize checkForScreenChanged(QWindowsWindow::FromDpiChange); - // Apply the suggested window geometry to the native window. This will make - // sure the window tracks the mouse cursor during screen change, and also - // that the window size is scaled according to the DPI change. - updateFullFrameMargins(); - const auto prcNewWindow = reinterpret_cast<RECT *>(lParam); - SetWindowPos(hwnd, nullptr, prcNewWindow->left, prcNewWindow->top, - prcNewWindow->right - prcNewWindow->left, - prcNewWindow->bottom - prcNewWindow->top, SWP_NOZORDER | SWP_NOACTIVATE); + // We get WM_DPICHANGED in one of two situations: + // + // 1. The DPI change is a "spontaneous" DPI change as a result of e.g. + // the user dragging the window to a new screen. In this case Windows + // first sends WM_GETDPISCALEDSIZE, where we set the new window size, + // followed by this event where we apply the suggested window geometry + // to the native window. This will make sure the window tracks the mouse + // cursor during screen change, and also that the window size is scaled + // according to the DPI change. + // + // 2. The DPI change is a result of a setGeometry() call. In this case + // Qt has already scaled the window size for the new DPI. Further, Windows + // does not call WM_GETDPISCALEDSIZE, and also applies its own scaling + // to the already scaled window size. Since there is no need to set the + // window geometry again, and the provided geometry is incorrect, we omit + // making the SetWindowPos() call. + if (!m_inSetgeometry) { + updateFullFrameMargins(); + const auto prcNewWindow = reinterpret_cast<RECT *>(lParam); + SetWindowPos(hwnd, nullptr, prcNewWindow->left, prcNewWindow->top, + prcNewWindow->right - prcNewWindow->left, + prcNewWindow->bottom - prcNewWindow->top, SWP_NOZORDER | SWP_NOACTIVATE); + } // Scale child QPlatformWindow size. Windows sends WM_DPICHANGE to top-level windows only. for (QWindow *childWindow : window()->findChildren<QWindow *>()) { @@ -1930,6 +1946,8 @@ static QString msgUnableToSetGeometry(const QWindowsWindow *platformWindow, void QWindowsWindow::setGeometry(const QRect &rectIn) { + QBoolBlocker b(m_inSetgeometry); + QRect rect = rectIn; // This means it is a call from QWindow::setFramePosition() and // the coordinates include the frame (size is still the contents rectangle). diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index 14c5f47853..205a02a30d 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -417,6 +417,7 @@ private: VkSurfaceKHR m_vkSurface = VK_NULL_HANDLE; #endif static bool m_borderInFullScreenDefault; + static bool m_inSetgeometry; }; #ifndef QT_NO_DEBUG_STREAM |