summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMorten Johan Sørvig <morten.sorvig@qt.io>2021-09-23 19:49:20 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-10-12 16:37:41 +0000
commitefb9190406a9a598bfe9100d74801acf1d5a2553 (patch)
tree551d93ecf9bc81e4cd3515b690a56353360e8911 /src
parenta398961e53145b17e2cabc751923f4e3fd840501 (diff)
Handle WM_GETDPISCALEDSIZE
By handling WM_GETDPISCALEDSIZE we can keep QWindow’s device independent size constant across DPI changes. This is done by scaling QPlatformWindow’s native size such that the change of scale factor and change of QPlatformWindow size cancels out. Qt now handles DPI change using two events: WM_GETDPISCALEDSIZE: Compute the new size for the window. WM_DPICHANGED: Apply the new DPI and window geometry. The reason for this complication is that Windows retains control over the window position during the DPI change, in order to e.g. accurately track the cursor position during a screen change. The default WM_GETDPISCALEDSIZE implementation (provided by Windows) scales the win32 window size linearly with the DPI change. We want to use linear scaling as well, however the win32 window size includes the margins, which do not change linearly as the DPI changes. Instead, scale the QPlatformWindow size, and then add the new margins. Change-Id: I4f225be8fad56b1fa77e9e3cfd6538a206589d73 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io> (cherry picked from commit 2cfca7fd1911cc82a22763152c04c65bc05bc19a) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src')
-rw-r--r--src/gui/kernel/qhighdpiscaling_p.h2
-rw-r--r--src/plugins/platforms/windows/qtwindowsglobal.h7
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp3
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.h3
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp18
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h1
6 files changed, 32 insertions, 2 deletions
diff --git a/src/gui/kernel/qhighdpiscaling_p.h b/src/gui/kernel/qhighdpiscaling_p.h
index 8460b3ec2e..89856570ce 100644
--- a/src/gui/kernel/qhighdpiscaling_p.h
+++ b/src/gui/kernel/qhighdpiscaling_p.h
@@ -124,6 +124,7 @@ public:
static QPoint mapPositionFromNative(const QPoint &pos, const QPlatformScreen *platformScreen);
static QPoint mapPositionToNative(const QPoint &pos, const QPlatformScreen *platformScreen);
static QDpi logicalDpi(const QScreen *screen);
+ static qreal roundScaleFactor(qreal rawFactor);
private:
struct ScreenFactor {
@@ -134,7 +135,6 @@ private:
};
static qreal rawScaleFactor(const QPlatformScreen *screen);
- static qreal roundScaleFactor(qreal rawFactor);
static QDpi effectiveLogicalDpi(const QPlatformScreen *screen, qreal rawFactor, qreal roundedFactor);
static qreal screenSubfactor(const QPlatformScreen *screen);
static QScreen *screenForPosition(Point position, QScreen *guess);
diff --git a/src/plugins/platforms/windows/qtwindowsglobal.h b/src/plugins/platforms/windows/qtwindowsglobal.h
index 573a8d07c8..3853a0afa4 100644
--- a/src/plugins/platforms/windows/qtwindowsglobal.h
+++ b/src/plugins/platforms/windows/qtwindowsglobal.h
@@ -60,6 +60,10 @@
# define WM_DPICHANGED 0x02E0
#endif
+#ifndef WM_GETDPISCALEDSIZE
+# define WM_GETDPISCALEDSIZE 0x02E4
+#endif
+
// WM_POINTER support from Windows 8 onwards (WINVER >= 0x0602)
#ifndef WM_POINTERUPDATE
# define WM_NCPOINTERUPDATE 0x0241
@@ -129,6 +133,7 @@ enum WindowsEventType // Simplify event types
EnterSizeMoveEvent = WindowEventFlag + 22,
ExitSizeMoveEvent = WindowEventFlag + 23,
PointerActivateWindowEvent = WindowEventFlag + 24,
+ DpiScaledSizeEvent = WindowEventFlag + 25,
MouseEvent = MouseEventFlag + 1,
MouseWheelEvent = MouseEventFlag + 2,
CursorEvent = MouseEventFlag + 3,
@@ -316,6 +321,8 @@ inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamI
return HIWORD(wParamIn) ? QtWindows::AcceleratorCommandEvent : QtWindows::MenuCommandEvent;
case WM_DPICHANGED:
return QtWindows::DpiChangedEvent;
+ case WM_GETDPISCALEDSIZE:
+ return QtWindows::DpiScaledSizeEvent;
case WM_ENTERSIZEMOVE:
return QtWindows::EnterSizeMoveEvent;
case WM_EXITSIZEMOVE:
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 91fb80dc28..1c75f7f7d2 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -1453,6 +1453,9 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
return true;
#endif
} break;
+ case QtWindows::DpiScaledSizeEvent:
+ platformWindow->handleDpiScaledSize(wParam, lParam, result);
+ return true;
case QtWindows::DpiChangedEvent:
platformWindow->handleDpiChanged(hwnd, wParam, lParam);
return true;
diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h
index 2052648933..319e998c80 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.h
+++ b/src/plugins/platforms/windows/qwindowsscreen.h
@@ -86,7 +86,7 @@ public:
QImage::Format format() const override { return m_data.format; }
QSizeF physicalSize() const override { return m_data.physicalSizeMM; }
QDpi logicalDpi() const override { return m_data.dpi; }
- QDpi logicalBaseDpi() const override { return QDpi(96, 96); }
+ QDpi logicalBaseDpi() const override { return QDpi(baseDpi, baseDpi); }
qreal devicePixelRatio() const override { return 1.0; }
qreal refreshRate() const override { return m_data.refreshRateHz; }
QString name() const override { return m_data.name; }
@@ -115,6 +115,7 @@ public:
const QWindowsScreenData &data() const { return m_data; }
static QRect virtualGeometry(const QPlatformScreen *screen);
+ static inline int baseDpi = 96;
private:
QWindowsScreenData m_data;
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index f167847a59..682ce8f710 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -1834,6 +1834,24 @@ void QWindowsWindow::handleCompositionSettingsChanged()
}
}
+void QWindowsWindow::handleDpiScaledSize(WPARAM wParam, LPARAM lParam, LRESULT *result)
+{
+ // We want to keep QWindow's device independent size constant across the
+ // DPI change. To accomplish this, scale QPlatformWindow's native size
+ // by the change of DPI (e.g. 120 -> 144 = 1.2), also taking any scale
+ // factor rounding into account. The win32 window size includes the margins;
+ // add the margins for the new DPI to the window size.
+ const int dpi = int(wParam);
+ const qreal scale = QHighDpiScaling::roundScaleFactor(qreal(dpi) / QWindowsScreen::baseDpi) /
+ QHighDpiScaling::roundScaleFactor(qreal(savedDpi()) / QWindowsScreen::baseDpi);
+ const QMargins margins = QWindowsGeometryHint::frame(style(), exStyle(), dpi);
+ const QSize windowSize = (geometry().size() * scale).grownBy(margins);
+ SIZE *size = reinterpret_cast<SIZE *>(lParam);
+ size->cx = windowSize.width();
+ size->cy = windowSize.height();
+ *result = true; // Inform Windows that we've set a size
+}
+
void QWindowsWindow::handleDpiChanged(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
const UINT dpi = HIWORD(wParam);
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index 205a02a30d..8b9e304e9b 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -318,6 +318,7 @@ public:
void handleResized(int wParam);
void handleHidden();
void handleCompositionSettingsChanged();
+ void handleDpiScaledSize(WPARAM wParam, LPARAM lParam, LRESULT *result);
void handleDpiChanged(HWND hwnd, WPARAM wParam, LPARAM lParam);
static void displayChanged();