diff options
Diffstat (limited to 'src/gui/kernel/qhighdpiscaling.cpp')
-rw-r--r-- | src/gui/kernel/qhighdpiscaling.cpp | 188 |
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" |