| 1 | /**************************************************************************** | 
|---|
| 2 | ** | 
|---|
| 3 | ** Copyright (C) 2016 The Qt Company Ltd. | 
|---|
| 4 | ** Contact: https://www.qt.io/licensing/ | 
|---|
| 5 | ** | 
|---|
| 6 | ** This file is part of the QtGui module of the Qt Toolkit. | 
|---|
| 7 | ** | 
|---|
| 8 | ** $QT_BEGIN_LICENSE:LGPL$ | 
|---|
| 9 | ** Commercial License Usage | 
|---|
| 10 | ** Licensees holding valid commercial Qt licenses may use this file in | 
|---|
| 11 | ** accordance with the commercial license agreement provided with the | 
|---|
| 12 | ** Software or, alternatively, in accordance with the terms contained in | 
|---|
| 13 | ** a written agreement between you and The Qt Company. For licensing terms | 
|---|
| 14 | ** and conditions see https://www.qt.io/terms-conditions. For further | 
|---|
| 15 | ** information use the contact form at https://www.qt.io/contact-us. | 
|---|
| 16 | ** | 
|---|
| 17 | ** GNU Lesser General Public License Usage | 
|---|
| 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | 
|---|
| 19 | ** General Public License version 3 as published by the Free Software | 
|---|
| 20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the | 
|---|
| 21 | ** packaging of this file. Please review the following information to | 
|---|
| 22 | ** ensure the GNU Lesser General Public License version 3 requirements | 
|---|
| 23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. | 
|---|
| 24 | ** | 
|---|
| 25 | ** GNU General Public License Usage | 
|---|
| 26 | ** Alternatively, this file may be used under the terms of the GNU | 
|---|
| 27 | ** General Public License version 2.0 or (at your option) the GNU General | 
|---|
| 28 | ** Public license version 3 or any later version approved by the KDE Free | 
|---|
| 29 | ** Qt Foundation. The licenses are as published by the Free Software | 
|---|
| 30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 | 
|---|
| 31 | ** included in the packaging of this file. Please review the following | 
|---|
| 32 | ** information to ensure the GNU General Public License requirements will | 
|---|
| 33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and | 
|---|
| 34 | ** https://www.gnu.org/licenses/gpl-3.0.html. | 
|---|
| 35 | ** | 
|---|
| 36 | ** $QT_END_LICENSE$ | 
|---|
| 37 | ** | 
|---|
| 38 | ****************************************************************************/ | 
|---|
| 39 |  | 
|---|
| 40 | #include "qhighdpiscaling_p.h" | 
|---|
| 41 | #include "qguiapplication.h" | 
|---|
| 42 | #include "qscreen.h" | 
|---|
| 43 | #include "qplatformintegration.h" | 
|---|
| 44 | #include "qplatformwindow.h" | 
|---|
| 45 | #include "private/qscreen_p.h" | 
|---|
| 46 | #include <private/qguiapplication_p.h> | 
|---|
| 47 |  | 
|---|
| 48 | #include <QtCore/qdebug.h> | 
|---|
| 49 | #include <QtCore/qmetaobject.h> | 
|---|
| 50 |  | 
|---|
| 51 | #include <algorithm> | 
|---|
| 52 |  | 
|---|
| 53 | QT_BEGIN_NAMESPACE | 
|---|
| 54 |  | 
|---|
| 55 | Q_LOGGING_CATEGORY(lcScaling, "qt.scaling"); | 
|---|
| 56 |  | 
|---|
| 57 | #ifndef QT_NO_HIGHDPISCALING | 
|---|
| 58 |  | 
|---|
| 59 | static const char enableHighDpiScalingEnvVar[] = "QT_ENABLE_HIGHDPI_SCALING"; | 
|---|
| 60 | static const char scaleFactorEnvVar[] = "QT_SCALE_FACTOR"; | 
|---|
| 61 | static const char screenFactorsEnvVar[] = "QT_SCREEN_SCALE_FACTORS"; | 
|---|
| 62 | static const char scaleFactorRoundingPolicyEnvVar[] = "QT_SCALE_FACTOR_ROUNDING_POLICY"; | 
|---|
| 63 | static const char dpiAdjustmentPolicyEnvVar[] = "QT_DPI_ADJUSTMENT_POLICY"; | 
|---|
| 64 | static const char usePhysicalDpiEnvVar[] = "QT_USE_PHYSICAL_DPI"; | 
|---|
| 65 |  | 
|---|
| 66 | // Per-screen scale factors for named screens set with QT_SCREEN_SCALE_FACTORS | 
|---|
| 67 | // are stored here. Use a global hash to keep the factor across screen | 
|---|
| 68 | // disconnect/connect cycles where the screen object may be deleted. | 
|---|
| 69 | typedef QHash<QString, qreal> QScreenScaleFactorHash; | 
|---|
| 70 | Q_GLOBAL_STATIC(QScreenScaleFactorHash, qNamedScreenScaleFactors); | 
|---|
| 71 |  | 
|---|
| 72 | // Reads and interprets the given environment variable as a bool, | 
|---|
| 73 | // returns the default value if not set. | 
|---|
| 74 | static bool qEnvironmentVariableAsBool(const char *name, bool defaultValue) | 
|---|
| 75 | { | 
|---|
| 76 | bool ok = false; | 
|---|
| 77 | int value = qEnvironmentVariableIntValue(name, &ok); | 
|---|
| 78 | return ok ? value > 0 : defaultValue; | 
|---|
| 79 | } | 
|---|
| 80 |  | 
|---|
| 81 | static inline qreal initialGlobalScaleFactor() | 
|---|
| 82 | { | 
|---|
| 83 |  | 
|---|
| 84 | qreal result = 1; | 
|---|
| 85 | if (qEnvironmentVariableIsSet(scaleFactorEnvVar)) { | 
|---|
| 86 | bool ok; | 
|---|
| 87 | const qreal f = qEnvironmentVariable(scaleFactorEnvVar).toDouble(&ok); | 
|---|
| 88 | if (ok && f > 0) { | 
|---|
| 89 | qCDebug(lcScaling) << "Apply "<< scaleFactorEnvVar << f; | 
|---|
| 90 | result = f; | 
|---|
| 91 | } | 
|---|
| 92 | } | 
|---|
| 93 |  | 
|---|
| 94 | return result; | 
|---|
| 95 | } | 
|---|
| 96 |  | 
|---|
| 97 | /*! | 
|---|
| 98 | \class QHighDpiScaling | 
|---|
| 99 | \since 5.6 | 
|---|
| 100 | \internal | 
|---|
| 101 | \preliminary | 
|---|
| 102 | \ingroup qpa | 
|---|
| 103 |  | 
|---|
| 104 | \brief Collection of utility functions for UI scaling. | 
|---|
| 105 |  | 
|---|
| 106 | QHighDpiScaling implements utility functions for high-dpi scaling for use | 
|---|
| 107 | on operating systems that provide limited support for native scaling, such | 
|---|
| 108 | as Windows, X11, and Android. In addition this functionality can be used | 
|---|
| 109 | for simulation and testing purposes. | 
|---|
| 110 |  | 
|---|
| 111 | The functions support scaling between the device independent coordinate | 
|---|
| 112 | system used by Qt applications and the native coordinate system used by | 
|---|
| 113 | the platform plugins. Intended usage locations are the low level / platform | 
|---|
| 114 | plugin interfacing parts of QtGui, for example the QWindow, QScreen and | 
|---|
| 115 | QWindowSystemInterface implementation. | 
|---|
| 116 |  | 
|---|
| 117 | There are now up to three active coordinate systems in Qt: | 
|---|
| 118 |  | 
|---|
| 119 | --------------------------------------------------- | 
|---|
| 120 | |  Application            Device Independent Pixels |   devicePixelRatio | 
|---|
| 121 | |  Qt Widgets                                       |         = | 
|---|
| 122 | |  Qt Gui                                           | | 
|---|
| 123 | |---------------------------------------------------|   Qt Scale Factor | 
|---|
| 124 | |  Qt Gui QPlatform*      Native Pixels             |         * | 
|---|
| 125 | |  Qt platform plugin                               | | 
|---|
| 126 | |---------------------------------------------------|   OS Scale Factor | 
|---|
| 127 | |  Display                Device Pixels             | | 
|---|
| 128 | |  (Graphics Buffers)                               | | 
|---|
| 129 | ----------------------------------------------------- | 
|---|
| 130 |  | 
|---|
| 131 | This is an simplification and shows the main coordinate system. All layers | 
|---|
| 132 | may work with device pixels in specific cases: OpenGL, creating the backing | 
|---|
| 133 | store, and QPixmap management. The "Native Pixels" coordinate system is | 
|---|
| 134 | internal to Qt and should not be exposed to Qt users: Seen from the outside | 
|---|
| 135 | there are only two coordinate systems: device independent pixels and device | 
|---|
| 136 | pixels. | 
|---|
| 137 |  | 
|---|
| 138 | The devicePixelRatio seen by applications is the product of the Qt scale | 
|---|
| 139 | factor and the OS scale factor (see QWindow::devicePixelRatio()). The value | 
|---|
| 140 | of the scale factors may be 1, in which case two or more of the coordinate | 
|---|
| 141 | systems are equivalent. Platforms that (may) have an OS scale factor include | 
|---|
| 142 | macOS, iOS, Wayland, and Web(Assembly). | 
|---|
| 143 |  | 
|---|
| 144 | Note that the API implemented in this file do use the OS scale factor, and | 
|---|
| 145 | is used for converting between device independent and native pixels only. | 
|---|
| 146 |  | 
|---|
| 147 | Configuration Examples: | 
|---|
| 148 |  | 
|---|
| 149 | 'Classic': Device Independent Pixels = Native Pixels = Device Pixels | 
|---|
| 150 | ---------------------------------------------------    devicePixelRatio: 1 | 
|---|
| 151 | |  Application / Qt Gui             100 x 100       | | 
|---|
| 152 | |                                                   |   Qt Scale Factor: 1 | 
|---|
| 153 | |  Qt Platform / OS                 100 x 100       | | 
|---|
| 154 | |                                                   |   OS Scale Factor: 1 | 
|---|
| 155 | |  Display                          100 x 100       | | 
|---|
| 156 | ----------------------------------------------------- | 
|---|
| 157 |  | 
|---|
| 158 | '2x Apple Device': Device Independent Pixels = Native Pixels | 
|---|
| 159 | ---------------------------------------------------    devicePixelRatio: 2 | 
|---|
| 160 | |  Application / Qt Gui             100 x 100       | | 
|---|
| 161 | |                                                   |   Qt Scale Factor: 1 | 
|---|
| 162 | |  Qt Platform / OS                 100 x 100       | | 
|---|
| 163 | |---------------------------------------------------|   OS Scale Factor: 2 | 
|---|
| 164 | |  Display                          200 x 200       | | 
|---|
| 165 | ----------------------------------------------------- | 
|---|
| 166 |  | 
|---|
| 167 | 'Windows at 200%': Native Pixels = Device Pixels | 
|---|
| 168 | ---------------------------------------------------    devicePixelRatio: 2 | 
|---|
| 169 | |  Application / Qt Gui             100 x 100       | | 
|---|
| 170 | |---------------------------------------------------|   Qt Scale Factor: 2 | 
|---|
| 171 | |  Qt Platform / OS                 200 x 200       | | 
|---|
| 172 | |                                                   |   OS Scale Factor: 1 | 
|---|
| 173 | |  Display                          200 x 200       | | 
|---|
| 174 | ----------------------------------------------------- | 
|---|
| 175 |  | 
|---|
| 176 | * Configuration | 
|---|
| 177 |  | 
|---|
| 178 | - Enabling: In Qt 6, high-dpi scaling (the functionality implemented in this file) | 
|---|
| 179 | is always enabled. The Qt scale factor value is typically determined by the | 
|---|
| 180 | QPlatformScreen implementation - see below. | 
|---|
| 181 |  | 
|---|
| 182 | There is one environment variable based opt-out option: set QT_ENABLE_HIGH_DPI_SCALING=0. | 
|---|
| 183 | Keep in mind that this does not affect the OS scale factor, which is controlled by | 
|---|
| 184 | the operating system. | 
|---|
| 185 |  | 
|---|
| 186 | - Qt scale factor value: The Qt scale factor is the product of the screen scale | 
|---|
| 187 | factor and the global scale factor, which are independently either set or determined | 
|---|
| 188 | by the platform plugin. Several APIs are offered for this, targeting both developers | 
|---|
| 189 | and end users. All scale factors are of type qreal. | 
|---|
| 190 |  | 
|---|
| 191 | 1) Per-screen scale factors | 
|---|
| 192 |  | 
|---|
| 193 | Per-screen scale factors are computed based on logical DPI provided by | 
|---|
| 194 | by the platform plugin. | 
|---|
| 195 |  | 
|---|
| 196 | The platform plugin implements DPI accessor functions: | 
|---|
| 197 | QDpi QPlatformScreen::logicalDpi() | 
|---|
| 198 | QDpi QPlatformScreen::logicalBaseDpi() | 
|---|
| 199 |  | 
|---|
| 200 | QHighDpiScaling then computes the per-screen scale factor as follows: | 
|---|
| 201 |  | 
|---|
| 202 | factor = logicalDpi / logicalBaseDpi | 
|---|
| 203 |  | 
|---|
| 204 | Alternatively, QT_SCREEN_SCALE_FACTORS can be used to set the screen | 
|---|
| 205 | scale factors. | 
|---|
| 206 |  | 
|---|
| 207 | 2) The global scale factor | 
|---|
| 208 |  | 
|---|
| 209 | The QT_SCALE_FACTOR environment variable can be used to set a global scale | 
|---|
| 210 | factor which applies to all application windows. This allows developing and | 
|---|
| 211 | testing at any DPR, independently of available hardware and without changing | 
|---|
| 212 | global desktop settings. | 
|---|
| 213 |  | 
|---|
| 214 | - Rounding | 
|---|
| 215 |  | 
|---|
| 216 | Qt 6 does not round scale factors by default. Qt 5 rounds the screen scale factor | 
|---|
| 217 | to the nearest integer (except for Qt on Android which does not round). | 
|---|
| 218 |  | 
|---|
| 219 | The rounding policy can be set by the application, or on the environment: | 
|---|
| 220 |  | 
|---|
| 221 | Application (C++):    QGuiApplication::setHighDpiScaleFactorRoundingPolicy() | 
|---|
| 222 | User (environment):   QT_SCALE_FACTOR_ROUNDING_POLICY | 
|---|
| 223 |  | 
|---|
| 224 | Note that the OS scale factor, and global scale factors set with QT_SCALE_FACTOR | 
|---|
| 225 | are never rounded by Qt. | 
|---|
| 226 |  | 
|---|
| 227 | * C++ API Overview | 
|---|
| 228 |  | 
|---|
| 229 | - Coordinate Conversion ("scaling") | 
|---|
| 230 |  | 
|---|
| 231 | The QHighDpi namespace provides several functions for converting geometry | 
|---|
| 232 | between the device independent and native coordinate systems. These should | 
|---|
| 233 | be used when calling "QPlatform*" API from QtGui. Callers are responsible | 
|---|
| 234 | for selecting a function variant based on geometry type: | 
|---|
| 235 |  | 
|---|
| 236 | Type                        From Native                              To Native | 
|---|
| 237 | local               :    QHighDpi::fromNativeLocalPosition()    QHighDpi::toNativeLocalPosition() | 
|---|
| 238 | global (screen)     :    QHighDpi::fromNativeGlobalPosition()   QHighDpi::toNativeGlobalPosition() | 
|---|
| 239 | QWindow::geometry() :    QHighDpi::fromNativeWindowGeometry()   QHighDpi::toNativeWindowGeometry() | 
|---|
| 240 | sizes, margins, etc :    QHighDpi::fromNativePixels()           QHighDpi::toNativePixels() | 
|---|
| 241 |  | 
|---|
| 242 | The conversion functions take two arguments; the geometry and a context: | 
|---|
| 243 |  | 
|---|
| 244 | QSize nativeSize = toNativePixels(deviceIndependentSize, window); | 
|---|
| 245 |  | 
|---|
| 246 | The context is usually a QWindow instance, but can also be a QScreen instance, | 
|---|
| 247 | or the corresponding QPlatform classes. | 
|---|
| 248 |  | 
|---|
| 249 | - Activation | 
|---|
| 250 |  | 
|---|
| 251 | QHighDpiScaling::isActive() returns true iff | 
|---|
| 252 | Qt high-dpi scaling is enabled (e.g. with AA_EnableHighDpiScaling) AND | 
|---|
| 253 | there is a Qt scale factor != 1 | 
|---|
| 254 |  | 
|---|
| 255 | (the value of the OS scale factor does not affect this API) | 
|---|
| 256 |  | 
|---|
| 257 | - Calling QtGui from the platform plugins | 
|---|
| 258 |  | 
|---|
| 259 | Platform plugin code should be careful about calling QtGui geometry accessor | 
|---|
| 260 | functions like geometry(): | 
|---|
| 261 |  | 
|---|
| 262 | QRect r = window->geometry(); | 
|---|
| 263 |  | 
|---|
| 264 | In this case the returned geometry is in the wrong coordinate system (device independent | 
|---|
| 265 | instead of native pixels). Fix this by adding a conversion call: | 
|---|
| 266 |  | 
|---|
| 267 | QRect r = QHighDpi::toNativeWindowGeometry(window->geometry()); | 
|---|
| 268 |  | 
|---|
| 269 | (Also consider if the call to QtGui is really needed - prefer calling QPlatform* API.) | 
|---|
| 270 | */ | 
|---|
| 271 |  | 
|---|
| 272 | qreal QHighDpiScaling::m_factor = 1.0; | 
|---|
| 273 | bool QHighDpiScaling::m_active = false; //"overall active" - is there any scale factor set. | 
|---|
| 274 | bool QHighDpiScaling::m_usePlatformPluginDpi = false; // use scale factor based on platform plugin DPI | 
|---|
| 275 | bool QHighDpiScaling::m_platformPluginDpiScalingActive  = false; // platform plugin DPI gives a scale factor > 1 | 
|---|
| 276 | bool QHighDpiScaling::m_globalScalingActive = false; // global scale factor is active | 
|---|
| 277 | bool QHighDpiScaling::m_screenFactorSet = false; // QHighDpiScaling::setScreenFactor has been used | 
|---|
| 278 |  | 
|---|
| 279 | /* | 
|---|
| 280 | Initializes the QHighDpiScaling global variables. Called before the | 
|---|
| 281 | platform plugin is created. | 
|---|
| 282 | */ | 
|---|
| 283 |  | 
|---|
| 284 | static inline bool usePlatformPluginDpi() | 
|---|
| 285 | { | 
|---|
| 286 | // Determine if we should set a scale factor based on the logical DPI | 
|---|
| 287 | // reported by the platform plugin. | 
|---|
| 288 |  | 
|---|
| 289 | bool enableEnvValueOk; | 
|---|
| 290 | const int enableEnvValue = qEnvironmentVariableIntValue(enableHighDpiScalingEnvVar, &enableEnvValueOk); | 
|---|
| 291 | if (enableEnvValueOk && enableEnvValue < 1) | 
|---|
| 292 | return false; | 
|---|
| 293 |  | 
|---|
| 294 | // Enable by default | 
|---|
| 295 | return true; | 
|---|
| 296 | } | 
|---|
| 297 |  | 
|---|
| 298 | qreal QHighDpiScaling::rawScaleFactor(const QPlatformScreen *screen) | 
|---|
| 299 | { | 
|---|
| 300 | // Determine if physical DPI should be used | 
|---|
| 301 | static const bool usePhysicalDpi = qEnvironmentVariableAsBool(usePhysicalDpiEnvVar, false); | 
|---|
| 302 |  | 
|---|
| 303 | // Calculate scale factor beased on platform screen DPI values | 
|---|
| 304 | qreal factor; | 
|---|
| 305 | QDpi platformBaseDpi = screen->logicalBaseDpi(); | 
|---|
| 306 | if (usePhysicalDpi) { | 
|---|
| 307 | QSize sz = screen->geometry().size(); | 
|---|
| 308 | QSizeF psz = screen->physicalSize(); | 
|---|
| 309 | qreal platformPhysicalDpi = ((sz.height() / psz.height()) + (sz.width() / psz.width())) * qreal(25.4 * 0.5); | 
|---|
| 310 | factor = qreal(platformPhysicalDpi) / qreal(platformBaseDpi.first); | 
|---|
| 311 | } else { | 
|---|
| 312 | const QDpi platformLogicalDpi = QPlatformScreen::overrideDpi(screen->logicalDpi()); | 
|---|
| 313 | factor = qreal(platformLogicalDpi.first) / qreal(platformBaseDpi.first); | 
|---|
| 314 | } | 
|---|
| 315 |  | 
|---|
| 316 | return factor; | 
|---|
| 317 | } | 
|---|
| 318 |  | 
|---|
| 319 | template <class EnumType> | 
|---|
| 320 | struct EnumLookup | 
|---|
| 321 | { | 
|---|
| 322 | const char *name; | 
|---|
| 323 | EnumType value; | 
|---|
| 324 | }; | 
|---|
| 325 |  | 
|---|
| 326 | template <class EnumType> | 
|---|
| 327 | static bool operator==(const EnumLookup<EnumType> &e1, const EnumLookup<EnumType> &e2) | 
|---|
| 328 | { | 
|---|
| 329 | return qstricmp(e1.name, e2.name) == 0; | 
|---|
| 330 | } | 
|---|
| 331 |  | 
|---|
| 332 | template <class EnumType> | 
|---|
| 333 | static QByteArray joinEnumValues(const EnumLookup<EnumType> *i1, const EnumLookup<EnumType> *i2) | 
|---|
| 334 | { | 
|---|
| 335 | QByteArray result; | 
|---|
| 336 | for (; i1 < i2; ++i1) { | 
|---|
| 337 | if (!result.isEmpty()) | 
|---|
| 338 | result += QByteArrayLiteral( ", "); | 
|---|
| 339 | result += i1->name; | 
|---|
| 340 | } | 
|---|
| 341 | return result; | 
|---|
| 342 | } | 
|---|
| 343 |  | 
|---|
| 344 | using ScaleFactorRoundingPolicyLookup = EnumLookup<Qt::HighDpiScaleFactorRoundingPolicy>; | 
|---|
| 345 |  | 
|---|
| 346 | static const ScaleFactorRoundingPolicyLookup scaleFactorRoundingPolicyLookup[] = | 
|---|
| 347 | { | 
|---|
| 348 | { "Round", Qt::HighDpiScaleFactorRoundingPolicy::Round}, | 
|---|
| 349 | { "Ceil", Qt::HighDpiScaleFactorRoundingPolicy::Ceil}, | 
|---|
| 350 | { "Floor", Qt::HighDpiScaleFactorRoundingPolicy::Floor}, | 
|---|
| 351 | { "RoundPreferFloor", Qt::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor}, | 
|---|
| 352 | { "PassThrough", Qt::HighDpiScaleFactorRoundingPolicy::PassThrough} | 
|---|
| 353 | }; | 
|---|
| 354 |  | 
|---|
| 355 | static Qt::HighDpiScaleFactorRoundingPolicy | 
|---|
| 356 | lookupScaleFactorRoundingPolicy(const QByteArray &v) | 
|---|
| 357 | { | 
|---|
| 358 | auto end = std::end(scaleFactorRoundingPolicyLookup); | 
|---|
| 359 | auto it = std::find(std::begin(scaleFactorRoundingPolicyLookup), end, | 
|---|
| 360 | ScaleFactorRoundingPolicyLookup{v.constData(), Qt::HighDpiScaleFactorRoundingPolicy::Unset}); | 
|---|
| 361 | return it != end ? it->value : Qt::HighDpiScaleFactorRoundingPolicy::Unset; | 
|---|
| 362 | } | 
|---|
| 363 |  | 
|---|
| 364 | using DpiAdjustmentPolicyLookup = EnumLookup<QHighDpiScaling::DpiAdjustmentPolicy>; | 
|---|
| 365 |  | 
|---|
| 366 | static const DpiAdjustmentPolicyLookup dpiAdjustmentPolicyLookup[] = | 
|---|
| 367 | { | 
|---|
| 368 | { "AdjustDpi", QHighDpiScaling::DpiAdjustmentPolicy::Enabled}, | 
|---|
| 369 | { "DontAdjustDpi", QHighDpiScaling::DpiAdjustmentPolicy::Disabled}, | 
|---|
| 370 | { "AdjustUpOnly", QHighDpiScaling::DpiAdjustmentPolicy::UpOnly} | 
|---|
| 371 | }; | 
|---|
| 372 |  | 
|---|
| 373 | static QHighDpiScaling::DpiAdjustmentPolicy | 
|---|
| 374 | lookupDpiAdjustmentPolicy(const QByteArray &v) | 
|---|
| 375 | { | 
|---|
| 376 | auto end = std::end(dpiAdjustmentPolicyLookup); | 
|---|
| 377 | auto it = std::find(std::begin(dpiAdjustmentPolicyLookup), end, | 
|---|
| 378 | DpiAdjustmentPolicyLookup{v.constData(), QHighDpiScaling::DpiAdjustmentPolicy::Unset}); | 
|---|
| 379 | return it != end ? it->value : QHighDpiScaling::DpiAdjustmentPolicy::Unset; | 
|---|
| 380 | } | 
|---|
| 381 |  | 
|---|
| 382 | qreal QHighDpiScaling::roundScaleFactor(qreal rawFactor) | 
|---|
| 383 | { | 
|---|
| 384 | // Apply scale factor rounding policy. Using mathematically correct rounding | 
|---|
| 385 | // may not give the most desirable visual results, especially for | 
|---|
| 386 | // critical fractions like .5. In general, rounding down results in visual | 
|---|
| 387 | // sizes that are smaller than the ideal size, and opposite for rounding up. | 
|---|
| 388 | // Rounding down is then preferable since "small UI" is a more acceptable | 
|---|
| 389 | // high-DPI experience than "large UI". | 
|---|
| 390 | static auto scaleFactorRoundingPolicy = Qt::HighDpiScaleFactorRoundingPolicy::Unset; | 
|---|
| 391 |  | 
|---|
| 392 | // Determine rounding policy | 
|---|
| 393 | if (scaleFactorRoundingPolicy == Qt::HighDpiScaleFactorRoundingPolicy::Unset) { | 
|---|
| 394 | // Check environment | 
|---|
| 395 | if (qEnvironmentVariableIsSet(scaleFactorRoundingPolicyEnvVar)) { | 
|---|
| 396 | QByteArray policyText = qgetenv(scaleFactorRoundingPolicyEnvVar); | 
|---|
| 397 | auto policyEnumValue = lookupScaleFactorRoundingPolicy(policyText); | 
|---|
| 398 | if (policyEnumValue != Qt::HighDpiScaleFactorRoundingPolicy::Unset) { | 
|---|
| 399 | scaleFactorRoundingPolicy = policyEnumValue; | 
|---|
| 400 | } else { | 
|---|
| 401 | auto values = joinEnumValues(std::begin(scaleFactorRoundingPolicyLookup), | 
|---|
| 402 | std::end(scaleFactorRoundingPolicyLookup)); | 
|---|
| 403 | qWarning( "Unknown scale factor rounding policy: %s. Supported values are: %s.", | 
|---|
| 404 | policyText.constData(), values.constData()); | 
|---|
| 405 | } | 
|---|
| 406 | } | 
|---|
| 407 |  | 
|---|
| 408 | // Check application object if no environment value was set. | 
|---|
| 409 | if (scaleFactorRoundingPolicy == Qt::HighDpiScaleFactorRoundingPolicy::Unset) { | 
|---|
| 410 | scaleFactorRoundingPolicy = QGuiApplication::highDpiScaleFactorRoundingPolicy(); | 
|---|
| 411 | } else { | 
|---|
| 412 | // Make application setting reflect environment | 
|---|
| 413 | QGuiApplication::setHighDpiScaleFactorRoundingPolicy(scaleFactorRoundingPolicy); | 
|---|
| 414 | } | 
|---|
| 415 | } | 
|---|
| 416 |  | 
|---|
| 417 | // Apply rounding policy. | 
|---|
| 418 | qreal roundedFactor = rawFactor; | 
|---|
| 419 | switch (scaleFactorRoundingPolicy) { | 
|---|
| 420 | case Qt::HighDpiScaleFactorRoundingPolicy::Round: | 
|---|
| 421 | roundedFactor = qRound(rawFactor); | 
|---|
| 422 | break; | 
|---|
| 423 | case Qt::HighDpiScaleFactorRoundingPolicy::Ceil: | 
|---|
| 424 | roundedFactor = qCeil(rawFactor); | 
|---|
| 425 | break; | 
|---|
| 426 | case Qt::HighDpiScaleFactorRoundingPolicy::Floor: | 
|---|
| 427 | roundedFactor = qFloor(rawFactor); | 
|---|
| 428 | break; | 
|---|
| 429 | case Qt::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor: | 
|---|
| 430 | // Round up for .75 and higher. This favors "small UI" over "large UI". | 
|---|
| 431 | roundedFactor = rawFactor - qFloor(rawFactor) < 0.75 | 
|---|
| 432 | ? qFloor(rawFactor) : qCeil(rawFactor); | 
|---|
| 433 | break; | 
|---|
| 434 | case Qt::HighDpiScaleFactorRoundingPolicy::PassThrough: | 
|---|
| 435 | case Qt::HighDpiScaleFactorRoundingPolicy::Unset: | 
|---|
| 436 | break; | 
|---|
| 437 | } | 
|---|
| 438 |  | 
|---|
| 439 | // Don't round down to to zero; clamp the minimum (rounded) factor to 1. | 
|---|
| 440 | // This is not a common case but can happen if a display reports a very | 
|---|
| 441 | // low DPI. | 
|---|
| 442 | if (scaleFactorRoundingPolicy != Qt::HighDpiScaleFactorRoundingPolicy::PassThrough) | 
|---|
| 443 | roundedFactor = qMax(roundedFactor, qreal(1)); | 
|---|
| 444 |  | 
|---|
| 445 | return roundedFactor; | 
|---|
| 446 | } | 
|---|
| 447 |  | 
|---|
| 448 | QDpi QHighDpiScaling::effectiveLogicalDpi(const QPlatformScreen *screen, qreal rawFactor, qreal roundedFactor) | 
|---|
| 449 | { | 
|---|
| 450 | // Apply DPI adjustment policy, if needed. If enabled this will change the | 
|---|
| 451 | // reported logical DPI to account for the difference between the rounded | 
|---|
| 452 | // scale factor and the actual scale factor. The effect is that text size | 
|---|
| 453 | // will be correct for the screen dpi, but may be (slightly) out of sync | 
|---|
| 454 | // with the rest of the UI. The amount of out-of-synch-ness depends on how | 
|---|
| 455 | // well user code handles a non-standard DPI values, but since the | 
|---|
| 456 | // adjustment is small (typically +/- 48 max) this might be OK. | 
|---|
| 457 | static auto dpiAdjustmentPolicy = DpiAdjustmentPolicy::Unset; | 
|---|
| 458 |  | 
|---|
| 459 | // Determine adjustment policy. | 
|---|
| 460 | if (dpiAdjustmentPolicy == DpiAdjustmentPolicy::Unset) { | 
|---|
| 461 | if (qEnvironmentVariableIsSet(dpiAdjustmentPolicyEnvVar)) { | 
|---|
| 462 | QByteArray policyText = qgetenv(dpiAdjustmentPolicyEnvVar); | 
|---|
| 463 | auto policyEnumValue = lookupDpiAdjustmentPolicy(policyText); | 
|---|
| 464 | if (policyEnumValue != DpiAdjustmentPolicy::Unset) { | 
|---|
| 465 | dpiAdjustmentPolicy = policyEnumValue; | 
|---|
| 466 | } else { | 
|---|
| 467 | auto values = joinEnumValues(std::begin(dpiAdjustmentPolicyLookup), | 
|---|
| 468 | std::end(dpiAdjustmentPolicyLookup)); | 
|---|
| 469 | qWarning( "Unknown DPI adjustment policy: %s. Supported values are: %s.", | 
|---|
| 470 | policyText.constData(), values.constData()); | 
|---|
| 471 | } | 
|---|
| 472 | } | 
|---|
| 473 | if (dpiAdjustmentPolicy == DpiAdjustmentPolicy::Unset) | 
|---|
| 474 | dpiAdjustmentPolicy = DpiAdjustmentPolicy::UpOnly; | 
|---|
| 475 | } | 
|---|
| 476 |  | 
|---|
| 477 | // Apply adjustment policy. | 
|---|
| 478 | const QDpi baseDpi = screen->logicalBaseDpi(); | 
|---|
| 479 | const qreal dpiAdjustmentFactor = rawFactor / roundedFactor; | 
|---|
| 480 |  | 
|---|
| 481 | // Return the base DPI for cases where there is no adjustment | 
|---|
| 482 | if (dpiAdjustmentPolicy == DpiAdjustmentPolicy::Disabled) | 
|---|
| 483 | return baseDpi; | 
|---|
| 484 | if (dpiAdjustmentPolicy == DpiAdjustmentPolicy::UpOnly && dpiAdjustmentFactor < 1) | 
|---|
| 485 | return baseDpi; | 
|---|
| 486 |  | 
|---|
| 487 | return QDpi(baseDpi.first * dpiAdjustmentFactor, baseDpi.second * dpiAdjustmentFactor); | 
|---|
| 488 | } | 
|---|
| 489 |  | 
|---|
| 490 | void QHighDpiScaling::initHighDpiScaling() | 
|---|
| 491 | { | 
|---|
| 492 | // Determine if there is a global scale factor set. | 
|---|
| 493 | m_factor = initialGlobalScaleFactor(); | 
|---|
| 494 | m_globalScalingActive = !qFuzzyCompare(m_factor, qreal(1)); | 
|---|
| 495 |  | 
|---|
| 496 | m_usePlatformPluginDpi = usePlatformPluginDpi(); | 
|---|
| 497 |  | 
|---|
| 498 | m_platformPluginDpiScalingActive  = false; //set in updateHighDpiScaling below | 
|---|
| 499 |  | 
|---|
| 500 | m_active = m_globalScalingActive || m_usePlatformPluginDpi; | 
|---|
| 501 | } | 
|---|
| 502 |  | 
|---|
| 503 | void QHighDpiScaling::updateHighDpiScaling() | 
|---|
| 504 | { | 
|---|
| 505 | m_usePlatformPluginDpi = usePlatformPluginDpi(); | 
|---|
| 506 |  | 
|---|
| 507 | if (m_usePlatformPluginDpi && !m_platformPluginDpiScalingActive ) { | 
|---|
| 508 | const auto screens = QGuiApplication::screens(); | 
|---|
| 509 | for (QScreen *screen : screens) { | 
|---|
| 510 | if (!qFuzzyCompare(screenSubfactor(screen->handle()), qreal(1))) { | 
|---|
| 511 | m_platformPluginDpiScalingActive  = true; | 
|---|
| 512 | break; | 
|---|
| 513 | } | 
|---|
| 514 | } | 
|---|
| 515 | } | 
|---|
| 516 | if (qEnvironmentVariableIsSet(screenFactorsEnvVar)) { | 
|---|
| 517 | int i = 0; | 
|---|
| 518 | const QString spec = qEnvironmentVariable(screenFactorsEnvVar); | 
|---|
| 519 | const auto specs = QStringView{spec}.split(u';'); | 
|---|
| 520 | for (const auto &spec : specs) { | 
|---|
| 521 | int equalsPos = spec.lastIndexOf(QLatin1Char('=')); | 
|---|
| 522 | qreal factor = 0; | 
|---|
| 523 | if (equalsPos > 0) { | 
|---|
| 524 | // support "name=factor" | 
|---|
| 525 | bool ok; | 
|---|
| 526 | const auto name = spec.left(equalsPos); | 
|---|
| 527 | factor = spec.mid(equalsPos + 1).toDouble(&ok); | 
|---|
| 528 | if (ok && factor > 0 ) { | 
|---|
| 529 | const auto screens = QGuiApplication::screens(); | 
|---|
| 530 | for (QScreen *s : screens) { | 
|---|
| 531 | if (s->name() == name) { | 
|---|
| 532 | setScreenFactor(s, factor); | 
|---|
| 533 | break; | 
|---|
| 534 | } | 
|---|
| 535 | } | 
|---|
| 536 | } | 
|---|
| 537 | } else { | 
|---|
| 538 | // listing screens in order | 
|---|
| 539 | bool ok; | 
|---|
| 540 | factor = spec.toDouble(&ok); | 
|---|
| 541 | if (ok && factor > 0 && i < QGuiApplication::screens().count()) { | 
|---|
| 542 | QScreen *screen = QGuiApplication::screens().at(i); | 
|---|
| 543 | setScreenFactor(screen, factor); | 
|---|
| 544 | } | 
|---|
| 545 | } | 
|---|
| 546 | ++i; | 
|---|
| 547 | } | 
|---|
| 548 | } | 
|---|
| 549 | m_active = m_globalScalingActive || m_screenFactorSet || m_platformPluginDpiScalingActive ; | 
|---|
| 550 | } | 
|---|
| 551 |  | 
|---|
| 552 | /* | 
|---|
| 553 | Sets the global scale factor which is applied to all windows. | 
|---|
| 554 | */ | 
|---|
| 555 | void QHighDpiScaling::setGlobalFactor(qreal factor) | 
|---|
| 556 | { | 
|---|
| 557 | if (qFuzzyCompare(factor, m_factor)) | 
|---|
| 558 | return; | 
|---|
| 559 | if (!QGuiApplication::allWindows().isEmpty()) | 
|---|
| 560 | qWarning( "QHighDpiScaling::setFactor: Should only be called when no windows exist."); | 
|---|
| 561 |  | 
|---|
| 562 | m_globalScalingActive = !qFuzzyCompare(factor, qreal(1)); | 
|---|
| 563 | m_factor = m_globalScalingActive ? factor : qreal(1); | 
|---|
| 564 | m_active = m_globalScalingActive || m_screenFactorSet || m_platformPluginDpiScalingActive ; | 
|---|
| 565 | const auto screens = QGuiApplication::screens(); | 
|---|
| 566 | for (QScreen *screen : screens) | 
|---|
| 567 | screen->d_func()->updateHighDpi(); | 
|---|
| 568 | } | 
|---|
| 569 |  | 
|---|
| 570 | static const char scaleFactorProperty[] = "_q_scaleFactor"; | 
|---|
| 571 |  | 
|---|
| 572 | /* | 
|---|
| 573 | Sets a per-screen scale factor. | 
|---|
| 574 | */ | 
|---|
| 575 | void QHighDpiScaling::setScreenFactor(QScreen *screen, qreal factor) | 
|---|
| 576 | { | 
|---|
| 577 | if (!qFuzzyCompare(factor, qreal(1))) { | 
|---|
| 578 | m_screenFactorSet = true; | 
|---|
| 579 | m_active = true; | 
|---|
| 580 | } | 
|---|
| 581 |  | 
|---|
| 582 | // Prefer associating the factor with screen name over the object | 
|---|
| 583 | // since the screen object may be deleted on screen disconnects. | 
|---|
| 584 | const QString name = screen->name(); | 
|---|
| 585 | if (name.isEmpty()) | 
|---|
| 586 | screen->setProperty(scaleFactorProperty, QVariant(factor)); | 
|---|
| 587 | else | 
|---|
| 588 | qNamedScreenScaleFactors()->insert(name, factor); | 
|---|
| 589 |  | 
|---|
| 590 | // hack to force re-evaluation of screen geometry | 
|---|
| 591 | if (screen->handle()) | 
|---|
| 592 | screen->d_func()->setPlatformScreen(screen->handle()); // updates geometries based on scale factor | 
|---|
| 593 | } | 
|---|
| 594 |  | 
|---|
| 595 | QPoint QHighDpiScaling::mapPositionToNative(const QPoint &pos, const QPlatformScreen *platformScreen) | 
|---|
| 596 | { | 
|---|
| 597 | if (!platformScreen) | 
|---|
| 598 | return pos; | 
|---|
| 599 | const qreal scaleFactor = factor(platformScreen); | 
|---|
| 600 | const QPoint topLeft = platformScreen->geometry().topLeft(); | 
|---|
| 601 | return (pos - topLeft) * scaleFactor + topLeft; | 
|---|
| 602 | } | 
|---|
| 603 |  | 
|---|
| 604 | QPoint QHighDpiScaling::mapPositionFromNative(const QPoint &pos, const QPlatformScreen *platformScreen) | 
|---|
| 605 | { | 
|---|
| 606 | if (!platformScreen) | 
|---|
| 607 | return pos; | 
|---|
| 608 | const qreal scaleFactor = factor(platformScreen); | 
|---|
| 609 | const QPoint topLeft = platformScreen->geometry().topLeft(); | 
|---|
| 610 | return (pos - topLeft) / scaleFactor + topLeft; | 
|---|
| 611 | } | 
|---|
| 612 |  | 
|---|
| 613 | qreal QHighDpiScaling::screenSubfactor(const QPlatformScreen *screen) | 
|---|
| 614 | { | 
|---|
| 615 | auto factor = qreal(1.0); | 
|---|
| 616 | if (!screen) | 
|---|
| 617 | return factor; | 
|---|
| 618 |  | 
|---|
| 619 | // Unlike the other code where factors are combined by multiplication, | 
|---|
| 620 | // factors from QT_SCREEN_SCALE_FACTORS takes precedence over the factor | 
|---|
| 621 | // computed from platform plugin DPI. The rationale is that the user is | 
|---|
| 622 | // setting the factor to override erroneous DPI values. | 
|---|
| 623 | bool screenPropertyUsed = false; | 
|---|
| 624 | if (m_screenFactorSet) { | 
|---|
| 625 | // Check if there is a factor set on the screen object or associated | 
|---|
| 626 | // with the screen name. These are mutually exclusive, so checking | 
|---|
| 627 | // order is not significant. | 
|---|
| 628 | if (auto qScreen = screen->screen()) { | 
|---|
| 629 | auto screenFactor = qScreen->property(scaleFactorProperty).toReal(&screenPropertyUsed); | 
|---|
| 630 | if (screenPropertyUsed) | 
|---|
| 631 | factor = screenFactor; | 
|---|
| 632 | } | 
|---|
| 633 |  | 
|---|
| 634 | if (!screenPropertyUsed) { | 
|---|
| 635 | auto byNameIt = qNamedScreenScaleFactors()->constFind(screen->name()); | 
|---|
| 636 | if ((screenPropertyUsed = byNameIt != qNamedScreenScaleFactors()->cend())) | 
|---|
| 637 | factor = *byNameIt; | 
|---|
| 638 | } | 
|---|
| 639 | } | 
|---|
| 640 |  | 
|---|
| 641 | if (!screenPropertyUsed && m_usePlatformPluginDpi) | 
|---|
| 642 | factor = roundScaleFactor(rawScaleFactor(screen)); | 
|---|
| 643 |  | 
|---|
| 644 | return factor; | 
|---|
| 645 | } | 
|---|
| 646 |  | 
|---|
| 647 | QDpi QHighDpiScaling::logicalDpi(const QScreen *screen) | 
|---|
| 648 | { | 
|---|
| 649 | // (Note: m_active test is performed at call site.) | 
|---|
| 650 | if (!screen || !screen->handle()) | 
|---|
| 651 | return QDpi(96, 96); | 
|---|
| 652 |  | 
|---|
| 653 | if (!m_usePlatformPluginDpi) { | 
|---|
| 654 | const qreal screenScaleFactor = screenSubfactor(screen->handle()); | 
|---|
| 655 | const QDpi dpi = QPlatformScreen::overrideDpi(screen->handle()->logicalDpi()); | 
|---|
| 656 | return QDpi{ dpi.first / screenScaleFactor, dpi.second / screenScaleFactor }; | 
|---|
| 657 | } | 
|---|
| 658 |  | 
|---|
| 659 | const qreal scaleFactor = rawScaleFactor(screen->handle()); | 
|---|
| 660 | const qreal roundedScaleFactor = roundScaleFactor(scaleFactor); | 
|---|
| 661 | return effectiveLogicalDpi(screen->handle(), scaleFactor, roundedScaleFactor); | 
|---|
| 662 | } | 
|---|
| 663 |  | 
|---|
| 664 | // Returns the screen containing \a position, using \a guess as a starting point | 
|---|
| 665 | // for the search. \a guess might be nullptr. Returns nullptr if \a position is outside | 
|---|
| 666 | // of all screens. | 
|---|
| 667 | QScreen *QHighDpiScaling::screenForPosition(QHighDpiScaling::Point position, QScreen *guess) | 
|---|
| 668 | { | 
|---|
| 669 | if (position.kind == QHighDpiScaling::Point::Invalid) | 
|---|
| 670 | return nullptr; | 
|---|
| 671 |  | 
|---|
| 672 | auto getPlatformScreenGuess = [](QScreen *maybeScreen) -> QPlatformScreen * { | 
|---|
| 673 | if (maybeScreen) | 
|---|
| 674 | return maybeScreen->handle(); | 
|---|
| 675 | if (QScreen *primary = QGuiApplication::primaryScreen()) | 
|---|
| 676 | return primary->handle(); | 
|---|
| 677 | return nullptr; | 
|---|
| 678 | }; | 
|---|
| 679 |  | 
|---|
| 680 | QPlatformScreen *platformGuess = getPlatformScreenGuess(guess); | 
|---|
| 681 | if (!platformGuess) | 
|---|
| 682 | return nullptr; | 
|---|
| 683 |  | 
|---|
| 684 | auto onScreen = [](QHighDpiScaling::Point position, const QPlatformScreen *platformScreen) -> bool { | 
|---|
| 685 | return position.kind == Point::Native | 
|---|
| 686 | ?  platformScreen->geometry().contains(position.point) | 
|---|
| 687 | :  platformScreen->screen()->geometry().contains(position.point); | 
|---|
| 688 | }; | 
|---|
| 689 |  | 
|---|
| 690 | // is the guessed screen correct? | 
|---|
| 691 | if (onScreen(position, platformGuess)) | 
|---|
| 692 | return platformGuess->screen(); | 
|---|
| 693 |  | 
|---|
| 694 | // search sibling screens | 
|---|
| 695 | const auto screens = platformGuess->virtualSiblings(); | 
|---|
| 696 | for (const QPlatformScreen *screen : screens) { | 
|---|
| 697 | if (onScreen(position, screen)) | 
|---|
| 698 | return screen->screen(); | 
|---|
| 699 | } | 
|---|
| 700 |  | 
|---|
| 701 | return nullptr; | 
|---|
| 702 | } | 
|---|
| 703 |  | 
|---|
| 704 | QHighDpiScaling::ScaleAndOrigin QHighDpiScaling::scaleAndOrigin(const QPlatformScreen *platformScreen, QHighDpiScaling::Point position) | 
|---|
| 705 | { | 
|---|
| 706 | Q_UNUSED(position) | 
|---|
| 707 | if (!m_active) | 
|---|
| 708 | return { qreal(1), QPoint() }; | 
|---|
| 709 | if (!platformScreen) | 
|---|
| 710 | return { m_factor, QPoint() }; // the global factor | 
|---|
| 711 | return { m_factor * screenSubfactor(platformScreen), platformScreen->geometry().topLeft() }; | 
|---|
| 712 | } | 
|---|
| 713 |  | 
|---|
| 714 | QHighDpiScaling::ScaleAndOrigin QHighDpiScaling::scaleAndOrigin(const QScreen *screen, QHighDpiScaling::Point position) | 
|---|
| 715 | { | 
|---|
| 716 | Q_UNUSED(position) | 
|---|
| 717 | if (!m_active) | 
|---|
| 718 | return { qreal(1), QPoint() }; | 
|---|
| 719 | if (!screen) | 
|---|
| 720 | return { m_factor, QPoint() }; // the global factor | 
|---|
| 721 | return scaleAndOrigin(screen->handle(), position); | 
|---|
| 722 | } | 
|---|
| 723 |  | 
|---|
| 724 | QHighDpiScaling::ScaleAndOrigin QHighDpiScaling::scaleAndOrigin(const QWindow *window, QHighDpiScaling::Point position) | 
|---|
| 725 | { | 
|---|
| 726 | if (!m_active) | 
|---|
| 727 | return { qreal(1), QPoint() }; | 
|---|
| 728 |  | 
|---|
| 729 | // Determine correct screen; use the screen which contains the given | 
|---|
| 730 | // position if a valid position is passed. | 
|---|
| 731 | QScreen *screen = window ? window->screen() : QGuiApplication::primaryScreen(); | 
|---|
| 732 | QScreen *overrideScreen = QHighDpiScaling::screenForPosition(position, screen); | 
|---|
| 733 | QScreen *targetScreen = overrideScreen ? overrideScreen : screen; | 
|---|
| 734 | return scaleAndOrigin(targetScreen, position); | 
|---|
| 735 | } | 
|---|
| 736 |  | 
|---|
| 737 | #else | 
|---|
| 738 | QHighDpiScaling::ScaleAndOrigin QHighDpiScaling::scaleAndOrigin(const QPlatformScreen *, QPoint *) | 
|---|
| 739 | { | 
|---|
| 740 | return { qreal(1), QPoint() }; | 
|---|
| 741 | } | 
|---|
| 742 |  | 
|---|
| 743 | QHighDpiScaling::ScaleAndOrigin QHighDpiScaling::scaleAndOrigin(const QScreen *, QPoint *) | 
|---|
| 744 | { | 
|---|
| 745 | return { qreal(1), QPoint() }; | 
|---|
| 746 | } | 
|---|
| 747 |  | 
|---|
| 748 | QHighDpiScaling::ScaleAndOrigin QHighDpiScaling::scaleAndOrigin(const QWindow *, QPoint *) | 
|---|
| 749 | { | 
|---|
| 750 | return { qreal(1), QPoint() }; | 
|---|
| 751 | } | 
|---|
| 752 | #endif //QT_NO_HIGHDPISCALING | 
|---|
| 753 | QT_END_NAMESPACE | 
|---|
| 754 |  | 
|---|