~gabriel1984sibiu/minitube/qt5.6

« back to all changes in this revision

Viewing changes to src/gui/kernel/qhighdpiscaling.cpp

  • Committer: Grevutiu Gabriel
  • Date: 2017-06-13 08:43:17 UTC
  • Revision ID: gabriel1984sibiu@gmail.com-20170613084317-ek0zqe0u9g3ocvi8
OriginalĀ upstreamĀ code

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "private/qscreen_p.h"
 
45
 
 
46
#include <QtCore/qdebug.h>
 
47
 
 
48
QT_BEGIN_NAMESPACE
 
49
 
 
50
Q_LOGGING_CATEGORY(lcScaling, "qt.scaling");
 
51
 
 
52
#ifndef QT_NO_HIGHDPISCALING
 
53
static const char legacyDevicePixelEnvVar[] = "QT_DEVICE_PIXEL_RATIO";
 
54
static const char scaleFactorEnvVar[] = "QT_SCALE_FACTOR";
 
55
static const char autoScreenEnvVar[] = "QT_AUTO_SCREEN_SCALE_FACTOR";
 
56
static const char screenFactorsEnvVar[] = "QT_SCREEN_SCALE_FACTORS";
 
57
 
 
58
static inline qreal initialGlobalScaleFactor()
 
59
{
 
60
 
 
61
    qreal result = 1;
 
62
    if (qEnvironmentVariableIsSet(scaleFactorEnvVar)) {
 
63
        bool ok;
 
64
        const qreal f = qgetenv(scaleFactorEnvVar).toDouble(&ok);
 
65
        if (ok && f > 0) {
 
66
            qCDebug(lcScaling) << "Apply " << scaleFactorEnvVar << f;
 
67
            result = f;
 
68
        }
 
69
    } else {
 
70
        if (qEnvironmentVariableIsSet(legacyDevicePixelEnvVar)) {
 
71
            qWarning() << "Warning:" << legacyDevicePixelEnvVar << "is deprecated. Instead use:" << endl
 
72
                       << "   " << autoScreenEnvVar << "to enable platform plugin controlled per-screen factors." << endl
 
73
                       << "   " << screenFactorsEnvVar << "to set per-screen factors." << endl
 
74
                       << "   " << scaleFactorEnvVar << "to set the application global scale factor.";
 
75
 
 
76
            int dpr = qEnvironmentVariableIntValue(legacyDevicePixelEnvVar);
 
77
            if (dpr > 0)
 
78
                result = dpr;
 
79
        }
 
80
    }
 
81
    return result;
 
82
}
 
83
 
 
84
/*!
 
85
    \class QHighDpiScaling
 
86
    \since 5.6
 
87
    \internal
 
88
    \preliminary
 
89
    \ingroup qpa
 
90
 
 
91
    \brief Collection of utility functions for UI scaling.
 
92
 
 
93
    QHighDpiScaling implements utility functions for high-dpi scaling for use
 
94
    on operating systems that provide limited support for native scaling. In
 
95
    addition this functionality can be used for simulation and testing purposes.
 
96
 
 
97
    The functions support scaling between the device independent coordinate
 
98
    system used by Qt applications and the native coordinate system used by
 
99
    the platform plugins. Intended usage locations are the low level / platform
 
100
    plugin interfacing parts of QtGui, for example the QWindow, QScreen and
 
101
    QWindowSystemInterface implementation.
 
102
 
 
103
    There are now up to three active coordinate systems in Qt:
 
104
 
 
105
     ---------------------------------------------------
 
106
    |  Application            Device Independent Pixels |   devicePixelRatio
 
107
    |  Qt Widgets                                       |         =
 
108
    |  Qt Gui                                           |
 
109
    |---------------------------------------------------|   Qt Scale Factor
 
110
    |  Qt Gui QPlatform*      Native Pixels             |         *
 
111
    |  Qt platform plugin                               |
 
112
    |---------------------------------------------------|   OS Scale Factor
 
113
    |  Display                Device Pixels             |
 
114
    |  (Graphics Buffers)                               |
 
115
    -----------------------------------------------------
 
116
 
 
117
    This is an simplification and shows the main coordinate system. All layers
 
118
    may work with device pixels in specific cases: OpenGL, creating the backing
 
119
    store, and QPixmap management. The "Native Pixels" coordinate system is
 
120
    internal to Qt and should not be exposed to Qt users: Seen from the outside
 
121
    there are only two coordinate systems: device independent pixels and device
 
122
    pixels.
 
123
 
 
124
    The devicePixelRatio seen by applications is the product of the Qt scale
 
125
    factor and the OS scale factor. The value of the scale factors may be 1,
 
126
    in which case two or more of the coordinate systems are equivalent. Platforms
 
127
    that (may) have an OS scale factor include \macos, iOS and Wayland.
 
128
 
 
129
    Note that the functions in this file do not work with the OS scale factor
 
130
    directly and are limited to converting between device independent and native
 
131
    pixels. The OS scale factor is accunted for by QWindow::devicePixelRatio()
 
132
    and similar functions.
 
133
 
 
134
    Configuration Examples:
 
135
 
 
136
    'Classic': Device Independent Pixels = Native Pixels = Device Pixels
 
137
     ---------------------------------------------------    devicePixelRatio: 1
 
138
    |  Application / Qt Gui             100 x 100       |
 
139
    |                                                   |   Qt Scale Factor: 1
 
140
    |  Qt Platform / OS                 100 x 100       |
 
141
    |                                                   |   OS Scale Factor: 1
 
142
    |  Display                          100 x 100       |
 
143
    -----------------------------------------------------
 
144
 
 
145
    'Retina Device': Device Independent Pixels = Native Pixels
 
146
     ---------------------------------------------------    devicePixelRatio: 2
 
147
    |  Application / Qt Gui             100 x 100       |
 
148
    |                                                   |   Qt Scale Factor: 1
 
149
    |  Qt Platform / OS                 100 x 100       |
 
150
    |---------------------------------------------------|   OS Scale Factor: 2
 
151
    |  Display                          200 x 200       |
 
152
    -----------------------------------------------------
 
153
 
 
154
    '2x Qt Scaling': Native Pixels = Device Pixels
 
155
     ---------------------------------------------------    devicePixelRatio: 2
 
156
    |  Application / Qt Gui             100 x 100       |
 
157
    |---------------------------------------------------|   Qt Scale Factor: 2
 
158
    |  Qt Platform / OS                 200 x 200       |
 
159
    |                                                   |   OS Scale Factor: 1
 
160
    |  Display                          200 x 200       |
 
161
    -----------------------------------------------------
 
162
 
 
163
    The Qt Scale Factor is the product of two sub-scale factors, which
 
164
    are independently either set or determined by the platform plugin.
 
165
    Several APIs are offered for this, targeting both developers and
 
166
    end users. All scale factors are of type qreal.
 
167
 
 
168
    1) A global scale factor
 
169
        The QT_SCALE_FACTOR environment variable can be used to set
 
170
        a global scale factor for all windows in the processs. This
 
171
        is useful for testing and debugging (you can simulate any
 
172
        devicePixelRatio without needing access to special hardware),
 
173
        and perhaps also for targeting a specific application to
 
174
        a specific display type (embedded use cases).
 
175
 
 
176
    2) Per-screen scale factors
 
177
        Some platform plugins support providing a per-screen scale
 
178
        factor based on display density information. These platforms
 
179
        include X11, Windows, and Android.
 
180
 
 
181
        There are two APIs for enabling or disabling this behavior:
 
182
            - The QT_AUTO_SCREEN_SCALE_FACTOR environment variable.
 
183
            - The AA_EnableHighDpiScaling and AA_DisableHighDpiScaling
 
184
              application attributes
 
185
 
 
186
        Enabling either will make QHighDpiScaling call QPlatformScreen::pixelDensity()
 
187
        and use the value provided as the scale factor for the screen in
 
188
        question. Disabling is done on a 'veto' basis where either the
 
189
        environment or the application can disable the scaling. The intended use
 
190
        cases are 'My system is not providing correct display density
 
191
        information' and 'My application needs to work in display pixels',
 
192
        respectively.
 
193
 
 
194
        The QT_SCREEN_SCALE_FACTORS environment variable can be used to set the screen
 
195
        scale factors manually. Set this to a semicolon-separated
 
196
        list of scale factors (matching the order of QGuiApplications::screens()),
 
197
        or to a list of name=value pairs (where name matches QScreen::name()).
 
198
 
 
199
    Coordinate conversion functions must be used when writing code that passes
 
200
    geometry across the Qt Gui / Platform plugin boundary. The main conversion
 
201
    functions are:
 
202
        T toNativePixels(T, QWindow *)
 
203
        T fromNativePixels(T, QWindow*)
 
204
 
 
205
    The following classes in QtGui use native pixels, for the convenience of the
 
206
    plataform plugins:
 
207
        QPlatformWindow
 
208
        QPlatformScreen
 
209
        QWindowSystemInterface (API only - Events are in device independent pixels)
 
210
 
 
211
    As a special consideration platform plugin code should be careful about
 
212
    calling QtGui geometry accessor functions:
 
213
        QRect r = window->geometry();
 
214
    Here the returned geometry is in device independent pixels. Add a conversion call:
 
215
        QRect r = QHighDpi::toNativePixels(window->geometry());
 
216
    (Avoiding calling QWindow and instead using the QPlatformWindow geometry
 
217
     might be a better course of action in this case.)
 
218
*/
 
