diff options
author | Morten Sørvig <morten.sorvig@qt.io> | 2023-11-01 09:51:06 +0100 |
---|---|---|
committer | Morten Sørvig <morten.sorvig@qt.io> | 2023-11-15 21:52:24 +0100 |
commit | 6017695bfa98d8d9a6e5977ec80aafa1a4d3ee4d (patch) | |
tree | f8d3f0808cda281da02705b8e35c33491afa7bde /src/widgets/styles/qwindowsstyle.cpp | |
parent | d6861926a12e3ee8eb3e1c8c90e9c6483b997d45 (diff) |
Windows: Improve hidpi style drawing and metrics
Follow-up change from enabling DPI awareness, which
caused some style elements (for instance check boxes)
to be rendered incorrectly on non-primary displays,
when there is a difference in DPI between displays.
Use two approaches to get system metrics and themes:
* Use forDpi() API variants and query at 96 DPI for style
metrics, that are in device independent pixels. These are
metrics which are used for layout calculations.
* Get theme metrics at the target display DPI, and scale
to device independent pixels when needed. This is used
for OpenThemeData(), since this theme is used for drawing
as well and needs to be in device pixels.
One approach is not used any more:
* Get metrics for the main display, and scale by the ratio
between the main and target display.
Change the theme cache to cache themes per window handle (HWND).
This is required since OpenThemeData() returns theme data for
a specific DPI, which means we can no longer use a shared
cache.
Clear the cache on theme change, DPI change, and when
the window is destroyed. This handles cache invalidation
when the window is moved to a different screen, and also
when the DPI for a screen is changed.
Move the cache implementation to QWindowsStyleSupport
in QtGui, where it can be accessed by both the style and
windows platform plugins.
Task-number: QTBUG-110681
Change-Id: I5a4ff3a3753762bad8a51d08e51e8013bc7816a1
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Jøger Hansegård <joger.hansegard@qt.io>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Diffstat (limited to 'src/widgets/styles/qwindowsstyle.cpp')
-rw-r--r-- | src/widgets/styles/qwindowsstyle.cpp | 36 |
1 files changed, 14 insertions, 22 deletions
diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp index 8f3d9d6d9a..8fa44e5796 100644 --- a/src/widgets/styles/qwindowsstyle.cpp +++ b/src/widgets/styles/qwindowsstyle.cpp @@ -262,29 +262,33 @@ void QWindowsStyle::polish(QPalette &pal) int QWindowsStylePrivate::pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *, const QWidget *widget) { #if defined(Q_OS_WIN) + // The pixel metrics are in device indepentent pixels; + // hardcode DPI to 1x 96 DPI. + const int dpi = 96; + switch (pm) { case QStyle::PM_DockWidgetFrameWidth: - return GetSystemMetrics(SM_CXFRAME); + return GetSystemMetricsForDpi(SM_CXFRAME, dpi); case QStyle::PM_TitleBarHeight: { const int resizeBorderThickness = - GetSystemMetrics(SM_CXSIZEFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER); + GetSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) + GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi); if (widget && (widget->windowType() == Qt::Tool)) - return GetSystemMetrics(SM_CYSMCAPTION) + resizeBorderThickness; - return GetSystemMetrics(SM_CYCAPTION) + resizeBorderThickness; + return GetSystemMetricsForDpi(SM_CYSMCAPTION, dpi) + resizeBorderThickness; + return GetSystemMetricsForDpi(SM_CYCAPTION, dpi) + resizeBorderThickness; } case QStyle::PM_ScrollBarExtent: { NONCLIENTMETRICS ncm; - ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT); - if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0)) + ncm.cbSize = sizeof(NONCLIENTMETRICS); + if (SystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0, dpi)) return qMax(ncm.iScrollHeight, ncm.iScrollWidth); } break; case QStyle::PM_MdiSubWindowFrameWidth: - return GetSystemMetrics(SM_CYFRAME); + return GetSystemMetricsForDpi(SM_CYFRAME, dpi); default: break; @@ -356,22 +360,10 @@ static QScreen *screenOf(const QWidget *w) } // Calculate the overall scale factor to obtain Qt Device Independent -// Pixels from a native Windows size. Divide by devicePixelRatio -// and account for secondary screens with differing logical DPI. +// Pixels from a native Windows size. qreal QWindowsStylePrivate::nativeMetricScaleFactor(const QWidget *widget) { - qreal scale = QHighDpiScaling::factor(screenOf(widget)); - qreal result = qreal(1) / scale; - if (QGuiApplicationPrivate::screen_list.size() > 1) { - const QScreen *primaryScreen = QGuiApplication::primaryScreen(); - const QScreen *screen = screenOf(widget); - if (screen != primaryScreen) { - qreal primaryScale = QHighDpiScaling::factor(primaryScreen); - if (!qFuzzyCompare(scale, primaryScale)) - result *= scale / primaryScale; - } - } - return result; + return qreal(1) / QHighDpiScaling::factor(screenOf(widget)); } /*! @@ -381,7 +373,7 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW { int ret = QWindowsStylePrivate::pixelMetricFromSystemDp(pm, opt, widget); if (ret != QWindowsStylePrivate::InvalidMetric) - return qRound(qreal(ret) * QWindowsStylePrivate::nativeMetricScaleFactor(widget)); + return ret; ret = QWindowsStylePrivate::fixedPixelMetric(pm); if (ret != QWindowsStylePrivate::InvalidMetric) |