diff options
author | Morten Johan Sørvig <morten.sorvig@qt.io> | 2021-03-12 14:49:09 +0100 |
---|---|---|
committer | Qt CI Bot <qt_ci_bot@qt-project.org> | 2021-03-15 15:54:49 +0000 |
commit | 68e69588e0270262f90c3050665eade81551d54b (patch) | |
tree | f46406b25a287b137840a06e34018066c74d728e /src/gui | |
parent | 8962fed044af763c29e98b923608ccf696ef58d9 (diff) | |
parent | f9f9004b40ed7a4f4d280ba48bf6422cac6d21a4 (diff) |
Merge "Add auto-test for QT_USE_PHYSICAL_DPI"
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/kernel/qhighdpiscaling.cpp | 222 | ||||
-rw-r--r-- | src/gui/kernel/qhighdpiscaling_p.h | 6 |
2 files changed, 123 insertions, 105 deletions
diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp index 5bc3f11b3d..3a70e5acf7 100644 --- a/src/gui/kernel/qhighdpiscaling.cpp +++ b/src/gui/kernel/qhighdpiscaling.cpp @@ -49,10 +49,11 @@ #include <QtCore/qmetaobject.h> #include <algorithm> +#include <optional> QT_BEGIN_NAMESPACE -Q_LOGGING_CATEGORY(lcScaling, "qt.scaling"); +Q_LOGGING_CATEGORY(lcHighDpi, "qt.highdpi"); #ifndef QT_NO_HIGHDPISCALING @@ -63,35 +64,38 @@ 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<QString, qreal> QScreenScaleFactorHash; -Q_GLOBAL_STATIC(QScreenScaleFactorHash, qNamedScreenScaleFactors); +static std::optional<QString> qEnvironmentVariableOptionalString(const char *name) +{ + if (!qEnvironmentVariableIsSet(name)) + return std::nullopt; + + return std::optional(qEnvironmentVariable(name)); +} -// 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) +static std::optional<QByteArray> qEnvironmentVariableOptionalByteArray(const char *name) { - bool ok = false; - int value = qEnvironmentVariableIntValue(name, &ok); - return ok ? value > 0 : defaultValue; + if (!qEnvironmentVariableIsSet(name)) + return std::nullopt; + + return std::optional(qgetenv(name)); } -static inline qreal initialGlobalScaleFactor() +static std::optional<int> qEnvironmentVariableOptionalInt(const char *name) { + bool ok = false; + const int value = qEnvironmentVariableIntValue(name, &ok); + auto opt = ok ? std::optional(value) : std::nullopt; + return opt; +} - qreal result = 1; - if (qEnvironmentVariableIsSet(scaleFactorEnvVar)) { - bool ok; - const qreal f = qEnvironmentVariable(scaleFactorEnvVar).toDouble(&ok); - if (ok && f > 0) { - qCDebug(lcScaling) << "Apply " << scaleFactorEnvVar << f; - result = f; - } - } +static std::optional<qreal> qEnvironmentVariableOptionalReal(const char *name) +{ + if (!qEnvironmentVariableIsSet(name)) + return std::nullopt; - return result; + bool ok = false; + const qreal value = qEnvironmentVariable(name).toDouble(&ok); + return ok ? std::optional(value) : std::nullopt; } /*! @@ -275,35 +279,17 @@ bool QHighDpiScaling::m_usePlatformPluginDpi = false; // use scale factor based bool QHighDpiScaling::m_platformPluginDpiScalingActive = false; // platform plugin DPI gives a scale factor > 1 bool QHighDpiScaling::m_globalScalingActive = false; // global scale factor is active bool QHighDpiScaling::m_screenFactorSet = false; // QHighDpiScaling::setScreenFactor has been used - -/* - Initializes the QHighDpiScaling global variables. Called before the - platform plugin is created. -*/ - -static inline bool usePlatformPluginDpi() -{ - // Determine if we should set a scale factor based on the logical DPI - // reported by the platform plugin. - - bool enableEnvValueOk; - const int enableEnvValue = qEnvironmentVariableIntValue(enableHighDpiScalingEnvVar, &enableEnvValueOk); - if (enableEnvValueOk && enableEnvValue < 1) - return false; - - // Enable by default - return true; -} +bool QHighDpiScaling::m_usePhysicalDpi = false; +QHighDpiScaling::DpiAdjustmentPolicy QHighDpiScaling::m_dpiAdjustmentPolicy = QHighDpiScaling::DpiAdjustmentPolicy::Unset; +QString QHighDpiScaling::m_screenFactorsSpec; +QHash<QString, qreal> QHighDpiScaling::m_namedScreenScaleFactors; // Per-screen scale factors (screen name -> factor) qreal QHighDpiScaling::rawScaleFactor(const QPlatformScreen *screen) { - // Determine if physical DPI should be used - static const bool usePhysicalDpi = qEnvironmentVariableAsBool(usePhysicalDpiEnvVar, false); - // Calculate scale factor beased on platform screen DPI values qreal factor; QDpi platformBaseDpi = screen->logicalBaseDpi(); - if (usePhysicalDpi) { + if (QHighDpiScaling::m_usePhysicalDpi) { QSize sz = screen->geometry().size(); QSizeF psz = screen->physicalSize(); qreal platformPhysicalDpi = ((sz.height() / psz.height()) + (sz.width() / psz.width())) * qreal(25.4 * 0.5); @@ -387,32 +373,9 @@ 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 = Qt::HighDpiScaleFactorRoundingPolicy::Unset; - - // Determine rounding policy - if (scaleFactorRoundingPolicy == Qt::HighDpiScaleFactorRoundingPolicy::Unset) { - // Check environment - if (qEnvironmentVariableIsSet(scaleFactorRoundingPolicyEnvVar)) { - QByteArray policyText = qgetenv(scaleFactorRoundingPolicyEnvVar); - auto policyEnumValue = lookupScaleFactorRoundingPolicy(policyText); - if (policyEnumValue != Qt::HighDpiScaleFactorRoundingPolicy::Unset) { - 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()); - } - } - // Check application object if no environment value was set. - if (scaleFactorRoundingPolicy == Qt::HighDpiScaleFactorRoundingPolicy::Unset) { - scaleFactorRoundingPolicy = QGuiApplication::highDpiScaleFactorRoundingPolicy(); - } else { - // Make application setting reflect environment - QGuiApplication::setHighDpiScaleFactorRoundingPolicy(scaleFactorRoundingPolicy); - } - } + Qt::HighDpiScaleFactorRoundingPolicy scaleFactorRoundingPolicy = + QGuiApplication::highDpiScaleFactorRoundingPolicy(); // Apply rounding policy. qreal roundedFactor = rawFactor; @@ -452,56 +415,108 @@ QDpi QHighDpiScaling::effectiveLogicalDpi(const QPlatformScreen *screen, qreal r // 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::Unset; - - // Determine adjustment policy. - if (dpiAdjustmentPolicy == DpiAdjustmentPolicy::Unset) { - if (qEnvironmentVariableIsSet(dpiAdjustmentPolicyEnvVar)) { - QByteArray policyText = qgetenv(dpiAdjustmentPolicyEnvVar); - auto policyEnumValue = lookupDpiAdjustmentPolicy(policyText); - if (policyEnumValue != DpiAdjustmentPolicy::Unset) { - 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::Unset) - 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) + if (QHighDpiScaling::m_dpiAdjustmentPolicy == DpiAdjustmentPolicy::Disabled) return baseDpi; - if (dpiAdjustmentPolicy == DpiAdjustmentPolicy::UpOnly && dpiAdjustmentFactor < 1) + if (QHighDpiScaling::m_dpiAdjustmentPolicy == DpiAdjustmentPolicy::UpOnly && dpiAdjustmentFactor < 1) return baseDpi; return QDpi(baseDpi.first * dpiAdjustmentFactor, baseDpi.second * dpiAdjustmentFactor); } +/* + Determine and apply global/initial configuration which do not depend on + having access to QScreen objects - this function is called before they + have been created. Screen-dependent configuration happens later in + updateHighDpiScaling(). +*/ void QHighDpiScaling::initHighDpiScaling() { - // Determine if there is a global scale factor set. - m_factor = initialGlobalScaleFactor(); + // Read environment variables + static const char* envDebugStr = "environment variable set:"; + std::optional<int> envEnableHighDpiScaling = qEnvironmentVariableOptionalInt(enableHighDpiScalingEnvVar); + if (envEnableHighDpiScaling.has_value()) + qCDebug(lcHighDpi) << envDebugStr << enableHighDpiScalingEnvVar << envEnableHighDpiScaling.value(); + + std::optional<qreal> envScaleFactor = qEnvironmentVariableOptionalReal(scaleFactorEnvVar); + if (envScaleFactor.has_value()) + qCDebug(lcHighDpi) << envDebugStr << scaleFactorEnvVar << envScaleFactor.value(); + + std::optional<QString> envScreenFactors = qEnvironmentVariableOptionalString(screenFactorsEnvVar); + if (envScreenFactors.has_value()) + qCDebug(lcHighDpi) << envDebugStr << screenFactorsEnvVar << envScreenFactors.value(); + + std::optional<int> envUsePhysicalDpi = qEnvironmentVariableOptionalInt(usePhysicalDpiEnvVar); + if (envUsePhysicalDpi.has_value()) + qCDebug(lcHighDpi) << envDebugStr << usePhysicalDpiEnvVar << envUsePhysicalDpi.value(); + + std::optional<QByteArray> envScaleFactorRoundingPolicy = qEnvironmentVariableOptionalByteArray(scaleFactorRoundingPolicyEnvVar); + if (envScaleFactorRoundingPolicy.has_value()) + qCDebug(lcHighDpi) << envDebugStr << scaleFactorRoundingPolicyEnvVar << envScaleFactorRoundingPolicy.value(); + + std::optional<QByteArray> envDpiAdjustmentPolicy = qEnvironmentVariableOptionalByteArray(dpiAdjustmentPolicyEnvVar); + if (envDpiAdjustmentPolicy.has_value()) + qCDebug(lcHighDpi) << envDebugStr << dpiAdjustmentPolicyEnvVar << envDpiAdjustmentPolicy.value(); + + // High-dpi scaling is enabled by default; check for global disable. + m_usePlatformPluginDpi = envEnableHighDpiScaling.value_or(1) > 0; + m_platformPluginDpiScalingActive = false; // see updateHighDpiScaling() + + // Check for glabal scale factor (different from 1) + m_factor = envScaleFactor.value_or(qreal(1)); m_globalScalingActive = !qFuzzyCompare(m_factor, qreal(1)); - m_usePlatformPluginDpi = usePlatformPluginDpi(); + // Store the envScreenFactors string for later use. The string format + // supports using screen names, which means that screen DPI cannot + // be resolved at this point. + QHighDpiScaling::m_screenFactorsSpec = envScreenFactors.value_or(QString()); + m_namedScreenScaleFactors.clear(); - m_platformPluginDpiScalingActive = false; //set in updateHighDpiScaling below + m_usePhysicalDpi = envUsePhysicalDpi.value_or(0) > 0; + // Resolve HighDpiScaleFactorRoundingPolicy to QGuiApplication::highDpiScaleFactorRoundingPolicy + if (envScaleFactorRoundingPolicy.has_value()) { + QByteArray policyText = envScaleFactorRoundingPolicy.value(); + auto policyEnumValue = lookupScaleFactorRoundingPolicy(policyText); + if (policyEnumValue != Qt::HighDpiScaleFactorRoundingPolicy::Unset) { + QGuiApplication::setHighDpiScaleFactorRoundingPolicy(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()); + } + } + + // Resolve DpiAdjustmentPolicy to m_dpiAdjustmentPolicy + if (envDpiAdjustmentPolicy.has_value()) { + QByteArray policyText = envScaleFactorRoundingPolicy.value(); + auto policyEnumValue = lookupDpiAdjustmentPolicy(policyText); + if (policyEnumValue != DpiAdjustmentPolicy::Unset) { + QHighDpiScaling::m_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()); + } + } + + // Set initial active state m_active = m_globalScalingActive || m_usePlatformPluginDpi; } +/* + Update configuration based on available screens and screen properties. + This function may be called whenever the screen configuration changed. +*/ void QHighDpiScaling::updateHighDpiScaling() { - m_usePlatformPluginDpi = usePlatformPluginDpi(); - if (m_usePlatformPluginDpi && !m_platformPluginDpiScalingActive ) { const auto screens = QGuiApplication::screens(); for (QScreen *screen : screens) { @@ -511,10 +526,9 @@ void QHighDpiScaling::updateHighDpiScaling() } } } - if (qEnvironmentVariableIsSet(screenFactorsEnvVar)) { + if (!m_screenFactorsSpec.isNull()) { int i = 0; - const QString spec = qEnvironmentVariable(screenFactorsEnvVar); - const auto specs = QStringView{spec}.split(u';'); + const auto specs = QStringView{m_screenFactorsSpec}.split(u';'); for (const auto &spec : specs) { int equalsPos = spec.lastIndexOf(QLatin1Char('=')); qreal factor = 0; @@ -583,7 +597,7 @@ void QHighDpiScaling::setScreenFactor(QScreen *screen, qreal factor) if (name.isEmpty()) screen->setProperty(scaleFactorProperty, QVariant(factor)); else - qNamedScreenScaleFactors()->insert(name, factor); + QHighDpiScaling::m_namedScreenScaleFactors.insert(name, factor); // hack to force re-evaluation of screen geometry if (screen->handle()) @@ -630,8 +644,8 @@ qreal QHighDpiScaling::screenSubfactor(const QPlatformScreen *screen) } if (!screenPropertyUsed) { - auto byNameIt = qNamedScreenScaleFactors()->constFind(screen->name()); - if ((screenPropertyUsed = byNameIt != qNamedScreenScaleFactors()->cend())) + auto byNameIt = QHighDpiScaling::m_namedScreenScaleFactors.constFind(screen->name()); + if ((screenPropertyUsed = byNameIt != QHighDpiScaling::m_namedScreenScaleFactors.cend())) factor = *byNameIt; } } diff --git a/src/gui/kernel/qhighdpiscaling_p.h b/src/gui/kernel/qhighdpiscaling_p.h index 3a3983387c..e85a9b4bd6 100644 --- a/src/gui/kernel/qhighdpiscaling_p.h +++ b/src/gui/kernel/qhighdpiscaling_p.h @@ -64,7 +64,7 @@ QT_BEGIN_NAMESPACE -Q_DECLARE_LOGGING_CATEGORY(lcScaling); +Q_DECLARE_LOGGING_CATEGORY(lcHighDpi); class QScreen; class QPlatformScreen; @@ -138,6 +138,10 @@ private: static bool m_platformPluginDpiScalingActive; static bool m_globalScalingActive; static bool m_screenFactorSet; + static bool m_usePhysicalDpi; + static QString m_screenFactorsSpec; + static DpiAdjustmentPolicy m_dpiAdjustmentPolicy; + static QHash<QString, qreal> m_namedScreenScaleFactors; }; namespace QHighDpi { |