219
 
 
220
qreal QHighDpiScaling::m_factor = 1.0;
 
221
bool QHighDpiScaling::m_active = false; //"overall active" - is there any scale factor set.
 
222
bool QHighDpiScaling::m_usePixelDensity = false; // use scale factor from platform plugin
 
223
bool QHighDpiScaling::m_pixelDensityScalingActive = false; // pixel density scale factor > 1
 
224
bool QHighDpiScaling::m_globalScalingActive = false; // global scale factor is active
 
225
bool QHighDpiScaling::m_screenFactorSet = false; // QHighDpiScaling::setScreenFactor has been used
 
226
QDpi QHighDpiScaling::m_logicalDpi = QDpi(-1,-1); // The scaled logical DPI of the primary screen
 
227
 
 
228
/*
 
229
    Initializes the QHighDpiScaling global variables. Called before the
 
230
    platform plugin is created.
 
231
*/
 
232
 
 
233
static inline bool usePixelDensity()
 
234
{
 
235
    // Determine if we should set a scale factor based on the pixel density
 
236
    // reported by the platform plugin. There are several enablers and several
 
237
    // disablers. A single disable may veto all other enablers.
 
238
    if (QCoreApplication::testAttribute(Qt::AA_DisableHighDpiScaling))
 
239
        return false;
 
240
    bool screenEnvValueOk;
 
241
    const int screenEnvValue = qEnvironmentVariableIntValue(autoScreenEnvVar, &screenEnvValueOk);
 
242
    if (screenEnvValueOk && screenEnvValue < 1)
 
243
        return false;
 
244
    return QCoreApplication::testAttribute(Qt::AA_EnableHighDpiScaling)
 
245
        || (screenEnvValueOk && screenEnvValue > 0)
 
246
        || (qEnvironmentVariableIsSet(legacyDevicePixelEnvVar) && qgetenv(legacyDevicePixelEnvVar).toLower() == "auto");
 
247
}
 
248
 
 
249
void QHighDpiScaling::initHighDpiScaling()
 
