diff --git a/3rdparty/ext_qt/0030-Windows-QPA-Make-the-expected-screen-be-in-sync-with.patch b/3rdparty/ext_qt/0030-Windows-QPA-Make-the-expected-screen-be-in-sync-with.patch new file mode 100644 --- /dev/null +++ b/3rdparty/ext_qt/0030-Windows-QPA-Make-the-expected-screen-be-in-sync-with.patch @@ -0,0 +1,59 @@ +From e553433c3dfa2664140a2ccf4b479821fc382e83 Mon Sep 17 00:00:00 2001 +From: Andy Shaw +Date: Fri, 21 Dec 2018 15:53:57 +0100 +Subject: [PATCH 30/36] Windows QPA: Make the expected screen be in sync with + the geometry changes + +When the window moves to a new screen then we should ensure the screen +is updated at that point with the new size so it can account for any +scaling changes. + +This reverts f1ec81b543fe1d5090acff298e24faf10a7bac63. + +Change-Id: I2be3aab677c4677841a07beaaf373f498483b320 +Fixes: QTBUG-72504 +Reviewed-by: Friedemann Kleint +--- + src/plugins/platforms/windows/qwindowswindow.cpp | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp +index 910d8dd209..865874846e 100644 +--- a/src/plugins/platforms/windows/qwindowswindow.cpp ++++ b/src/plugins/platforms/windows/qwindowswindow.cpp +@@ -1756,15 +1756,12 @@ void QWindowsWindow::checkForScreenChanged() + + QPlatformScreen *currentScreen = screen(); + const auto &screenManager = QWindowsContext::instance()->screenManager(); +- // QTBUG-62971: When dragging a window by its border, detect by mouse position +- // to prevent it from oscillating between screens when it resizes +- const QWindowsScreen *newScreen = testFlag(ResizeMoveActive) +- ? screenManager.screenAtDp(QWindowsCursor::mousePosition()) +- : screenManager.screenForHwnd(m_data.hwnd); ++ const QWindowsScreen *newScreen = screenManager.screenForHwnd(m_data.hwnd); + if (newScreen != nullptr && newScreen != currentScreen) { + qCDebug(lcQpaWindows).noquote().nospace() << __FUNCTION__ + << ' ' << window() << " \"" << currentScreen->name() + << "\"->\"" << newScreen->name() << '"'; ++ setFlag(SynchronousGeometryChangeEvent); + QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); + } + } +@@ -1783,11 +1780,14 @@ void QWindowsWindow::handleGeometryChange() + fireExpose(QRect(QPoint(0, 0), m_data.geometry.size()), true); + } + ++ const bool wasSync = testFlag(SynchronousGeometryChangeEvent); + checkForScreenChanged(); + + if (testFlag(SynchronousGeometryChangeEvent)) + QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); + ++ if (!wasSync) ++ clearFlag(SynchronousGeometryChangeEvent); + qCDebug(lcQpaEvents) << __FUNCTION__ << this << window() << m_data.geometry; + } + +-- +2.18.0.windows.1 + diff --git a/3rdparty/ext_qt/0031-Compute-logical-DPI-on-a-per-screen-basis.patch b/3rdparty/ext_qt/0031-Compute-logical-DPI-on-a-per-screen-basis.patch new file mode 100644 --- /dev/null +++ b/3rdparty/ext_qt/0031-Compute-logical-DPI-on-a-per-screen-basis.patch @@ -0,0 +1,115 @@ +From 676320297d7e5654cbe66fe4bd86125824e05840 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= +Date: Mon, 25 Apr 2016 09:27:48 +0200 +Subject: [PATCH 31/36] Compute logical DPI on a per-screen basis + +The logical DPI reported to applications is the platform screen +logical DPI divided by the platform screen scale factor. + +Use the screen in question when calculating the DPI instead of +the values from the main screen. + +QHighDpiScaling::logicalDpi now takes a QScreen pointer. + +Done-with: Friedemann Kleint +Task-number: QTBUG-53022 +Change-Id: I0f62b5878c37e3488e9a8cc48aef183ff822d0c4 +--- + src/gui/kernel/qhighdpiscaling.cpp | 20 +++++++++----------- + src/gui/kernel/qhighdpiscaling_p.h | 2 +- + src/gui/kernel/qscreen.cpp | 6 +++--- + 3 files changed, 13 insertions(+), 15 deletions(-) + +diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp +index 22e46e0851..541d4f12af 100644 +--- a/src/gui/kernel/qhighdpiscaling.cpp ++++ b/src/gui/kernel/qhighdpiscaling.cpp +@@ -224,7 +224,6 @@ bool QHighDpiScaling::m_usePixelDensity = false; // use scale factor from platfo + bool QHighDpiScaling::m_pixelDensityScalingActive = false; // pixel density scale factor > 1 + bool QHighDpiScaling::m_globalScalingActive = false; // global scale factor is active + bool QHighDpiScaling::m_screenFactorSet = false; // QHighDpiScaling::setScreenFactor has been used +-QDpi QHighDpiScaling::m_logicalDpi = QDpi(-1,-1); // The scaled logical DPI of the primary screen + + /* + Initializes the QHighDpiScaling global variables. Called before the +@@ -312,14 +311,6 @@ void QHighDpiScaling::updateHighDpiScaling() + } + } + m_active = m_globalScalingActive || m_screenFactorSet || m_pixelDensityScalingActive; +- +- QScreen *primaryScreen = QGuiApplication::primaryScreen(); +- if (!primaryScreen) +- return; +- QPlatformScreen *platformScreen = primaryScreen->handle(); +- qreal sf = screenSubfactor(platformScreen); +- QDpi primaryDpi = platformScreen->logicalDpi(); +- m_logicalDpi = QDpi(primaryDpi.first / sf, primaryDpi.second / sf); + } + + /* +@@ -405,9 +396,16 @@ qreal QHighDpiScaling::screenSubfactor(const QPlatformScreen *screen) + return factor; + } + +-QDpi QHighDpiScaling::logicalDpi() ++QDpi QHighDpiScaling::logicalDpi(const QScreen *screen) + { +- return m_logicalDpi; ++ // (Note: m_active test is performed at call site.) ++ if (!screen) ++ return QDpi(96, 96); ++ ++ qreal platformScreenfactor = screenSubfactor(screen->handle()); ++ QDpi platformScreenDpi = screen->handle()->logicalDpi(); ++ return QDpi(platformScreenDpi.first / platformScreenfactor, ++ platformScreenDpi.second / platformScreenfactor); + } + + qreal QHighDpiScaling::factor(const QScreen *screen) +diff --git a/src/gui/kernel/qhighdpiscaling_p.h b/src/gui/kernel/qhighdpiscaling_p.h +index 83fc9452c5..ecd9ed6515 100644 +--- a/src/gui/kernel/qhighdpiscaling_p.h ++++ b/src/gui/kernel/qhighdpiscaling_p.h +@@ -85,7 +85,7 @@ public: + static QPoint origin(const QPlatformScreen *platformScreen); + static QPoint mapPositionFromNative(const QPoint &pos, const QPlatformScreen *platformScreen); + static QPoint mapPositionToNative(const QPoint &pos, const QPlatformScreen *platformScreen); +- static QDpi logicalDpi(); ++ static QDpi logicalDpi(const QScreen *screen); + + private: + static qreal screenSubfactor(const QPlatformScreen *screen); +diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp +index f208eb02be..82ee62e6b4 100644 +--- a/src/gui/kernel/qscreen.cpp ++++ b/src/gui/kernel/qscreen.cpp +@@ -279,7 +279,7 @@ qreal QScreen::logicalDotsPerInchX() const + { + Q_D(const QScreen); + if (QHighDpiScaling::isActive()) +- return QHighDpiScaling::logicalDpi().first; ++ return QHighDpiScaling::logicalDpi(this).first; + return d->logicalDpi.first; + } + +@@ -295,7 +295,7 @@ qreal QScreen::logicalDotsPerInchY() const + { + Q_D(const QScreen); + if (QHighDpiScaling::isActive()) +- return QHighDpiScaling::logicalDpi().second; ++ return QHighDpiScaling::logicalDpi(this).second; + return d->logicalDpi.second; + } + +@@ -314,7 +314,7 @@ qreal QScreen::logicalDotsPerInchY() const + qreal QScreen::logicalDotsPerInch() const + { + Q_D(const QScreen); +- QDpi dpi = QHighDpiScaling::isActive() ? QHighDpiScaling::logicalDpi() : d->logicalDpi; ++ QDpi dpi = QHighDpiScaling::isActive() ? QHighDpiScaling::logicalDpi(this) : d->logicalDpi; + return (dpi.first + dpi.second) * qreal(0.5); + } + +-- +2.18.0.windows.1 + diff --git a/3rdparty/ext_qt/0032-Update-Dpi-and-scale-factor-computation.patch b/3rdparty/ext_qt/0032-Update-Dpi-and-scale-factor-computation.patch new file mode 100644 --- /dev/null +++ b/3rdparty/ext_qt/0032-Update-Dpi-and-scale-factor-computation.patch @@ -0,0 +1,554 @@ +From 3ef20bcb114c316efb74a0a704e918731847620c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= +Date: Mon, 25 Apr 2016 11:31:34 +0200 +Subject: [PATCH 32/36] Update Dpi and scale factor computation + +Remove pixelScale() in favor of logicalBaseDpi(). Compute scale factor +based on logical DPI and logical base DPI, or optionally based on the +physical DPI. + +Add policies for running the scale factor and adjusting the logical +DPI reported to the application. The policies are set via environment +variables: + + QT_SCALE_FACTOR_ROUNDING_POLICY=Round|Ceil|Floor|RoundPreferFloor|PassThrough + QT_DPI_ADJUSTMENT_POLICY=AdjustDpi|DontAdjustDpi|AdjustUpOnly + QT_USE_PHYSICAL_DPI=0|1 + +Done-with: Friedemann Kleint +Task-number: QTBUG-53022 +Change-Id: I4846f223186df665eb0a9c827eaef0a96d1f458f +--- + src/gui/kernel/qhighdpiscaling.cpp | 234 ++++++++++++++++-- + src/gui/kernel/qhighdpiscaling_p.h | 29 +++ + src/gui/kernel/qplatformscreen.cpp | 14 ++ + src/gui/kernel/qplatformscreen.h | 1 + + .../android/qandroidplatformscreen.cpp | 8 +- + .../android/qandroidplatformscreen.h | 2 +- + src/plugins/platforms/cocoa/qcocoascreen.h | 1 + + .../platforms/windows/qwindowsscreen.cpp | 9 - + .../platforms/windows/qwindowsscreen.h | 2 +- + src/plugins/platforms/xcb/qxcbscreen.cpp | 11 - + src/plugins/platforms/xcb/qxcbscreen.h | 3 +- + tests/manual/highdpi/highdpi.pro | 1 + + 12 files changed, 264 insertions(+), 51 deletions(-) + +diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp +index 541d4f12af..ae531569ce 100644 +--- a/src/gui/kernel/qhighdpiscaling.cpp ++++ b/src/gui/kernel/qhighdpiscaling.cpp +@@ -44,6 +44,9 @@ + #include "private/qscreen_p.h" + + #include ++#include ++ ++#include + + QT_BEGIN_NAMESPACE + +@@ -54,6 +57,18 @@ static const char legacyDevicePixelEnvVar[] = "QT_DEVICE_PIXEL_RATIO"; + static const char scaleFactorEnvVar[] = "QT_SCALE_FACTOR"; + static const char autoScreenEnvVar[] = "QT_AUTO_SCREEN_SCALE_FACTOR"; + static const char screenFactorsEnvVar[] = "QT_SCREEN_SCALE_FACTORS"; ++static const char scaleFactorRoundingPolicyEnvVar[] = "QT_SCALE_FACTOR_ROUNDING_POLICY"; ++static const char dpiAdjustmentPolicyEnvVar[] = "QT_DPI_ADJUSTMENT_POLICY"; ++static const char usePhysicalDpiEnvVar[] = "QT_USE_PHYSICAL_DPI"; ++ ++// Reads and interprets the given environment variable as a bool, ++// returns the default value if not set. ++static bool qEnvironmentVariableAsBool(const char *name, bool defaultValue) ++{ ++ bool ok = false; ++ int value = qEnvironmentVariableIntValue(name, &ok); ++ return ok ? value > 0 : defaultValue; ++} + + static inline qreal initialGlobalScaleFactor() + { +@@ -247,6 +262,191 @@ static inline bool usePixelDensity() + qgetenv(legacyDevicePixelEnvVar).compare("auto", Qt::CaseInsensitive) == 0); + } + ++qreal QHighDpiScaling::rawScaleFactor(const QPlatformScreen *screen) ++{ ++ // Determine if physical DPI should be used ++ static bool usePhysicalDpi = qEnvironmentVariableAsBool(usePhysicalDpiEnvVar, false); ++ ++ // Calculate scale factor beased on platform screen DPI values ++ qreal factor; ++ QDpi platformBaseDpi = screen->logicalBaseDpi(); ++ if (usePhysicalDpi) { ++ qreal platformPhysicalDpi = screen->screen()->physicalDotsPerInch(); ++ factor = qreal(platformPhysicalDpi) / qreal(platformBaseDpi.first); ++ } else { ++ QDpi platformLogicalDpi = screen->logicalDpi(); ++ factor = qreal(platformLogicalDpi.first) / qreal(platformBaseDpi.first); ++ } ++ ++ return factor; ++} ++ ++template ++struct EnumLookup ++{ ++ const char *name; ++ EnumType value; ++}; ++ ++template ++static bool operator==(const EnumLookup &e1, const EnumLookup &e2) ++{ ++ return qstricmp(e1.name, e2.name) == 0; ++} ++ ++template ++static QByteArray joinEnumValues(const EnumLookup *i1, const EnumLookup *i2) ++{ ++ QByteArray result; ++ for (; i1 < i2; ++i1) { ++ if (!result.isEmpty()) ++ result += QByteArrayLiteral(", "); ++ result += i1->name; ++ } ++ return result; ++} ++ ++using ScaleFactorRoundingPolicyLookup = EnumLookup; ++ ++static const ScaleFactorRoundingPolicyLookup scaleFactorRoundingPolicyLookup[] = ++{ ++ {"Round", QHighDpiScaling::HighDpiScaleFactorRoundingPolicy::Round}, ++ {"Ceil", QHighDpiScaling::HighDpiScaleFactorRoundingPolicy::Ceil}, ++ {"Floor", QHighDpiScaling::HighDpiScaleFactorRoundingPolicy::Floor}, ++ {"RoundPreferFloor", QHighDpiScaling::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor}, ++ {"PassThrough", QHighDpiScaling::HighDpiScaleFactorRoundingPolicy::PassThrough} ++}; ++ ++static QHighDpiScaling::HighDpiScaleFactorRoundingPolicy ++ lookupScaleFactorRoundingPolicy(const QByteArray &v) ++{ ++ auto end = std::end(scaleFactorRoundingPolicyLookup); ++ auto it = std::find(std::begin(scaleFactorRoundingPolicyLookup), end, ++ ScaleFactorRoundingPolicyLookup{v.constData(), QHighDpiScaling::HighDpiScaleFactorRoundingPolicy::NotSet}); ++ return it != end ? it->value : QHighDpiScaling::HighDpiScaleFactorRoundingPolicy::NotSet; ++} ++ ++using DpiAdjustmentPolicyLookup = EnumLookup; ++ ++static const DpiAdjustmentPolicyLookup dpiAdjustmentPolicyLookup[] = ++{ ++ {"AdjustDpi", QHighDpiScaling::DpiAdjustmentPolicy::Enabled}, ++ {"DontAdjustDpi", QHighDpiScaling::DpiAdjustmentPolicy::Disabled}, ++ {"AdjustUpOnly", QHighDpiScaling::DpiAdjustmentPolicy::UpOnly} ++}; ++ ++static QHighDpiScaling::DpiAdjustmentPolicy ++ lookupDpiAdjustmentPolicy(const QByteArray &v) ++{ ++ auto end = std::end(dpiAdjustmentPolicyLookup); ++ auto it = std::find(std::begin(dpiAdjustmentPolicyLookup), end, ++ DpiAdjustmentPolicyLookup{v.constData(), QHighDpiScaling::DpiAdjustmentPolicy::NotSet}); ++ return it != end ? it->value : QHighDpiScaling::DpiAdjustmentPolicy::NotSet; ++} ++ ++qreal QHighDpiScaling::roundScaleFactor(qreal rawFactor) ++{ ++ // Apply scale factor rounding policy. Using mathematically correct rounding ++ // may not give the most desirable visual results, especially for ++ // critical fractions like .5. In general, rounding down results in visual ++ // sizes that are smaller than the ideal size, and opposite for rounding up. ++ // Rounding down is then preferable since "small UI" is a more acceptable ++ // high-DPI experience than "large UI". ++ static auto scaleFactorRoundingPolicy = HighDpiScaleFactorRoundingPolicy::NotSet; ++ ++ // Determine rounding policy ++ if (scaleFactorRoundingPolicy == HighDpiScaleFactorRoundingPolicy::NotSet) { ++ // Check environment ++ if (qEnvironmentVariableIsSet(scaleFactorRoundingPolicyEnvVar)) { ++ QByteArray policyText = qgetenv(scaleFactorRoundingPolicyEnvVar); ++ auto policyEnumValue = lookupScaleFactorRoundingPolicy(policyText); ++ if (policyEnumValue != HighDpiScaleFactorRoundingPolicy::NotSet) { ++ scaleFactorRoundingPolicy = policyEnumValue; ++ } else { ++ auto values = joinEnumValues(std::begin(scaleFactorRoundingPolicyLookup), ++ std::end(scaleFactorRoundingPolicyLookup)); ++ qWarning("Unknown scale factor rounding policy: %s. Supported values are: %s.", ++ policyText.constData(), values.constData()); ++ } ++ } else { ++ // Set default policy if no environment variable is set. ++ scaleFactorRoundingPolicy = HighDpiScaleFactorRoundingPolicy::RoundPreferFloor; ++ } ++ } ++ ++ // Apply rounding policy. ++ qreal roundedFactor = rawFactor; ++ switch (scaleFactorRoundingPolicy) { ++ case HighDpiScaleFactorRoundingPolicy::Round: ++ roundedFactor = qRound(rawFactor); ++ break; ++ case HighDpiScaleFactorRoundingPolicy::Ceil: ++ roundedFactor = qCeil(rawFactor); ++ break; ++ case HighDpiScaleFactorRoundingPolicy::Floor: ++ roundedFactor = qFloor(rawFactor); ++ break; ++ case HighDpiScaleFactorRoundingPolicy::RoundPreferFloor: ++ // Round up for .75 and higher. This favors "small UI" over "large UI". ++ roundedFactor = rawFactor - qFloor(rawFactor) < 0.75 ++ ? qFloor(rawFactor) : qCeil(rawFactor); ++ break; ++ case HighDpiScaleFactorRoundingPolicy::PassThrough: ++ case HighDpiScaleFactorRoundingPolicy::NotSet: ++ break; ++ } ++ ++ // Don't round down to to zero; clamp the minimum (rounded) factor to 1. ++ // This is not a common case but can happen if a display reports a very ++ // low DPI. ++ if (scaleFactorRoundingPolicy != HighDpiScaleFactorRoundingPolicy::PassThrough) ++ roundedFactor = qMax(roundedFactor, qreal(1)); ++ ++ return roundedFactor; ++} ++ ++QDpi QHighDpiScaling::effectiveLogicalDpi(const QPlatformScreen *screen, qreal rawFactor, qreal roundedFactor) ++{ ++ // Apply DPI adjustment policy, if needed. If enabled this will change ++ // the reported logical DPI to account for the difference between the ++ // rounded scale factor and the actual scale factor. The effect ++ // is that text size will be correct for the screen dpi, but may be (slightly) ++ // out of sync with the rest of the UI. The amount of out-of-synch-ness ++ // depends on how well user code handles a non-standard DPI values, but ++ // since the adjustment is small (typically +/- 48 max) this might be OK. ++ static auto dpiAdjustmentPolicy = DpiAdjustmentPolicy::NotSet; ++ ++ // Determine adjustment policy. ++ if (dpiAdjustmentPolicy == DpiAdjustmentPolicy::NotSet) { ++ if (qEnvironmentVariableIsSet(dpiAdjustmentPolicyEnvVar)) { ++ QByteArray policyText = qgetenv(dpiAdjustmentPolicyEnvVar); ++ auto policyEnumValue = lookupDpiAdjustmentPolicy(policyText); ++ if (policyEnumValue != DpiAdjustmentPolicy::NotSet) { ++ dpiAdjustmentPolicy = policyEnumValue; ++ } else { ++ auto values = joinEnumValues(std::begin(dpiAdjustmentPolicyLookup), ++ std::end(dpiAdjustmentPolicyLookup)); ++ qWarning("Unknown DPI adjustment policy: %s. Supported values are: %s.", ++ policyText.constData(), values.constData()); ++ } ++ } ++ if (dpiAdjustmentPolicy == DpiAdjustmentPolicy::NotSet) ++ dpiAdjustmentPolicy = DpiAdjustmentPolicy::UpOnly; ++ } ++ ++ // Apply adjustment policy. ++ const QDpi baseDpi = screen->logicalBaseDpi(); ++ const qreal dpiAdjustmentFactor = rawFactor / roundedFactor; ++ ++ // Return the base DPI for cases where there is no adjustment ++ if (dpiAdjustmentPolicy == DpiAdjustmentPolicy::Disabled) ++ return baseDpi; ++ if (dpiAdjustmentPolicy == DpiAdjustmentPolicy::UpOnly && dpiAdjustmentFactor < 1) ++ return baseDpi; ++ ++ return QDpi(baseDpi.first * dpiAdjustmentFactor, baseDpi.second * dpiAdjustmentFactor); ++} ++ + void QHighDpiScaling::initHighDpiScaling() + { + // Determine if there is a global scale factor set. +@@ -257,8 +457,6 @@ void QHighDpiScaling::initHighDpiScaling() + + m_pixelDensityScalingActive = false; //set in updateHighDpiScaling below + +- // we update m_active in updateHighDpiScaling, but while we create the +- // screens, we have to assume that m_usePixelDensity implies scaling + m_active = m_globalScalingActive || m_usePixelDensity; + } + +@@ -310,7 +508,7 @@ void QHighDpiScaling::updateHighDpiScaling() + ++i; + } + } +- m_active = m_globalScalingActive || m_screenFactorSet || m_pixelDensityScalingActive; ++ m_active = m_globalScalingActive || m_usePixelDensity; + } + + /* +@@ -371,22 +569,8 @@ qreal QHighDpiScaling::screenSubfactor(const QPlatformScreen *screen) + { + qreal factor = qreal(1.0); + if (screen) { +- if (m_usePixelDensity) { +- qreal pixelDensity = screen->pixelDensity(); +- +- // Pixel density reported by the screen is sometimes not precise enough, +- // so recalculate it: divide px (physical pixels) by dp (device-independent pixels) +- // for both width and height, and then use the average if it is different from +- // the one initially reported by the screen +- QRect screenGeometry = screen->geometry(); +- qreal wFactor = qreal(screenGeometry.width()) / qRound(screenGeometry.width() / pixelDensity); +- qreal hFactor = qreal(screenGeometry.height()) / qRound(screenGeometry.height() / pixelDensity); +- qreal averageDensity = (wFactor + hFactor) / 2; +- if (!qFuzzyCompare(pixelDensity, averageDensity)) +- pixelDensity = averageDensity; +- +- factor *= pixelDensity; +- } ++ if (m_usePixelDensity) ++ factor *= roundScaleFactor(rawScaleFactor(screen)); + if (m_screenFactorSet) { + QVariant screenFactor = screen->screen()->property(scaleFactorProperty); + if (screenFactor.isValid()) +@@ -399,13 +583,15 @@ qreal QHighDpiScaling::screenSubfactor(const QPlatformScreen *screen) + QDpi QHighDpiScaling::logicalDpi(const QScreen *screen) + { + // (Note: m_active test is performed at call site.) +- if (!screen) ++ if (!screen || !screen->handle()) + return QDpi(96, 96); + +- qreal platformScreenfactor = screenSubfactor(screen->handle()); +- QDpi platformScreenDpi = screen->handle()->logicalDpi(); +- return QDpi(platformScreenDpi.first / platformScreenfactor, +- platformScreenDpi.second / platformScreenfactor); ++ if (!m_usePixelDensity) ++ return screen->handle()->logicalDpi(); ++ ++ const qreal scaleFactor = rawScaleFactor(screen->handle()); ++ const qreal roundedScaleFactor = roundScaleFactor(scaleFactor); ++ return effectiveLogicalDpi(screen->handle(), scaleFactor, roundedScaleFactor); + } + + qreal QHighDpiScaling::factor(const QScreen *screen) +diff --git a/src/gui/kernel/qhighdpiscaling_p.h b/src/gui/kernel/qhighdpiscaling_p.h +index ecd9ed6515..55bddfeb88 100644 +--- a/src/gui/kernel/qhighdpiscaling_p.h ++++ b/src/gui/kernel/qhighdpiscaling_p.h +@@ -71,7 +71,33 @@ typedef QPair QDpi; + + #ifndef QT_NO_HIGHDPISCALING + class Q_GUI_EXPORT QHighDpiScaling { ++ Q_GADGET + public: ++ enum class HighDpiScaleFactorRoundingPolicy { ++ NotSet, ++ Round, ++ Ceil, ++ Floor, ++ RoundPreferFloor, ++ PassThrough ++ }; ++ Q_ENUM(HighDpiScaleFactorRoundingPolicy) ++ ++ enum class DpiAdjustmentPolicy { ++ NotSet, ++ Enabled, ++ Disabled, ++ UpOnly ++ }; ++ Q_ENUM(DpiAdjustmentPolicy) ++ ++ QHighDpiScaling() = delete; ++ ~QHighDpiScaling() = delete; ++ QHighDpiScaling(const QHighDpiScaling &) = delete; ++ QHighDpiScaling &operator=(const QHighDpiScaling &) = delete; ++ QHighDpiScaling(QHighDpiScaling &&) = delete; ++ QHighDpiScaling &operator=(QHighDpiScaling &&) = delete; ++ + static void initHighDpiScaling(); + static void updateHighDpiScaling(); + static void setGlobalFactor(qreal factor); +@@ -88,6 +114,9 @@ public: + static QDpi logicalDpi(const QScreen *screen); + + 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 qreal m_factor; +diff --git a/src/gui/kernel/qplatformscreen.cpp b/src/gui/kernel/qplatformscreen.cpp +index b7b312e89e..07a2231228 100644 +--- a/src/gui/kernel/qplatformscreen.cpp ++++ b/src/gui/kernel/qplatformscreen.cpp +@@ -194,6 +194,20 @@ QDpi QPlatformScreen::logicalDpi() const + 25.4 * s.height() / ps.height()); + } + ++/*! ++ Reimplement to return the base logical DPI for the platform. This ++ DPI value should correspond to a standard-DPI (1x) display. The ++ default implementation returns 96. ++ ++ QtGui will use this value (together with logicalDpi) to compute ++ the scale factor when high-DPI scaling is enabled: ++ factor = logicalDPI / baseDPI ++*/ ++QDpi QPlatformScreen::logicalBaseDpi() const ++{ ++ return QDpi(96, 96); ++} ++ + /*! + Reimplement this function in subclass to return the device pixel ratio + for the screen. This is the ratio between physical pixels and the +diff --git a/src/gui/kernel/qplatformscreen.h b/src/gui/kernel/qplatformscreen.h +index e9d64c8a29..63b5d5a4a7 100644 +--- a/src/gui/kernel/qplatformscreen.h ++++ b/src/gui/kernel/qplatformscreen.h +@@ -113,6 +113,7 @@ public: + + virtual QSizeF physicalSize() const; + virtual QDpi logicalDpi() const; ++ virtual QDpi logicalBaseDpi() const; + virtual qreal devicePixelRatio() const; + virtual qreal pixelDensity() const; + +diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp +index 7dc8bb8080..80757c2135 100644 +--- a/src/plugins/platforms/android/qandroidplatformscreen.cpp ++++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp +@@ -401,15 +401,17 @@ void QAndroidPlatformScreen::doRedraw() + m_dirtyRect = QRect(); + } + ++static const int androidLogicalDpi = 72; ++ + QDpi QAndroidPlatformScreen::logicalDpi() const + { +- qreal lDpi = QtAndroid::scaledDensity() * 72; ++ qreal lDpi = QtAndroid::scaledDensity() * androidLogicalDpi; + return QDpi(lDpi, lDpi); + } + +-qreal QAndroidPlatformScreen::pixelDensity() const ++QDpi QAndroidPlatformScreen::logicalBaseDpi() const + { +- return QtAndroid::pixelDensity(); ++ return QDpi(androidLogicalDpi, androidLogicalDpi); + } + + Qt::ScreenOrientation QAndroidPlatformScreen::orientation() const +diff --git a/src/plugins/platforms/android/qandroidplatformscreen.h b/src/plugins/platforms/android/qandroidplatformscreen.h +index f15aeae3fd..5dc158e351 100644 +--- a/src/plugins/platforms/android/qandroidplatformscreen.h ++++ b/src/plugins/platforms/android/qandroidplatformscreen.h +@@ -103,7 +103,7 @@ protected: + + private: + QDpi logicalDpi() const override; +- qreal pixelDensity() const override; ++ QDpi logicalBaseDpi() const override; + Qt::ScreenOrientation orientation() const override; + Qt::ScreenOrientation nativeOrientation() const override; + void surfaceChanged(JNIEnv *env, jobject surface, int w, int h) override; +diff --git a/src/plugins/platforms/cocoa/qcocoascreen.h b/src/plugins/platforms/cocoa/qcocoascreen.h +index 9ded98df32..a73b97c771 100644 +--- a/src/plugins/platforms/cocoa/qcocoascreen.h ++++ b/src/plugins/platforms/cocoa/qcocoascreen.h +@@ -64,6 +64,7 @@ public: + qreal devicePixelRatio() const override; + QSizeF physicalSize() const override { return m_physicalSize; } + QDpi logicalDpi() const override { return m_logicalDpi; } ++ QDpi logicalBaseDpi() const override { return m_logicalDpi; } + qreal refreshRate() const override { return m_refreshRate; } + QString name() const override { return m_name; } + QPlatformCursor *cursor() const override { return m_cursor; } +diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp +index 8a5f0e6577..ebde684038 100644 +--- a/src/plugins/platforms/windows/qwindowsscreen.cpp ++++ b/src/plugins/platforms/windows/qwindowsscreen.cpp +@@ -254,15 +254,6 @@ QWindow *QWindowsScreen::windowAt(const QPoint &screenPoint, unsigned flags) + return result; + } + +-qreal QWindowsScreen::pixelDensity() const +-{ +- // QTBUG-49195: Use logical DPI instead of physical DPI to calculate +- // the pixel density since it is reflects the Windows UI scaling. +- // High DPI auto scaling should be disabled when the user chooses +- // small fonts on a High DPI monitor, resulting in lower logical DPI. +- return qMax(1, qRound(logicalDpi().first / 96)); +-} +- + /*! + \brief Determine siblings in a virtual desktop system. + +diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h +index 33c9effa2a..a7b1c64e29 100644 +--- a/src/plugins/platforms/windows/qwindowsscreen.h ++++ b/src/plugins/platforms/windows/qwindowsscreen.h +@@ -87,7 +87,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; } +- qreal pixelDensity() const override; ++ QDpi logicalBaseDpi() const override { return QDpi(96, 96); }; + qreal devicePixelRatio() const override { return 1.0; } + qreal refreshRate() const override { return m_data.refreshRateHz; } + QString name() const override { return m_data.name; } +diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp +index 57dbdc9bec..9af0794d29 100644 +--- a/src/plugins/platforms/xcb/qxcbscreen.cpp ++++ b/src/plugins/platforms/xcb/qxcbscreen.cpp +@@ -671,11 +671,6 @@ QDpi QXcbScreen::logicalDpi() const + return m_virtualDesktop->dpi(); + } + +-qreal QXcbScreen::pixelDensity() const +-{ +- return m_pixelDensity; +-} +- + QPlatformCursor *QXcbScreen::cursor() const + { + return m_cursor; +@@ -739,12 +734,6 @@ void QXcbScreen::updateGeometry(const QRect &geometry, uint8_t rotation) + if (m_sizeMillimeters.isEmpty()) + m_sizeMillimeters = sizeInMillimeters(geometry.size(), m_virtualDesktop->dpi()); + +- qreal dpi = geometry.width() / physicalSize().width() * qreal(25.4); +- +- // Use 128 as a reference DPI on small screens. This favors "small UI" over "large UI". +- qreal referenceDpi = physicalSize().width() <= 320 ? 128 : 96; +- +- m_pixelDensity = qMax(1, qRound(dpi/referenceDpi)); + m_geometry = geometry; + m_availableGeometry = geometry & m_virtualDesktop->workArea(); + QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), m_geometry, m_availableGeometry); +diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h +index be6c45e415..3f619d71c2 100644 +--- a/src/plugins/platforms/xcb/qxcbscreen.h ++++ b/src/plugins/platforms/xcb/qxcbscreen.h +@@ -161,7 +161,7 @@ public: + QImage::Format format() const override; + QSizeF physicalSize() const override { return m_sizeMillimeters; } + QDpi logicalDpi() const override; +- qreal pixelDensity() const override; ++ QDpi logicalBaseDpi() const override { return QDpi(96, 96); }; + QPlatformCursor *cursor() const override; + qreal refreshRate() const override { return m_refreshRate; } + Qt::ScreenOrientation orientation() const override { return m_orientation; } +@@ -226,7 +226,6 @@ private: + Qt::ScreenOrientation m_orientation = Qt::PrimaryOrientation; + QXcbCursor *m_cursor; + int m_refreshRate = 60; +- int m_pixelDensity = 1; + QEdidParser m_edid; + }; + +diff --git a/tests/manual/highdpi/highdpi.pro b/tests/manual/highdpi/highdpi.pro +index 9db083cd82..2de8ed3bb5 100644 +--- a/tests/manual/highdpi/highdpi.pro ++++ b/tests/manual/highdpi/highdpi.pro +@@ -15,3 +15,4 @@ HEADERS += \ + RESOURCES += \ + highdpi.qrc + ++DEFINES += HAVE_SCREEN_BASE_DPI +-- +2.18.0.windows.1 + diff --git a/3rdparty/ext_qt/0033-Move-QT_FONT_DPI-to-cross-platform-code.patch b/3rdparty/ext_qt/0033-Move-QT_FONT_DPI-to-cross-platform-code.patch new file mode 100644 --- /dev/null +++ b/3rdparty/ext_qt/0033-Move-QT_FONT_DPI-to-cross-platform-code.patch @@ -0,0 +1,133 @@ +From 3f00c3cddb35c4f17100b2becbb99dec4e48b351 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= +Date: Thu, 2 Jun 2016 09:52:21 +0200 +Subject: [PATCH 33/36] Move QT_FONT_DPI to cross-platform code + +This makes it possible to test the effects of setting +Qt::AA_HighDpiScaling/QT_AUTO_SCREEN_SCALE_FACTOR, with different DPI +values on all platforms. + +This also makes it possible to access the actual DPI values reported +by the OS/WS via the QPlatformScreen API. + +A drawback is that there is no single place to check the environment +variable; currently done in three places. This may be +further simplified later on. + +Done-with: Friedemann Kleint +Task-number: QTBUG-53022 +Change-Id: Idd6463219d3ae58fe0ab72c17686cce2eb9dbadd +--- + src/gui/kernel/qhighdpiscaling.cpp | 4 ++-- + src/gui/kernel/qplatformscreen.cpp | 8 ++++++++ + src/gui/kernel/qplatformscreen.h | 2 ++ + src/gui/kernel/qscreen.cpp | 7 +++++-- + src/gui/kernel/qwindowsysteminterface.cpp | 4 ++-- + src/plugins/platforms/xcb/qxcbscreen.cpp | 4 ---- + 6 files changed, 19 insertions(+), 10 deletions(-) + +diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp +index ae531569ce..fc8084c45a 100644 +--- a/src/gui/kernel/qhighdpiscaling.cpp ++++ b/src/gui/kernel/qhighdpiscaling.cpp +@@ -274,7 +274,7 @@ qreal QHighDpiScaling::rawScaleFactor(const QPlatformScreen *screen) + qreal platformPhysicalDpi = screen->screen()->physicalDotsPerInch(); + factor = qreal(platformPhysicalDpi) / qreal(platformBaseDpi.first); + } else { +- QDpi platformLogicalDpi = screen->logicalDpi(); ++ const QDpi platformLogicalDpi = QPlatformScreen::overrideDpi(screen->logicalDpi()); + factor = qreal(platformLogicalDpi.first) / qreal(platformBaseDpi.first); + } + +@@ -587,7 +587,7 @@ QDpi QHighDpiScaling::logicalDpi(const QScreen *screen) + return QDpi(96, 96); + + if (!m_usePixelDensity) +- return screen->handle()->logicalDpi(); ++ return QPlatformScreen::overrideDpi(screen->handle()->logicalDpi()); + + const qreal scaleFactor = rawScaleFactor(screen->handle()); + const qreal roundedScaleFactor = roundScaleFactor(scaleFactor); +diff --git a/src/gui/kernel/qplatformscreen.cpp b/src/gui/kernel/qplatformscreen.cpp +index 07a2231228..54ec211f2c 100644 +--- a/src/gui/kernel/qplatformscreen.cpp ++++ b/src/gui/kernel/qplatformscreen.cpp +@@ -194,6 +194,14 @@ QDpi QPlatformScreen::logicalDpi() const + 25.4 * s.height() / ps.height()); + } + ++// Helper function for accessing the platform screen logical dpi ++// which accounts for QT_FONT_DPI. ++QPair QPlatformScreen::overrideDpi(const QPair &in) ++{ ++ static const int overrideDpi = qEnvironmentVariableIntValue("QT_FONT_DPI"); ++ return overrideDpi > 0 ? QDpi(overrideDpi, overrideDpi) : in; ++} ++ + /*! + Reimplement to return the base logical DPI for the platform. This + DPI value should correspond to a standard-DPI (1x) display. The +diff --git a/src/gui/kernel/qplatformscreen.h b/src/gui/kernel/qplatformscreen.h +index 63b5d5a4a7..32e6bf7ec7 100644 +--- a/src/gui/kernel/qplatformscreen.h ++++ b/src/gui/kernel/qplatformscreen.h +@@ -159,6 +159,8 @@ public: + // The platform screen's geometry in device independent coordinates + QRect deviceIndependentGeometry() const; + ++ static QDpi overrideDpi(const QDpi &in); ++ + protected: + void resizeMaximizedWindows(); + +diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp +index 82ee62e6b4..b856435f67 100644 +--- a/src/gui/kernel/qscreen.cpp ++++ b/src/gui/kernel/qscreen.cpp +@@ -84,8 +84,11 @@ void QScreenPrivate::setPlatformScreen(QPlatformScreen *screen) + platformScreen->d_func()->screen = q; + orientation = platformScreen->orientation(); + geometry = platformScreen->deviceIndependentGeometry(); +- availableGeometry = QHighDpi::fromNative(platformScreen->availableGeometry(), QHighDpiScaling::factor(platformScreen), geometry.topLeft()); +- logicalDpi = platformScreen->logicalDpi(); ++ availableGeometry = QHighDpi::fromNative(platformScreen->availableGeometry(), ++ QHighDpiScaling::factor(platformScreen), geometry.topLeft()); ++ ++ logicalDpi = QPlatformScreen::overrideDpi(platformScreen->logicalDpi()); ++ + refreshRate = platformScreen->refreshRate(); + // safeguard ourselves against buggy platform behavior... + if (refreshRate < 1.0) +diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp +index 5b32405f5e..0bedae1bb4 100644 +--- a/src/gui/kernel/qwindowsysteminterface.cpp ++++ b/src/gui/kernel/qwindowsysteminterface.cpp +@@ -780,8 +780,8 @@ void QWindowSystemInterface::handleScreenGeometryChange(QScreen *screen, const Q + + void QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(QScreen *screen, qreal dpiX, qreal dpiY) + { +- QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent *e = +- new QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent(screen, dpiX, dpiY); // ### tja ++ const QDpi effectiveDpi = QPlatformScreen::overrideDpi(QDpi{dpiX, dpiY}); ++ auto e = new QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent(screen, effectiveDpi.first, effectiveDpi.second); + QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + } + +diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp +index 9af0794d29..27ffcad902 100644 +--- a/src/plugins/platforms/xcb/qxcbscreen.cpp ++++ b/src/plugins/platforms/xcb/qxcbscreen.cpp +@@ -660,10 +660,6 @@ QImage::Format QXcbScreen::format() const + + QDpi QXcbScreen::logicalDpi() const + { +- static const int overrideDpi = qEnvironmentVariableIntValue("QT_FONT_DPI"); +- if (overrideDpi) +- return QDpi(overrideDpi, overrideDpi); +- + const int forcedDpi = m_virtualDesktop->forcedDpi(); + if (forcedDpi > 0) { + return QDpi(forcedDpi, forcedDpi); +-- +2.18.0.windows.1 + diff --git a/3rdparty/ext_qt/0034-Update-QT_SCREEN_SCALE_FACTORS.patch b/3rdparty/ext_qt/0034-Update-QT_SCREEN_SCALE_FACTORS.patch new file mode 100644 --- /dev/null +++ b/3rdparty/ext_qt/0034-Update-QT_SCREEN_SCALE_FACTORS.patch @@ -0,0 +1,155 @@ +From f58ea52d89d9230ab9d441d96f6884044c4c686d Mon Sep 17 00:00:00 2001 +From: Friedemann Kleint +Date: Wed, 27 Feb 2019 08:46:47 +0100 +Subject: [PATCH 34/36] Update QT_SCREEN_SCALE_FACTORS +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Store name->factor associations in a global QHash instead of on the +QScreen object, making them survive QScreen object deletion, for +example on disconnect/ connect cycles. + +Make factors set with QT_SCREEN_SCALE_FACTORS override the screen +factors computed from platform plugin DPI values. This matches the use +case for QT_SCREEN_SCALE_FACTORS (but not the general scale factors +combine by multiplication?rinciple) + +Done-with: Friedemann Kleint +Task-number: QTBUG-53022 +Change-Id: I12771249314ab0c073e609d62f57ac0d18d3b6ce +--- + src/gui/kernel/qhighdpiscaling.cpp | 62 ++++++++++++++++++++++-------- + src/gui/kernel/qhighdpiscaling_p.h | 2 +- + 2 files changed, 47 insertions(+), 17 deletions(-) + +diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp +index fc8084c45a..b1350599b7 100644 +--- a/src/gui/kernel/qhighdpiscaling.cpp ++++ b/src/gui/kernel/qhighdpiscaling.cpp +@@ -61,6 +61,12 @@ static const char scaleFactorRoundingPolicyEnvVar[] = "QT_SCALE_FACTOR_ROUNDING_ + static const char dpiAdjustmentPolicyEnvVar[] = "QT_DPI_ADJUSTMENT_POLICY"; + static const char usePhysicalDpiEnvVar[] = "QT_USE_PHYSICAL_DPI"; + ++// Per-screen scale factors for named screens set with QT_SCREEN_SCALE_FACTORS ++// are stored here. Use a global hash to keep the factor across screen ++// disconnect/connect cycles where the screen object may be deleted. ++typedef QHash QScreenScaleFactorHash; ++Q_GLOBAL_STATIC(QScreenScaleFactorHash, qNamedScreenScaleFactors); ++ + // Reads and interprets the given environment variable as a bool, + // returns the default value if not set. + static bool qEnvironmentVariableAsBool(const char *name, bool defaultValue) +@@ -478,20 +484,19 @@ void QHighDpiScaling::updateHighDpiScaling() + int i = 0; + const auto specs = qgetenv(screenFactorsEnvVar).split(';'); + for (const QByteArray &spec : specs) { +- QScreen *screen = 0; + int equalsPos = spec.lastIndexOf('='); +- double factor = 0; ++ qreal factor = 0; + if (equalsPos > 0) { + // support "name=factor" + QByteArray name = spec.mid(0, equalsPos); + QByteArray f = spec.mid(equalsPos + 1); + bool ok; + factor = f.toDouble(&ok); +- if (ok) { ++ if (ok && factor > 0 ) { + const auto screens = QGuiApplication::screens(); + for (QScreen *s : screens) { + if (s->name() == QString::fromLocal8Bit(name)) { +- screen = s; ++ setScreenFactor(s, factor); + break; + } + } +@@ -500,11 +505,11 @@ void QHighDpiScaling::updateHighDpiScaling() + // listing screens in order + bool ok; + factor = spec.toDouble(&ok); +- if (ok && i < QGuiApplication::screens().count()) +- screen = QGuiApplication::screens().at(i); ++ if (ok && factor > 0 && i < QGuiApplication::screens().count()) { ++ QScreen *screen = QGuiApplication::screens().at(i); ++ setScreenFactor(screen, factor); ++ } + } +- if (screen) +- setScreenFactor(screen, factor); + ++i; + } + } +@@ -540,7 +545,14 @@ void QHighDpiScaling::setScreenFactor(QScreen *screen, qreal factor) + m_screenFactorSet = true; + m_active = true; + } +- screen->setProperty(scaleFactorProperty, QVariant(factor)); ++ ++ // Prefer associating the factor with screen name over the object ++ // since the screen object may be deleted on screen disconnects. ++ const QString name = screen->name(); ++ if (!name.isEmpty()) ++ qNamedScreenScaleFactors()->insert(name, factor); ++ else ++ screen->setProperty(scaleFactorProperty, QVariant(factor)); + + // hack to force re-evaluation of screen geometry + if (screen->handle()) +@@ -568,15 +580,33 @@ QPoint QHighDpiScaling::mapPositionFromNative(const QPoint &pos, const QPlatform + qreal QHighDpiScaling::screenSubfactor(const QPlatformScreen *screen) + { + qreal factor = qreal(1.0); +- if (screen) { +- if (m_usePixelDensity) +- factor *= roundScaleFactor(rawScaleFactor(screen)); +- if (m_screenFactorSet) { +- QVariant screenFactor = screen->screen()->property(scaleFactorProperty); +- if (screenFactor.isValid()) +- factor *= screenFactor.toReal(); ++ if (!screen) ++ return factor; ++ ++ // Unlike the other code where factors are combined ++ // by multiplication, factors from QT_SCREEN_SCALE_FACTORS takes ++ // precedence over the factor computed from platform plugin ++ // DPI. The rationale is that the user is setting the factor ++ // to override erroneous DPI values. ++ bool screenPropertyUsed = false; ++ if (m_screenFactorSet) { ++ // Check if there is a factor set on the screen object or ++ // associated with the screen name. These are mutually ++ // exclusive, so checking order is not significant. ++ QVariant byIndex = screen->screen()->property(scaleFactorProperty); ++ auto byName = qNamedScreenScaleFactors()->find(screen->name()); ++ if (byIndex.isValid()) { ++ screenPropertyUsed = true; ++ factor = byIndex.toReal(); ++ } else if (byName != qNamedScreenScaleFactors()->end()) { ++ screenPropertyUsed = true; ++ factor = *byName; + } + } ++ ++ if (!screenPropertyUsed && m_usePixelDensity) ++ factor = roundScaleFactor(rawScaleFactor(screen)); ++ + return factor; + } + +diff --git a/src/gui/kernel/qhighdpiscaling_p.h b/src/gui/kernel/qhighdpiscaling_p.h +index 55bddfeb88..d3f71854a8 100644 +--- a/src/gui/kernel/qhighdpiscaling_p.h ++++ b/src/gui/kernel/qhighdpiscaling_p.h +@@ -101,7 +101,7 @@ public: + static void initHighDpiScaling(); + static void updateHighDpiScaling(); + static void setGlobalFactor(qreal factor); +- static void setScreenFactor(QScreen *window, qreal factor); ++ static void setScreenFactor(QScreen *screen, qreal factor); + + static bool isActive() { return m_active; } + static qreal factor(const QWindow *window); +-- +2.18.0.windows.1 + diff --git a/3rdparty/ext_qt/0035-Deprecate-QT_AUTO_SCREEN_SCALE_FACTOR.patch b/3rdparty/ext_qt/0035-Deprecate-QT_AUTO_SCREEN_SCALE_FACTOR.patch new file mode 100644 --- /dev/null +++ b/3rdparty/ext_qt/0035-Deprecate-QT_AUTO_SCREEN_SCALE_FACTOR.patch @@ -0,0 +1,101 @@ +From 4fdc698603e5ac3bc0cf107fdf3880ba68dbfb02 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= +Date: Thu, 10 Nov 2016 14:17:53 +0100 +Subject: [PATCH 35/36] Deprecate QT_AUTO_SCREEN_SCALE_FACTOR +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Replace by QT_ENABLE_HIGHDPI_SCALING. + +QT_AUTO_SCREEN_SCALE_FACTOR has the usability problem that it mixes +enabling the high-DPI scaling mode with the method of getting screen +scale factors (?uto??. Due to this, it ends up with a slightly +strange name. + +QT_ENABLE_HIGHDPI_SCALING matches the C++ option +(Qt::AA_EnableHighDPiScaling), and leaves the scale factor acquisition +method unspecified, possibly to be set by some other means (like +QT_SCREEN_SCALE_FACTORS). + +Done-with: Friedemann Kleint +Task-number: QTBUG-53022 +Change-Id: I30033d91175a00db7837efc9c48c33396f5f0449 +--- + src/gui/kernel/qhighdpiscaling.cpp | 29 +++++++++++++++++++++++------ + 1 file changed, 23 insertions(+), 6 deletions(-) + +diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp +index b1350599b7..52c0665b5b 100644 +--- a/src/gui/kernel/qhighdpiscaling.cpp ++++ b/src/gui/kernel/qhighdpiscaling.cpp +@@ -54,8 +54,10 @@ Q_LOGGING_CATEGORY(lcScaling, "qt.scaling"); + + #ifndef QT_NO_HIGHDPISCALING + static const char legacyDevicePixelEnvVar[] = "QT_DEVICE_PIXEL_RATIO"; ++static const char legacyAutoScreenEnvVar[] = "QT_AUTO_SCREEN_SCALE_FACTOR"; ++ ++static const char enableHighDpiScalingEnvVar[] = "QT_ENABLE_HIGHDPI_SCALING"; + static const char scaleFactorEnvVar[] = "QT_SCALE_FACTOR"; +-static const char autoScreenEnvVar[] = "QT_AUTO_SCREEN_SCALE_FACTOR"; + static const char screenFactorsEnvVar[] = "QT_SCREEN_SCALE_FACTORS"; + static const char scaleFactorRoundingPolicyEnvVar[] = "QT_SCALE_FACTOR_ROUNDING_POLICY"; + static const char dpiAdjustmentPolicyEnvVar[] = "QT_DPI_ADJUSTMENT_POLICY"; +@@ -88,17 +90,24 @@ static inline qreal initialGlobalScaleFactor() + result = f; + } + } else { ++ // Check for deprecated environment variables. + if (qEnvironmentVariableIsSet(legacyDevicePixelEnvVar)) { + qWarning("Warning: %s is deprecated. Instead use:\n" + " %s to enable platform plugin controlled per-screen factors.\n" +- " %s to set per-screen factors.\n" ++ " %s to set per-screen DPI.\n" + " %s to set the application global scale factor.", +- legacyDevicePixelEnvVar, autoScreenEnvVar, screenFactorsEnvVar, scaleFactorEnvVar); ++ legacyDevicePixelEnvVar, legacyAutoScreenEnvVar, screenFactorsEnvVar, scaleFactorEnvVar); + + int dpr = qEnvironmentVariableIntValue(legacyDevicePixelEnvVar); + if (dpr > 0) + result = dpr; + } ++ ++ if (qEnvironmentVariableIsSet(legacyAutoScreenEnvVar)) { ++ qWarning("Warning: %s is deprecated. Instead use:\n" ++ " %s to enable platform plugin controlled per-screen factors.", ++ legacyAutoScreenEnvVar, enableHighDpiScalingEnvVar); ++ } + } + return result; + } +@@ -256,16 +265,24 @@ static inline bool usePixelDensity() + // Determine if we should set a scale factor based on the pixel density + // reported by the platform plugin. There are several enablers and several + // disablers. A single disable may veto all other enablers. ++ ++ // First, check of there is an explicit disable. + if (QCoreApplication::testAttribute(Qt::AA_DisableHighDpiScaling)) + return false; + bool screenEnvValueOk; +- const int screenEnvValue = qEnvironmentVariableIntValue(autoScreenEnvVar, &screenEnvValueOk); ++ const int screenEnvValue = qEnvironmentVariableIntValue(legacyAutoScreenEnvVar, &screenEnvValueOk); + if (screenEnvValueOk && screenEnvValue < 1) + return false; ++ bool enableEnvValueOk; ++ const int enableEnvValue = qEnvironmentVariableIntValue(enableHighDpiScalingEnvVar, &enableEnvValueOk); ++ if (enableEnvValueOk && enableEnvValue < 1) ++ return false; ++ ++ // Then return if there was an enable. + return QCoreApplication::testAttribute(Qt::AA_EnableHighDpiScaling) + || (screenEnvValueOk && screenEnvValue > 0) +- || (qEnvironmentVariableIsSet(legacyDevicePixelEnvVar) && +- qgetenv(legacyDevicePixelEnvVar).compare("auto", Qt::CaseInsensitive) == 0); ++ || (enableEnvValueOk && enableEnvValue > 0) ++ || (qEnvironmentVariableIsSet(legacyDevicePixelEnvVar) && qgetenv(legacyDevicePixelEnvVar).toLower() == "auto"); + } + + qreal QHighDpiScaling::rawScaleFactor(const QPlatformScreen *screen) +-- +2.18.0.windows.1 + diff --git a/3rdparty/ext_qt/0036-Add-high-DPI-scale-factor-rounding-policy-C-API.patch b/3rdparty/ext_qt/0036-Add-high-DPI-scale-factor-rounding-policy-C-API.patch new file mode 100644 --- /dev/null +++ b/3rdparty/ext_qt/0036-Add-high-DPI-scale-factor-rounding-policy-C-API.patch @@ -0,0 +1,314 @@ +From 8e4d9b59af6b64345dd2a23656cf157ad76614eb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= +Date: Sat, 7 Oct 2017 01:35:29 +0200 +Subject: [PATCH 36/36] Add high-DPI scale factor rounding policy C++ API + +This API enables tuning of how Qt rounds fractional scale factors, and +corresponds to the QT_SCALE_FACTOR_ROUNDING_POLICY environment +variable + +New API: + Qt::HighDPiScaleFactorRoundingPolicy + QGuiApplication::setHighDpiScaleFactorRoundingPolicy() + QGuiApplication::highDpiScaleFactorRoundingPolicy() + +Done-with: Friedemann Kleint +Task-number: QTBUG-53022 +Change-Id: Ic360f26a173caa757e4ebde35ce08a6b74290b7d +--- + src/corelib/global/qnamespace.h | 10 +++++++ + src/corelib/global/qnamespace.qdoc | 22 ++++++++++++++ + src/gui/kernel/qguiapplication.cpp | 44 ++++++++++++++++++++++++++++ + src/gui/kernel/qguiapplication.h | 3 ++ + src/gui/kernel/qguiapplication_p.h | 1 + + src/gui/kernel/qhighdpiscaling.cpp | 47 +++++++++++++++++------------- + src/gui/kernel/qhighdpiscaling_p.h | 10 ------- + 7 files changed, 106 insertions(+), 31 deletions(-) + +diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h +index 3ab9921986..fea3d4d8da 100644 +--- a/src/corelib/global/qnamespace.h ++++ b/src/corelib/global/qnamespace.h +@@ -1728,6 +1728,15 @@ public: + ChecksumItuV41 + }; + ++ enum class HighDpiScaleFactorRoundingPolicy { ++ NotSet, ++ Round, ++ Ceil, ++ Floor, ++ RoundPreferFloor, ++ PassThrough ++ }; ++ + #ifndef Q_QDOC + // NOTE: Generally, do not add QT_Q_ENUM if a corresponding Q_Q_FLAG exists. + QT_Q_ENUM(ScrollBarPolicy) +@@ -1813,6 +1822,7 @@ public: + QT_Q_ENUM(MouseEventSource) + QT_Q_FLAG(MouseEventFlag) + QT_Q_ENUM(ChecksumType) ++ QT_Q_ENUM(HighDpiScaleFactorRoundingPolicy) + QT_Q_ENUM(TabFocusBehavior) + #endif // Q_DOC + +diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc +index 5bba8c5fe5..a3ca70a74d 100644 +--- a/src/corelib/global/qnamespace.qdoc ++++ b/src/corelib/global/qnamespace.qdoc +@@ -3252,3 +3252,25 @@ + + \value ChecksumItuV41 Checksum calculation based on ITU-V.41. + */ ++ ++/*! ++ \enum Qt::HighDpiScaleFactorRoundingPolicy ++ \since 5.14 ++ ++ This enum describes the possible High-DPI scale factor rounding policies, which ++ decide how non-integer scale factors (such as Windows 150%) are handled. ++ ++ The active policy is set by calling QGuiApplication::setHighDdpiScaleFactorRoundingPolicy() before ++ the application object is created, or by setting the QT_SCALE_FACTOR_ROUNDING_POLICY ++ environment variable. ++ ++ \sa QGuiApplication::setHighDdpiScaleFactorRoundingPolicy() ++ \sa AA_EnableHighDpiScaling. ++ ++ \omitvalue NotSet ++ \value Round Round up for .5 and above. ++ \value Ceil Always round up. ++ \value Floor Always round down. ++ \value RoundPreferFloor Round up for .75 and above. ++ \value PassThrough Don't round. ++*/ +diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp +index fd01f8bb7b..3541c1ae59 100644 +--- a/src/gui/kernel/qguiapplication.cpp ++++ b/src/gui/kernel/qguiapplication.cpp +@@ -146,6 +146,8 @@ QString QGuiApplicationPrivate::styleOverride; + + Qt::ApplicationState QGuiApplicationPrivate::applicationState = Qt::ApplicationInactive; + ++Qt::HighDpiScaleFactorRoundingPolicy QGuiApplicationPrivate::highDpiScaleFactorRoundingPolicy = ++ Qt::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor; + bool QGuiApplicationPrivate::highDpiScalingUpdated = false; + + QPointer QGuiApplicationPrivate::currentDragWindow; +@@ -677,6 +679,8 @@ QGuiApplication::~QGuiApplication() + QGuiApplicationPrivate::lastCursorPosition = {qInf(), qInf()}; + QGuiApplicationPrivate::currentMousePressWindow = QGuiApplicationPrivate::currentMouseWindow = nullptr; + QGuiApplicationPrivate::applicationState = Qt::ApplicationInactive; ++ QGuiApplicationPrivate::highDpiScaleFactorRoundingPolicy = ++ Qt::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor; + QGuiApplicationPrivate::highDpiScalingUpdated = false; + QGuiApplicationPrivate::currentDragWindow = nullptr; + QGuiApplicationPrivate::tabletDevicePoints.clear(); +@@ -3448,6 +3452,46 @@ Qt::ApplicationState QGuiApplication::applicationState() + return QGuiApplicationPrivate::applicationState; + } + ++/*! ++ \since 5.14 ++ ++ Sets the high-DPI scale factor rounding policy for the application. The ++ policy decides how non-integer scale factors (such as Windows 150%) are ++ handled, for applications that have AA_EnableHighDpiScaling enabled. ++ ++ The two principal options are whether fractional scale factors should ++ be rounded to an integer or not. Keeping the scale factor as-is will ++ make the user interface size match the OS setting exactly, but may cause ++ painting errors, for example with the Windows style. ++ ++ If rounding is wanted, then which type of rounding should be decided ++ next. Mathematically correct rounding is supported but may not give ++ the best visual results: Consider if you want to render 1.5x as 1x ++ ("small UI") or as 2x ("large UI"). See the Qt::HighDpiScaleFactorRoundingPolicy ++ enum for a complete list of all options. ++ ++ This function must be called before creating the application object, ++ and can be overridden by setting the QT_SCALE_FACTOR_ROUNDING_POLICY ++ environment variable. The QGuiApplication::highDpiScaleFactorRoundingPolicy() ++ accessor will reflect the environment, if set. ++ ++ The default value is Qt::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor. ++*/ ++void QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy policy) ++{ ++ QGuiApplicationPrivate::highDpiScaleFactorRoundingPolicy = policy; ++} ++ ++/*! ++ \since 5.14 ++ ++ Returns the high-DPI scale factor rounding policy. ++*/ ++Qt::HighDpiScaleFactorRoundingPolicy QGuiApplication::highDpiScaleFactorRoundingPolicy() ++{ ++ return QGuiApplicationPrivate::highDpiScaleFactorRoundingPolicy; ++} ++ + /*! + \since 5.2 + \fn void QGuiApplication::applicationStateChanged(Qt::ApplicationState state) +diff --git a/src/gui/kernel/qguiapplication.h b/src/gui/kernel/qguiapplication.h +index 02dffef0fe..2814ba1d1b 100644 +--- a/src/gui/kernel/qguiapplication.h ++++ b/src/gui/kernel/qguiapplication.h +@@ -156,6 +156,9 @@ public: + + static Qt::ApplicationState applicationState(); + ++ static void setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy policy); ++ static Qt::HighDpiScaleFactorRoundingPolicy highDpiScaleFactorRoundingPolicy(); ++ + static int exec(); + bool notify(QObject *, QEvent *) override; + +diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h +index 042a36c31f..7962bb0177 100644 +--- a/src/gui/kernel/qguiapplication_p.h ++++ b/src/gui/kernel/qguiapplication_p.h +@@ -216,6 +216,7 @@ public: + static QWindow *currentMouseWindow; + static QWindow *currentMousePressWindow; + static Qt::ApplicationState applicationState; ++ static Qt::HighDpiScaleFactorRoundingPolicy highDpiScaleFactorRoundingPolicy; + static bool highDpiScalingUpdated; + static QPointer currentDragWindow; + +diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp +index 52c0665b5b..29b6d7e7c2 100644 +--- a/src/gui/kernel/qhighdpiscaling.cpp ++++ b/src/gui/kernel/qhighdpiscaling.cpp +@@ -329,24 +329,24 @@ static QByteArray joinEnumValues(const EnumLookup *i1, const EnumLooku + return result; + } + +-using ScaleFactorRoundingPolicyLookup = EnumLookup; ++using ScaleFactorRoundingPolicyLookup = EnumLookup; + + static const ScaleFactorRoundingPolicyLookup scaleFactorRoundingPolicyLookup[] = + { +- {"Round", QHighDpiScaling::HighDpiScaleFactorRoundingPolicy::Round}, +- {"Ceil", QHighDpiScaling::HighDpiScaleFactorRoundingPolicy::Ceil}, +- {"Floor", QHighDpiScaling::HighDpiScaleFactorRoundingPolicy::Floor}, +- {"RoundPreferFloor", QHighDpiScaling::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor}, +- {"PassThrough", QHighDpiScaling::HighDpiScaleFactorRoundingPolicy::PassThrough} ++ {"Round", Qt::HighDpiScaleFactorRoundingPolicy::Round}, ++ {"Ceil", Qt::HighDpiScaleFactorRoundingPolicy::Ceil}, ++ {"Floor", Qt::HighDpiScaleFactorRoundingPolicy::Floor}, ++ {"RoundPreferFloor", Qt::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor}, ++ {"PassThrough", Qt::HighDpiScaleFactorRoundingPolicy::PassThrough} + }; + +-static QHighDpiScaling::HighDpiScaleFactorRoundingPolicy ++static Qt::HighDpiScaleFactorRoundingPolicy + lookupScaleFactorRoundingPolicy(const QByteArray &v) + { + auto end = std::end(scaleFactorRoundingPolicyLookup); + auto it = std::find(std::begin(scaleFactorRoundingPolicyLookup), end, +- ScaleFactorRoundingPolicyLookup{v.constData(), QHighDpiScaling::HighDpiScaleFactorRoundingPolicy::NotSet}); +- return it != end ? it->value : QHighDpiScaling::HighDpiScaleFactorRoundingPolicy::NotSet; ++ ScaleFactorRoundingPolicyLookup{v.constData(), Qt::HighDpiScaleFactorRoundingPolicy::NotSet}); ++ return it != end ? it->value : Qt::HighDpiScaleFactorRoundingPolicy::NotSet; + } + + using DpiAdjustmentPolicyLookup = EnumLookup; +@@ -375,15 +375,15 @@ qreal QHighDpiScaling::roundScaleFactor(qreal rawFactor) + // sizes that are smaller than the ideal size, and opposite for rounding up. + // Rounding down is then preferable since "small UI" is a more acceptable + // high-DPI experience than "large UI". +- static auto scaleFactorRoundingPolicy = HighDpiScaleFactorRoundingPolicy::NotSet; ++ static auto scaleFactorRoundingPolicy = Qt::HighDpiScaleFactorRoundingPolicy::NotSet; + + // Determine rounding policy +- if (scaleFactorRoundingPolicy == HighDpiScaleFactorRoundingPolicy::NotSet) { ++ if (scaleFactorRoundingPolicy == Qt::HighDpiScaleFactorRoundingPolicy::NotSet) { + // Check environment + if (qEnvironmentVariableIsSet(scaleFactorRoundingPolicyEnvVar)) { + QByteArray policyText = qgetenv(scaleFactorRoundingPolicyEnvVar); + auto policyEnumValue = lookupScaleFactorRoundingPolicy(policyText); +- if (policyEnumValue != HighDpiScaleFactorRoundingPolicy::NotSet) { ++ if (policyEnumValue != Qt::HighDpiScaleFactorRoundingPolicy::NotSet) { + scaleFactorRoundingPolicy = policyEnumValue; + } else { + auto values = joinEnumValues(std::begin(scaleFactorRoundingPolicyLookup), +@@ -391,38 +391,43 @@ qreal QHighDpiScaling::roundScaleFactor(qreal rawFactor) + qWarning("Unknown scale factor rounding policy: %s. Supported values are: %s.", + policyText.constData(), values.constData()); + } ++ } ++ ++ // Check application object if no environment value was set. ++ if (scaleFactorRoundingPolicy == Qt::HighDpiScaleFactorRoundingPolicy::NotSet) { ++ scaleFactorRoundingPolicy = QGuiApplication::highDpiScaleFactorRoundingPolicy(); + } else { +- // Set default policy if no environment variable is set. +- scaleFactorRoundingPolicy = HighDpiScaleFactorRoundingPolicy::RoundPreferFloor; ++ // Make application setting reflect environment ++ QGuiApplication::setHighDpiScaleFactorRoundingPolicy(scaleFactorRoundingPolicy); + } + } + + // Apply rounding policy. + qreal roundedFactor = rawFactor; + switch (scaleFactorRoundingPolicy) { +- case HighDpiScaleFactorRoundingPolicy::Round: ++ case Qt::HighDpiScaleFactorRoundingPolicy::Round: + roundedFactor = qRound(rawFactor); + break; +- case HighDpiScaleFactorRoundingPolicy::Ceil: ++ case Qt::HighDpiScaleFactorRoundingPolicy::Ceil: + roundedFactor = qCeil(rawFactor); + break; +- case HighDpiScaleFactorRoundingPolicy::Floor: ++ case Qt::HighDpiScaleFactorRoundingPolicy::Floor: + roundedFactor = qFloor(rawFactor); + break; +- case HighDpiScaleFactorRoundingPolicy::RoundPreferFloor: ++ case Qt::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor: + // Round up for .75 and higher. This favors "small UI" over "large UI". + roundedFactor = rawFactor - qFloor(rawFactor) < 0.75 + ? qFloor(rawFactor) : qCeil(rawFactor); + break; +- case HighDpiScaleFactorRoundingPolicy::PassThrough: +- case HighDpiScaleFactorRoundingPolicy::NotSet: ++ case Qt::HighDpiScaleFactorRoundingPolicy::PassThrough: ++ case Qt::HighDpiScaleFactorRoundingPolicy::NotSet: + break; + } + + // Don't round down to to zero; clamp the minimum (rounded) factor to 1. + // This is not a common case but can happen if a display reports a very + // low DPI. +- if (scaleFactorRoundingPolicy != HighDpiScaleFactorRoundingPolicy::PassThrough) ++ if (scaleFactorRoundingPolicy != Qt::HighDpiScaleFactorRoundingPolicy::PassThrough) + roundedFactor = qMax(roundedFactor, qreal(1)); + + return roundedFactor; +diff --git a/src/gui/kernel/qhighdpiscaling_p.h b/src/gui/kernel/qhighdpiscaling_p.h +index d3f71854a8..ae361a9ddb 100644 +--- a/src/gui/kernel/qhighdpiscaling_p.h ++++ b/src/gui/kernel/qhighdpiscaling_p.h +@@ -73,16 +73,6 @@ typedef QPair QDpi; + class Q_GUI_EXPORT QHighDpiScaling { + Q_GADGET + public: +- enum class HighDpiScaleFactorRoundingPolicy { +- NotSet, +- Round, +- Ceil, +- Floor, +- RoundPreferFloor, +- PassThrough +- }; +- Q_ENUM(HighDpiScaleFactorRoundingPolicy) +- + enum class DpiAdjustmentPolicy { + NotSet, + Enabled, +-- +2.18.0.windows.1 + diff --git a/3rdparty/ext_qt/CMakeLists.txt b/3rdparty/ext_qt/CMakeLists.txt --- a/3rdparty/ext_qt/CMakeLists.txt +++ b/3rdparty/ext_qt/CMakeLists.txt @@ -62,6 +62,13 @@ COMMAND ${PATCH_COMMAND} -p1 -d qtbase -i ${CMAKE_CURRENT_SOURCE_DIR}/set-has-border-in-full-screen-default.patch COMMAND ${PATCH_COMMAND} -p1 -d qtbase -i ${CMAKE_CURRENT_SOURCE_DIR}/remove-fullscreen-border-hack.patch COMMAND ${PATCH_COMMAND} -p1 -d qttools -i ${CMAKE_CURRENT_SOURCE_DIR}/windeployqt-force-allow-debug-info.patch + COMMAND ${PATCH_COMMAND} -p1 -d qtbase -i ${CMAKE_CURRENT_SOURCE_DIR}/0030-Windows-QPA-Make-the-expected-screen-be-in-sync-with.patch + COMMAND ${PATCH_COMMAND} -p1 -d qtbase -i ${CMAKE_CURRENT_SOURCE_DIR}/0031-Compute-logical-DPI-on-a-per-screen-basis.patch + COMMAND ${PATCH_COMMAND} -p1 -d qtbase -i ${CMAKE_CURRENT_SOURCE_DIR}/0032-Update-Dpi-and-scale-factor-computation.patch + COMMAND ${PATCH_COMMAND} -p1 -d qtbase -i ${CMAKE_CURRENT_SOURCE_DIR}/0033-Move-QT_FONT_DPI-to-cross-platform-code.patch + COMMAND ${PATCH_COMMAND} -p1 -d qtbase -i ${CMAKE_CURRENT_SOURCE_DIR}/0034-Update-QT_SCREEN_SCALE_FACTORS.patch + COMMAND ${PATCH_COMMAND} -p1 -d qtbase -i ${CMAKE_CURRENT_SOURCE_DIR}/0035-Deprecate-QT_AUTO_SCREEN_SCALE_FACTOR.patch + COMMAND ${PATCH_COMMAND} -p1 -d qtbase -i ${CMAKE_CURRENT_SOURCE_DIR}/0036-Add-high-DPI-scale-factor-rounding-policy-C-API.patch ) ExternalProject_Add( diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -339,6 +339,18 @@ ) configure_file(config-hdr.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-hdr.h) +CHECK_CXX_SOURCE_COMPILES(" +#include +int main(int argc, char *argv[]) { +QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Round); +QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor); +QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); +} +" +HAVE_HIGH_DPI_SCALE_FACTOR_ROUNDING_POLICY +) +configure_file(config-high-dpi-scale-factor-rounding-policy.h.in ${CMAKE_CURRENT_BINARY_DIR}/config-high-dpi-scale-factor-rounding-policy.h) + if (WIN32) CHECK_CXX_SOURCE_COMPILES(" #include diff --git a/config-high-dpi-scale-factor-rounding-policy.h.in b/config-high-dpi-scale-factor-rounding-policy.h.in new file mode 100644 --- /dev/null +++ b/config-high-dpi-scale-factor-rounding-policy.h.in @@ -0,0 +1,4 @@ +/* config-hdr.h. Generated by cmake from config-high-dpi-scale-factor-rounding-policy.h.in */ + +/* Define if QGuiApplication::setHighDpiScaleFactorRoundingPolicy is available */ +#cmakedefine HAVE_HIGH_DPI_SCALE_FACTOR_ROUNDING_POLICY 1 diff --git a/krita/main.cc b/krita/main.cc --- a/krita/main.cc +++ b/krita/main.cc @@ -67,6 +67,7 @@ #else #include #endif +#include "config-high-dpi-scale-factor-rounding-policy.h" #include "config-set-has-border-in-full-screen-default.h" #ifdef HAVE_SET_HAS_BORDER_IN_FULL_SCREEN_DEFAULT #include @@ -157,6 +158,24 @@ QCoreApplication::setAttribute(Qt::AA_DisableShaderDiskCache, true); #endif +#ifdef HAVE_HIGH_DPI_SCALE_FACTOR_ROUNDING_POLICY + // This rounding policy depends on a series of patches to Qt related to + // https://bugreports.qt.io/browse/QTBUG-53022. These patches are applied + // in ext_qt for WIndows (patches 0031-0036). + // + // The rounding policy can be set externally by setting the environment + // variable `QT_SCALE_FACTOR_ROUNDING_POLICY` to one of the following: + // Round: Round up for .5 and above. + // Ceil: Always round up. + // Floor: Always round down. + // RoundPreferFloor: Round up for .75 and above. + // PassThrough: Don't round. + // + // The default is set to Round to obtain the same behaviour as in the past, + // but can be overridden by the above environment variable. + QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Round); +#endif + const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat);