Coverage Report

Created: 2026-03-31 07:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/qtbase/src/gui/kernel/qplatformscreen.cpp
Line
Count
Source
1
// Copyright (C) 2016 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
// Qt-Security score:significant reason:default
4
5
#include "qplatformscreen.h"
6
#include <QtCore/qdebug.h>
7
#include <QtGui/qguiapplication.h>
8
#include <qpa/qplatformcursor.h>
9
#include <QtGui/private/qguiapplication_p.h>
10
#include <qpa/qplatformscreen_p.h>
11
#include <qpa/qplatformintegration.h>
12
#include <QtGui/qscreen.h>
13
#include <QtGui/qwindow.h>
14
#include <private/qhighdpiscaling_p.h>
15
#include <private/qwindow_p.h>
16
17
QT_BEGIN_NAMESPACE
18
19
QPlatformScreen::QPlatformScreen()
20
0
    : d_ptr(new QPlatformScreenPrivate)
21
0
{
22
0
    Q_D(QPlatformScreen);
23
0
    d->screen = nullptr;
24
0
}
25
26
QPlatformScreen::~QPlatformScreen()
27
0
{
28
0
    Q_D(QPlatformScreen);
29
0
    Q_ASSERT_X(!d->screen, "QPlatformScreen",
30
0
        "QPlatformScreens should be removed via QWindowSystemInterface::handleScreenRemoved()");
31
0
}
32
33
/*!
34
    This function is called when Qt needs to be able to grab the content of a window.
35
36
    Returns the content of the window specified with the WId handle within the boundaries of
37
    QRect(x,y,width,height).
38
*/
39
QPixmap QPlatformScreen::grabWindow(WId window, int x, int y, int width, int height) const
40
0
{
41
0
    Q_UNUSED(window);
42
0
    Q_UNUSED(x);
43
0
    Q_UNUSED(y);
44
0
    Q_UNUSED(width);
45
0
    Q_UNUSED(height);
46
0
    return QPixmap();
47
0
}
48
49
/*!
50
    Return the given top level window for a given position.
51
52
    Default implementation retrieves a list of all top level windows and finds the first window
53
    which contains point \a pos
54
*/
55
QWindow *QPlatformScreen::topLevelAt(const QPoint & pos) const
56
0
{
57
0
    const QWindowList list = QGuiApplication::topLevelWindows();
58
0
    const auto crend = list.crend();
59
0
    for (auto it = list.crbegin(); it != crend; ++it) {
60
0
        QWindow *w = *it;
61
0
        if (w->isVisible() && QHighDpi::toNativePixels(w->geometry(), w).contains(pos))
62
0
            return w;
63
0
    }
64
65
0
    return nullptr;
66
0
}
67
68
/*!
69
    Return all windows residing on this screen.
70
*/
71
QWindowList QPlatformScreen::windows() const
72
0
{
73
0
    QWindowList windows;
74
0
    for (QWindow *window : QGuiApplication::allWindows()) {
75
0
        if (platformScreenForWindow(window) != this)
76
0
            continue;
77
0
        windows.append(window);
78
0
    }
79
0
    return windows;
80
0
}
81
82
/*!
83
  Find the sibling screen corresponding to \a globalPos.
84
85
  Returns this screen if no suitable screen is found at the position.
86
 */