250
{
 
251
    // Determine if there is a global scale factor set.
 
252
    m_factor = initialGlobalScaleFactor();
 
253
    m_globalScalingActive = !qFuzzyCompare(m_factor, qreal(1));
 
254
 
 
255
    m_usePixelDensity = usePixelDensity();
 
256
 
 
257
    m_pixelDensityScalingActive = false; //set in updateHighDpiScaling below
 
258
 
 
259
    // we update m_active in updateHighDpiScaling, but while we create the
 
260
    // screens, we have to assume that m_usePixelDensity implies scaling
 
261
    m_active = m_globalScalingActive || m_usePixelDensity;
 
262
}
 
263
 
 
264
void QHighDpiScaling::updateHighDpiScaling()
 
265
{
 
266
    if (QCoreApplication::testAttribute(Qt::AA_DisableHighDpiScaling))
 
267
        return;
 
268
 
 
269
    if (m_usePixelDensity && !m_pixelDensityScalingActive) {
 
270
        const auto screens = QGuiApplication::screens();
 
271
        for (QScreen *screen : screens) {
 
272
            if (!qFuzzyCompare(screenSubfactor(screen->handle()), qreal(1))) {
 
273
                m_pixelDensityScalingActive = true;
 
274
                break;
 
275
            }
 
276
        }
 
277
    }
 
278
    if (qEnvironmentVariableIsSet(screenFactorsEnvVar)) {
 
279
        int i = 0;
 
280
        const auto specs = qgetenv(screenFactorsEnvVar).split(';');
 
281
        for (const QByteArray &spec : specs) {
 
282
            QScreen *screen = 0;
 
283
            int equalsPos = spec.lastIndexOf('=');
 
284
            double factor = 0;
 
285
            if (equalsPos > 0) {
 
286
                // support "name=factor"
 
287
                QByteArray name = spec.mid(0, equalsPos);
 
288
                QByteArray f = spec.mid(equalsPos + 1);
 
289
                bool ok;
 
290
                factor = f.toDouble(&ok);
 
291
                if (ok) {
 
292
                    const auto screens = QGuiApplication::screens();
 
293
                    for (QScreen *s : screens) {
 
294
                        if (s->name() == QString::fromLocal8Bit(name)) {
 
295
                            screen = s;
 
296
                            break;
 
297
                        }
 
298
                    }
 
299
                }
 
300
            } else {
 
301
                // listing screens in order
 
302
                bool ok;
 
303
                factor = spec.toDouble(&ok);
 
304
                if (ok && i < QGuiApplication::screens().count())
 
305
                    screen = QGuiApplication::screens().at(i);
 
306
            }
 
307
            if (screen)
 
308
                setScreenFactor(screen, factor);
 
309
            ++i;
 
310
        }
 
311
    }
 
312
    m_active = m_globalScalingActive || m_screenFactorSet || m_pixelDensityScalingActive;
 
313
 
 
314
    QPlatformScreen *primaryScreen = QGuiApplication::primaryScreen()->handle();
 
315
    qreal sf = screenSubfactor(primaryScreen);
 
316
    QDpi primaryDpi = primaryScreen->logicalDpi();
 
317
    m_logicalDpi = QDpi(primaryDpi.first / sf, primaryDpi.second / sf);
 
318
}
 
319
 
 
320
/*
 
321
    Sets the global scale factor which is applied to all windows.
 
322
*/
 
323
void QHighDpiScaling::setGlobalFactor(qreal factor)
 
324
{
 
325
    if (qFuzzyCompare(factor, m_factor))
 
326
        return;
 
327
    if (!QGuiApplication::allWindows().isEmpty())
 
328
        qWarning("QHighDpiScaling::setFactor: Should only be called when no windows exist.");
 
329
 
 
330
    m_globalScalingActive = !qFuzzyCompare(factor, qreal(1));
 
331
    m_factor = m_globalScalingActive ? factor : qreal(1);
 
332
    m_active = m_globalScalingActive || m_screenFactorSet || m_pixelDensityScalingActive;
 
333
    const auto screens = QGuiApplication::screens();
 
334
    for (QScreen *screen : screens)
 
335
         screen->d_func()->updateHighDpi();
 
336
}
 
