summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMorten Johan Sørvig <morten.sorvig@qt.io>2021-09-29 11:42:43 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-10-12 16:37:41 +0000
commita398961e53145b17e2cabc751923f4e3fd840501 (patch)
tree0ce7aaa401702caa2eb51cfca8ff06a0aeb34b4a /src
parent64148e8d363adcea59ee15cc7b726ead21574d0c (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.cpp34
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h1
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