87
const QPlatformScreen *QPlatformScreen::screenForPosition(const QPoint &point) const
88
0
{
89
0
    if (!geometry().contains(point)) {
90
0
        const auto screens = virtualSiblings();
91
0
        for (const QPlatformScreen *screen : screens) {
92
0
            if (screen->geometry().contains(point))
93
0
                return screen;
94
0
        }
95
0
    }
96
0
    return this;
97
0
}
98
99
100
/*!
101
    Returns a list of all the platform screens that are part of the same
102
    virtual desktop.
103
104
    Screens part of the same virtual desktop share a common coordinate system,
105
    and windows can be freely moved between them.
106
*/
107
QList<QPlatformScreen *> QPlatformScreen::virtualSiblings() const
108
0
{
109
0
    QList<QPlatformScreen *> list;
110
0
    list << const_cast<QPlatformScreen *>(this);
111
0
    return list;
112
0
}
113
114
QScreen *QPlatformScreen::screen() const
115
0
{
116
0
    Q_D(const QPlatformScreen);
117
0
    return d->screen;
118
0
}
119
120
/*!
121
    Reimplement this function in subclass to return the physical size of the
122
    screen, in millimeters. The physical size represents the actual physical
123
    dimensions of the display.
124
125
    The default implementation takes the pixel size of the screen, considers a
126
    resolution of 100 dots per inch, and returns the calculated physical size.
127
    A device with a screen that has different resolutions will need to be
128
    supported by a suitable reimplementation of this function.
129
130
    \sa logcalDpi
131
*/
132
QSizeF QPlatformScreen::physicalSize() const
133
0
{
134
0
    static const int dpi = 100;
135
0
    return QSizeF(geometry().size()) / dpi * qreal(25.4);
136
0
}
137
138
/*!
139
    Reimplement this function in subclass to return the logical horizontal
140
    and vertical dots per inch metrics of the screen.
141
142
    The logical dots per inch metrics are used by Qt to scale the user interface.
143
144
    The default implementation returns logicalBaseDpi(), which results in a
145
    UI scale factor of 1.0.
146
147
    \sa physicalSize
148
*/
149
QDpi QPlatformScreen::logicalDpi() const
150
0
{
151
0
    return logicalBaseDpi();
152
0
}
153
154
// Helper function for accessing the platform screen logical dpi
155
// which accounts for QT_FONT_DPI.
156
QDpi QPlatformScreen::overrideDpi(const QDpi &in)
157
0
{
158
0
    static const int overrideDpi = qEnvironmentVariableIntValue("QT_FONT_DPI");
159
0
    return overrideDpi > 0 ?  QDpi(overrideDpi, overrideDpi) : in;
160
0
}
161
162
/*!
163
    Reimplement to return the base logical DPI for the platform. This
164
    DPI value should correspond to a standard-DPI (1x) display. The
165
    default implementation returns 96.
166
167
    QtGui will use this value (together with logicalDpi) to compute
168
    the scale factor when high-DPI scaling is enabled, as follows:
169
        factor = logicalDPI / baseDPI
170
*/
171
QDpi QPlatformScreen::logicalBaseDpi() const
172
0
{
173
0
    return QDpi(96, 96);
174
0
}
175
176
/*!
177
    Reimplement this function in subclass to return the device pixel ratio
178
    for the screen. This is the ratio between physical pixels and the
179
    device-independent pixels of the windowing system. The default
180
    implementation returns 1.0.
181
182
    \sa QPlatformWindow::devicePixelRatio()
183
*/
184
qreal QPlatformScreen::devicePixelRatio() const
185
0
{
186
0
    return 1.0;
187
0
}
188
189
/*!
190
    Reimplement this function in subclass to return the vertical refresh rate
191
    of the screen, in Hz.
192
193
    The default returns 60, a sensible default for modern displays.
194
*/
195
qreal QPlatformScreen::refreshRate() const
196
0
{
197
0
    return 60;
198
0
}
199
200
/*!
201
    Reimplement this function in subclass to return the native orientation
202
    of the screen, e.g. the orientation where the logo sticker of the device
203
    appears the right way up.
204
205
    The default implementation returns Qt::PrimaryOrientation.
206
*/
207
Qt::ScreenOrientation QPlatformScreen::nativeOrientation() const
208
0
{
209
0
    return Qt::PrimaryOrientation;
210
0
}
211
212
/*!
213
    Reimplement this function in subclass to return the current orientation
214
    of the screen, for example based on accelerometer data to determine
215
    the device orientation.
216
217
    The default implementation returns Qt::PrimaryOrientation.
218
*/
219
Qt::ScreenOrientation QPlatformScreen::orientation() const
220
0
{
221
0
    return Qt::PrimaryOrientation;
222
0
}
223
224
QPlatformScreen * QPlatformScreen::platformScreenForWindow(const QWindow *window)
225
0
{
226
    // QTBUG 32681: It can happen during the transition between screens
227
    // when one screen is disconnected that the window doesn't have a screen.
228
0
    if (!window->screen())
229
0
        return nullptr;
230
0
    return window->screen()->handle();
231
0
}
232
233
/*!
234
    Reimplement this function in subclass to return the manufacturer
235
    of this screen.
236
237
    The default implementation returns an empty string.
238
239
    \since 5.9
240
*/
241
QString QPlatformScreen::manufacturer() const
242
0
{
243
0
    return QString();
244
0
}
245
246
/*!
247
    Reimplement this function in subclass to return the model
248
    of this screen.
249
250
    The default implementation returns an empty string.
251
252
    \since 5.9
253
*/
254
QString QPlatformScreen::model() const
255
0
{
256
0
    return QString();
257
0
}
258
259
/*!
260
    Reimplement this function in subclass to return the serial number
261
    of this screen.
262
263
    The default implementation returns an empty string.
264
265
    \since 5.9
266
*/
267
QString QPlatformScreen::serialNumber() const
268
0
{
269
0
    return QString();
270
0
}
271
272
/*!
273
    \class QPlatformScreen
274
    \since 4.8
275
    \internal
276
    \preliminary
277
    \ingroup qpa
278
279
    \brief The QPlatformScreen class provides an abstraction for visual displays.
280
281
    Many window systems has support for retrieving information on the attached displays. To be able
282
    to query the display QPA uses QPlatformScreen. Qt its self is most dependent on the
283
    physicalSize() function, since this is the function it uses to calculate the dpi to use when
284
    converting point sizes to pixels sizes. However, this is unfortunate on some systems, as the
285
    native system fakes its dpi size.
286
 */
