summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorMorten Johan Sørvig <morten.sorvig@qt.io>2021-03-12 14:49:09 +0100
committerQt CI Bot <qt_ci_bot@qt-project.org>2021-03-15 15:54:49 +0000
commit68e69588e0270262f90c3050665eade81551d54b (patch)
treef46406b25a287b137840a06e34018066c74d728e /src/gui
parent8962fed044af763c29e98b923608ccf696ef58d9 (diff)
parentf9f9004b40ed7a4f4d280ba48bf6422cac6d21a4 (diff)
Merge "Add auto-test for QT_USE_PHYSICAL_DPI"
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/kernel/qhighdpiscaling.cpp222
-rw-r--r--src/gui/kernel/qhighdpiscaling_p.h6
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 {