summaryrefslogtreecommitdiffstats
path: root/src/gui/kernel/qhighdpiscaling.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/kernel/qhighdpiscaling.cpp')
-rw-r--r--src/gui/kernel/qhighdpiscaling.cpp188
1 files changed, 106 insertions, 82 deletions
diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp
index f93ec5fe76..a0e1b48dcb 100644
--- a/src/gui/kernel/qhighdpiscaling.cpp
+++ b/src/gui/kernel/qhighdpiscaling.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qhighdpiscaling_p.h"
#include "qguiapplication.h"
@@ -183,7 +147,7 @@ static std::optional<qreal> qEnvironmentVariableOptionalReal(const char *name)
is always enabled. The Qt scale factor value is typically determined by the
QPlatformScreen implementation - see below.
- There is one environment variable based opt-out option: set QT_ENABLE_HIGH_DPI_SCALING=0.
+ There is one environment variable based opt-out option: set QT_ENABLE_HIGHDPI_SCALING=0.
Keep in mind that this does not affect the OS scale factor, which is controlled by
the operating system.
@@ -280,8 +244,8 @@ bool QHighDpiScaling::m_platformPluginDpiScalingActive = false; // platform plu
bool QHighDpiScaling::m_globalScalingActive = false; // global scale factor is active
bool QHighDpiScaling::m_screenFactorSet = false; // QHighDpiScaling::setScreenFactor has been used
bool QHighDpiScaling::m_usePhysicalDpi = false;
+QVector<QHighDpiScaling::ScreenFactor> QHighDpiScaling::m_screenFactors;
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)
@@ -437,6 +401,8 @@ QDpi QHighDpiScaling::effectiveLogicalDpi(const QPlatformScreen *screen, qreal r
*/
void QHighDpiScaling::initHighDpiScaling()
{
+ qCDebug(lcHighDpi) << "Initializing high-DPI scaling";
+
// Read environment variables
static const char* envDebugStr = "environment variable set:";
std::optional<int> envEnableHighDpiScaling = qEnvironmentVariableOptionalInt(enableHighDpiScalingEnvVar);
@@ -474,7 +440,8 @@ void QHighDpiScaling::initHighDpiScaling()
// 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());
+ QString screenFactorsSpec = envScreenFactors.value_or(QString());
+ m_screenFactors = parseScreenScaleFactorsSpec(QStringView{screenFactorsSpec});
m_namedScreenScaleFactors.clear();
m_usePhysicalDpi = envUsePhysicalDpi.value_or(0) > 0;
@@ -495,7 +462,7 @@ void QHighDpiScaling::initHighDpiScaling()
// Resolve DpiAdjustmentPolicy to m_dpiAdjustmentPolicy
if (envDpiAdjustmentPolicy.has_value()) {
- QByteArray policyText = envScaleFactorRoundingPolicy.value();
+ QByteArray policyText = envDpiAdjustmentPolicy.value();
auto policyEnumValue = lookupDpiAdjustmentPolicy(policyText);
if (policyEnumValue != DpiAdjustmentPolicy::Unset) {
QHighDpiScaling::m_dpiAdjustmentPolicy = policyEnumValue;
@@ -509,6 +476,9 @@ void QHighDpiScaling::initHighDpiScaling()
// Set initial active state
m_active = m_globalScalingActive || m_usePlatformPluginDpi;
+
+ qCDebug(lcHighDpi) << "Initialization done, high-DPI scaling is"
+ << (m_active ? "active" : "inactive");
}
/*
@@ -517,6 +487,32 @@ void QHighDpiScaling::initHighDpiScaling()
*/
void QHighDpiScaling::updateHighDpiScaling()
{
+ qCDebug(lcHighDpi) << "Updating high-DPI scaling";
+
+ // Apply screen factors from environment
+ if (m_screenFactors.size() > 0) {
+ qCDebug(lcHighDpi) << "Applying screen factors" << m_screenFactors;
+ int i = -1;
+ const auto screens = QGuiApplication::screens();
+ for (const auto &[name, rawFactor]: m_screenFactors) {
+ const qreal factor = roundScaleFactor(rawFactor);
+ ++i;
+ if (name.isNull()) {
+ if (i < screens.size())
+ setScreenFactor(screens.at(i), factor);
+ } else {
+ for (QScreen *screen : screens) {
+ if (screen->name() == name) {
+ setScreenFactor(screen, factor);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // Check if any screens (now) has a scale factor != 1 and set
+ // m_platformPluginDpiScalingActive if so.
if (m_usePlatformPluginDpi && !m_platformPluginDpiScalingActive ) {
const auto screens = QGuiApplication::screens();
for (QScreen *screen : screens) {
@@ -526,39 +522,11 @@ void QHighDpiScaling::updateHighDpiScaling()
}
}
}
- if (!m_screenFactorsSpec.isNull()) {
- int i = 0;
- const auto specs = QStringView{m_screenFactorsSpec}.split(u';');
- for (const auto &spec : specs) {
- int equalsPos = spec.lastIndexOf(QLatin1Char('='));
- qreal factor = 0;
- if (equalsPos > 0) {
- // support "name=factor"
- bool ok;
- const auto name = spec.left(equalsPos);
- factor = spec.mid(equalsPos + 1).toDouble(&ok);
- if (ok && factor > 0 ) {
- const auto screens = QGuiApplication::screens();
- for (QScreen *s : screens) {
- if (s->name() == name) {
- setScreenFactor(s, factor);
- break;
- }
- }
- }
- } else {
- // listing screens in order
- bool ok;
- factor = spec.toDouble(&ok);
- if (ok && factor > 0 && i < QGuiApplication::screens().count()) {
- QScreen *screen = QGuiApplication::screens().at(i);
- setScreenFactor(screen, factor);
- }
- }
- ++i;
- }
- }
- m_active = m_globalScalingActive || m_screenFactorSet || m_platformPluginDpiScalingActive ;
+
+ m_active = m_globalScalingActive || m_screenFactorSet || m_platformPluginDpiScalingActive;
+
+ qCDebug(lcHighDpi) << "Update done, high-DPI scaling is"
+ << (m_active ? "active" : "inactive");
}
/*
@@ -566,17 +534,24 @@ void QHighDpiScaling::updateHighDpiScaling()
*/
void QHighDpiScaling::setGlobalFactor(qreal factor)
{
+ qCDebug(lcHighDpi) << "Setting global scale factor to" << factor;
+
if (qFuzzyCompare(factor, m_factor))
return;
if (!QGuiApplication::allWindows().isEmpty())
qWarning("QHighDpiScaling::setFactor: Should only be called when no windows exist.");
+ const auto screens = QGuiApplication::screens();
+
+ std::vector<QScreenPrivate::UpdateEmitter> updateEmitters;
+ for (QScreen *screen : screens)
+ updateEmitters.emplace_back(screen);
+
m_globalScalingActive = !qFuzzyCompare(factor, qreal(1));
m_factor = m_globalScalingActive ? factor : qreal(1);
m_active = m_globalScalingActive || m_screenFactorSet || m_platformPluginDpiScalingActive ;
- const auto screens = QGuiApplication::screens();
for (QScreen *screen : screens)
- screen->d_func()->updateHighDpi();
+ screen->d_func()->updateGeometry();
}
static const char scaleFactorProperty[] = "_q_scaleFactor";
@@ -586,11 +561,15 @@ static const char scaleFactorProperty[] = "_q_scaleFactor";
*/
void QHighDpiScaling::setScreenFactor(QScreen *screen, qreal factor)
{
+ qCDebug(lcHighDpi) << "Setting screen scale factor for" << screen << "to" << factor;
+
if (!qFuzzyCompare(factor, qreal(1))) {
m_screenFactorSet = true;
m_active = true;
}
+ QScreenPrivate::UpdateEmitter updateEmitter(screen);
+
// 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();
@@ -599,9 +578,7 @@ void QHighDpiScaling::setScreenFactor(QScreen *screen, qreal factor)
else
QHighDpiScaling::m_namedScreenScaleFactors.insert(name, factor);
- // hack to force re-evaluation of screen geometry
- if (screen->handle())
- screen->d_func()->setPlatformScreen(screen->handle()); // updates geometries based on scale factor
+ screen->d_func()->updateGeometry();
}
QPoint QHighDpiScaling::mapPositionToNative(const QPoint &pos, const QPlatformScreen *platformScreen)
@@ -713,6 +690,36 @@ QScreen *QHighDpiScaling::screenForPosition(QHighDpiScaling::Point position, QSc
return nullptr;
}
+QVector<QHighDpiScaling::ScreenFactor> QHighDpiScaling::parseScreenScaleFactorsSpec(const QStringView &screenScaleFactors)
+{
+ QVector<QHighDpiScaling::ScreenFactor> screenFactors;
+
+ // The spec is _either_
+ // - a semicolon-separated ordered factor list: "1.5;2;3"
+ // - a semicolon-separated name=factor list: "foo=1.5;bar=2;baz=3"
+ const auto specs = screenScaleFactors.split(u';');
+ for (const auto &spec : specs) {
+ const qsizetype equalsPos = spec.lastIndexOf(u'=');
+ if (equalsPos == -1) {
+ // screens in order
+ bool ok;
+ const qreal factor = spec.toDouble(&ok);
+ if (ok && factor > 0) {
+ screenFactors.append(QHighDpiScaling::ScreenFactor(QString(), factor));
+ }
+ } else {
+ // "name=factor"
+ bool ok;
+ const qreal factor = spec.mid(equalsPos + 1).toDouble(&ok);
+ if (ok && factor > 0) {
+ screenFactors.append(QHighDpiScaling::ScreenFactor(spec.left(equalsPos).toString(), factor));
+ }
+ }
+ } // for (specs)
+
+ return screenFactors;
+}
+
QHighDpiScaling::ScaleAndOrigin QHighDpiScaling::scaleAndOrigin(const QPlatformScreen *platformScreen, QHighDpiScaling::Point position)
{
Q_UNUSED(position)
@@ -746,7 +753,20 @@ QHighDpiScaling::ScaleAndOrigin QHighDpiScaling::scaleAndOrigin(const QWindow *w
return scaleAndOrigin(targetScreen, position);
}
-#else
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, const QHighDpiScaling::ScreenFactor &factor)
+{
+ const QDebugStateSaver saver(debug);
+ debug.nospace();
+ if (!factor.name.isEmpty())
+ debug << factor.name << "=";
+ debug << factor.factor;
+ return debug;
+}
+#endif
+
+#else // QT_NO_HIGHDPISCALING
+
QHighDpiScaling::ScaleAndOrigin QHighDpiScaling::scaleAndOrigin(const QPlatformScreen *, QPoint *)
{
return { qreal(1), QPoint() };
@@ -761,5 +781,9 @@ QHighDpiScaling::ScaleAndOrigin QHighDpiScaling::scaleAndOrigin(const QWindow *,
{
return { qreal(1), QPoint() };
}
-#endif //QT_NO_HIGHDPISCALING
+
+#endif // QT_NO_HIGHDPISCALING
+
QT_END_NAMESPACE
+
+#include "moc_qhighdpiscaling_p.cpp"