287
288
/*! \fn QRect QPlatformScreen::geometry() const = 0
289
    Reimplement in subclass to return the pixel geometry of the screen
290
*/
291
292
/*! \fn QRect QPlatformScreen::availableGeometry() const
293
    Reimplement in subclass to return the pixel geometry of the available space
294
    This normally is the desktop screen minus the task manager, global menubar etc.
295
*/
296
297
/*! \fn int QPlatformScreen::depth() const = 0
298
    Reimplement in subclass to return current depth of the screen
299
*/
300
301
/*! \fn QImage::Format QPlatformScreen::format() const = 0
302
    Reimplement in subclass to return the image format which corresponds to the screen format
303
*/
304
305
/*!
306
    Reimplement this function in subclass to return the cursor of the screen.
307
308
    The default implementation returns \nullptr.
309
*/
310
QPlatformCursor *QPlatformScreen::cursor() const
311
0
{
312
0
    return nullptr;
313
0
}
314
315
/*!
316
  Convenience method to resize all the maximized and fullscreen windows
317
  of this platform screen.
318
*/
319
void QPlatformScreen::resizeMaximizedWindows()
320
0
{
321
    // 'screen()' still has the old geometry (in device independent pixels),
322
    // while 'this' has the new geometry (in native pixels)
323
0
    const QRect oldGeometry = screen()->geometry();
324
0
    const QRect oldAvailableGeometry = screen()->availableGeometry();
325
0
    const QRect newNativeGeometry = this->geometry();
326
0
    const QRect newNativeAvailableGeometry = this->availableGeometry();
327
328
0
    const bool supportsMaximizeUsingFullscreen = QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::MaximizeUsingFullscreenGeometry);
329
330
0
    for (QWindow *w : windows()) {
331
        // Skip non-platform windows, e.g., offscreen windows.
332
0
        if (!w->handle())
333
0
            continue;
334
335
        // Set QPlatformWindow size in native pixels, and let the platform's geometry
336
        // change signals update the QWindow geomeyry. This way we make sure that the
337
        // platform window geometry covers the entire (available) platform screen geometry,
338
        // also when fractional DPRs introduce rounding errors in the device independent
339
        // QWindow and QScreen sizes.
340
0
        if (supportsMaximizeUsingFullscreen
341
0
                && w->windowState() & Qt::WindowMaximized
342
0
                && w->flags() & Qt::ExpandedClientAreaHint) {
343
0
            w->handle()->setGeometry(newNativeGeometry);
344
0
        } else if (w->windowState() & Qt::WindowMaximized || w->geometry() == oldAvailableGeometry) {
345
0
            w->handle()->setGeometry(newNativeAvailableGeometry);
346
0
        } else if (w->windowState() & Qt::WindowFullScreen || w->geometry() == oldGeometry) {
347
0
            w->handle()->setGeometry(newNativeGeometry);
348
0
        }
349
0
    }