337
 
 
338
static const char scaleFactorProperty[] = "_q_scaleFactor";
 
339
 
 
340
/*
 
341
    Sets a per-screen scale factor.
 
342
*/
 
343
void QHighDpiScaling::setScreenFactor(QScreen *screen, qreal factor)
 
344
{
 
345
    m_screenFactorSet = true;
 
346
    m_active = true;
 
347
    screen->setProperty(scaleFactorProperty, QVariant(factor));
 
348
 
 
349
    // hack to force re-evaluation of screen geometry
 
350
    if (screen->handle())
 
351
        screen->d_func()->setPlatformScreen(screen->handle()); // updates geometries based on scale factor
 
352
}
 
353
 
 
354
QPoint QHighDpiScaling::mapPositionToNative(const QPoint &pos, const QPlatformScreen *platformScreen)
 
355
{
 
356
    if (!platformScreen)
 
357
        return pos;
 
358
    const qreal scaleFactor = factor(platformScreen);
 
359
    const QPoint topLeft = platformScreen->geometry().topLeft();
 
360
    return (pos - topLeft) * scaleFactor + topLeft;
 
361
}
 
362
 
 
363
QPoint QHighDpiScaling::mapPositionFromNative(const QPoint &pos, const QPlatformScreen *platformScreen)
 
364
{
 
365
    if (!platformScreen)
 
366
        return pos;
 
367
    const qreal scaleFactor = factor(platformScreen);
 
368
    const QPoint topLeft = platformScreen->geometry().topLeft();
 
369
    return (pos - topLeft) / scaleFactor + topLeft;
 
370
}
 
371
 
 
372
qreal QHighDpiScaling::screenSubfactor(const QPlatformScreen *screen)
 
373
{
 
374
    qreal factor = qreal(1.0);
 
375
    if (screen) {
 
376
        if (m_usePixelDensity)
 
377
            factor *= screen->pixelDensity();
 
378
        if (m_screenFactorSet) {
 
379
            QVariant screenFactor = screen->screen()->property(scaleFactorProperty);
 
380
            if (screenFactor.isValid())
 
381
                factor *= screenFactor.toReal();
 
382
        }
 
383
    }
 
384
    return factor;
 
385
}
 
386
 
 
387
QDpi QHighDpiScaling::logicalDpi()
 
388
{
 
389
    return m_logicalDpi;
 
390
}
 
391
 
 
392
qreal QHighDpiScaling::factor(const QScreen *screen)
 
393
{
 
394
    // Fast path for when scaling in Qt is not used at all.
 
395
    if (!m_active)
 
396
        return qreal(1.0);
 
397
 
 
398
    // The effective factor for a given screen is the product of the
 
399
    // screen and global sub-factors
 
400
    qreal factor = m_factor;
 
401
    if (screen)
 
402
        factor *= screenSubfactor(screen->handle());
 
403
    return factor;
 
404
}
 
405
 
 
406
qreal QHighDpiScaling::factor(const QPlatformScreen *platformScreen)
 
407
{
 
408
    if (!m_active)
 
409
        return qreal(1.0);
 
410
 
 
411
    return m_factor * screenSubfactor(platformScreen);
 
412
}
 
413
 
 
414
qreal QHighDpiScaling::factor(const QWindow *window)
 
415
{
 
416
    if (!m_active)
 
417
        return qreal(1.0);
 
418
 
 
419
    return factor(window ? window->screen() : QGuiApplication::primaryScreen());
 
420
}
 
421
 
 
422
QPoint QHighDpiScaling::origin(const QScreen *screen)
 
423
{
 
424
    return screen->geometry().topLeft();
 
425
}
 
426
 
 
427
QPoint QHighDpiScaling::origin(const QPlatformScreen *platformScreen)
 
428
{
 
429
    return platformScreen->geometry().topLeft();
 
430
}
 
431
 
 
432
#endif //QT_NO_HIGHDPISCALING
 
433
QT_END_NAMESPACE