350
0
}
351
352
// i must be power of two
353
static int log2(uint i)
354
0
{
355
0
    if (i == 0)
356
0
        return -1;
357
358
0
    int result = 0;
359
0
    while (!(i & 1)) {
360
0
        ++result;
361
0
        i >>= 1;
362
0
    }
363
0
    return result;
364
0
}
365
366
int QPlatformScreen::angleBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b)
367
0
{
368
0
    if (a == Qt::PrimaryOrientation || b == Qt::PrimaryOrientation) {
369
0
        qWarning("Use QScreen version of %sBetween() when passing Qt::PrimaryOrientation", "angle");
370
0
        return 0;
371
0
    }
372
373
0
    if (a == b)
374
0
        return 0;
375
376
0
    int ia = log2(uint(a));
377
0
    int ib = log2(uint(b));
378
379
0
    int delta = ia - ib;
380
381
0
    if (delta < 0)
382
0
        delta = delta + 4;
383
384
0
    int angles[] = { 0, 90, 180, 270 };
385
0
    return angles[delta];
386
0
}
387
388
QTransform QPlatformScreen::transformBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b, const QRect &target)
389
0
{
390
0
    if (a == Qt::PrimaryOrientation || b == Qt::PrimaryOrientation) {
391
0
        qWarning("Use QScreen version of %sBetween() when passing Qt::PrimaryOrientation", "transform");
392
0
        return QTransform();
393
0
    }
394
395
0
    if (a == b)
396
0
        return QTransform();
397
398
0
    int angle = angleBetween(a, b);
399
400
0
    QTransform result;
401
0
    switch (angle) {
402
0
    case 90:
403
0
        result.translate(target.width(), 0);
404
0
        break;
405
0
    case 180:
406
0
        result.translate(target.width(), target.height());
407
0
        break;
408
0
    case 270:
409
0
        result.translate(0, target.height());
410
0
        break;
411
0
    default:
412
0
        Q_ASSERT(false);
413
0
    }
414
0
    result.rotate(angle);
415
416
0
    return result;
417
0
}
418
419
QRect QPlatformScreen::mapBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b, const QRect &rect)
420
0
{
421
0
    if (a == Qt::PrimaryOrientation || b == Qt::PrimaryOrientation) {
422
0
        qWarning("Use QScreen version of %sBetween() when passing Qt::PrimaryOrientation", "map");
423
0
        return rect;
424
0
    }
425
426
0
    if (a == b)
427
0
        return rect;
428
429
0
    if ((a == Qt::PortraitOrientation || a == Qt::InvertedPortraitOrientation)
430
0
        != (b == Qt::PortraitOrientation || b == Qt::InvertedPortraitOrientation))
431
0
    {
432
0
        return QRect(rect.y(), rect.x(), rect.height(), rect.width());
433
0
    }
434
435
0
    return rect;
436
0
}
437
438
/*!
439
  Returns a hint about this screen's subpixel layout structure.
440
441
  The default implementation queries the \b{QT_SUBPIXEL_AA_TYPE} env variable.
442
  This is just a hint because most platforms don't have a way to retrieve the correct value from hardware
443
  and instead rely on font configurations.
444
*/
445
QPlatformScreen::SubpixelAntialiasingType QPlatformScreen::subpixelAntialiasingTypeHint() const
446
0
{
447
0
    static int type = -1;
448
0
    if (type == -1) {
449
0
        QByteArray env = qgetenv("QT_SUBPIXEL_AA_TYPE");
450
0
        if (env == "RGB")
451
0
            type = QPlatformScreen::Subpixel_RGB;
452
0
        else if (env == "BGR")
453
0
            type = QPlatformScreen::Subpixel_BGR;
454
0
        else if (env == "VRGB")
455
0
            type = QPlatformScreen::Subpixel_VRGB;
456
0
        else if (env == "VBGR")
457
0
            type = QPlatformScreen::Subpixel_VBGR;
458
0
        else
459
0
            type = QPlatformScreen::Subpixel_None;
460
0
    }
461
462
0
    return static_cast<QPlatformScreen::SubpixelAntialiasingType>(type);
463
0
}
464
465
/*!
466
  Returns the current power state.
467
468
  The default implementation always returns PowerStateOn.
469
*/
470
QPlatformScreen::PowerState QPlatformScreen::powerState() const
471
0
{
472
0
    return PowerStateOn;
473
0
}
474
475
/*!
476
  Sets the power state for this screen.
477
*/
478
void QPlatformScreen::setPowerState(PowerState state)
479
0
{
480
0
    Q_UNUSED(state);
481
0
}
482
483
/*!
484
    Reimplement this function in subclass to return the list
485
    of modes for this screen.
486
487
    The default implementation returns a list with
488
    only one mode from the current screen size and refresh rate.
489
490
    \sa QPlatformScreen::geometry
491
    \sa QPlatformScreen::refreshRate
492
493
    \since 5.9
494
*/
495
QList<QPlatformScreen::Mode> QPlatformScreen::modes() const
496
0
{
497
0
    QList<QPlatformScreen::Mode> list;
498
0
    list.append({geometry().size(), refreshRate()});
499
0
    return list;
500
0
}
501
502
/*!
503
    Reimplement this function in subclass to return the
504
    index of the current mode from the modes list.
505
506
    The default implementation returns 0.
507
508
    \sa QPlatformScreen::modes
509
510
    \since 5.9
511
*/
512
int QPlatformScreen::currentMode() const
513
0
{
514
0
    return 0;
515
0
}
516
517
/*!
518
    Reimplement this function in subclass to return the preferred
519
    mode index from the modes list.
520
521
    The default implementation returns 0.
522
523
    \sa QPlatformScreen::modes
524
525
    \since 5.9
526
*/
527
int QPlatformScreen::preferredMode() const
528
0
{
529
0
    return 0;
530
0
}
531
532
QList<QPlatformScreen *> QPlatformPlaceholderScreen::virtualSiblings() const
533
0
{
534
0
    QList<QPlatformScreen *> siblings;
535
536
0
    if (!m_virtualSibling)
537
0
        return siblings;
538
539
0
    for (QScreen *screen : QGuiApplication::screens()) {
540
0
        if (screen->handle() && screen->handle() != this)
541
0
            siblings << screen->handle();
542
0
    }
543
0
    return siblings;
544
0
}
545
546
QT_END_NAMESPACE