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
4#include "qscreen.h"
5#include "qscreen_p.h"
6#include "qpixmap.h"
7#include "qguiapplication_p.h"
8#include <qpa/qplatformscreen.h>
9#include <qpa/qplatformscreen_p.h>
10
11#include <QtCore/QDebug>
12#include <QtCore/private/qobject_p.h>
13#include "qhighdpiscaling_p.h"
14
15QT_BEGIN_NAMESPACE
16
17/*!
18 \class QScreen
19 \since 5.0
20 \brief The QScreen class is used to query screen properties.
21 \inmodule QtGui
22
23 A note on logical vs physical dots per inch: physical DPI is based on the
24 actual physical pixel sizes when available, and is useful for print preview
25 and other cases where it's desirable to know the exact physical dimensions
26 of screen displayed contents.
27
28 Logical dots per inch are used to convert font and user interface elements
29 from point sizes to pixel sizes, and might be different from the physical
30 dots per inch. The logical dots per inch are sometimes user-settable in the
31 desktop environment's settings panel, to let the user globally control UI
32 and font sizes in different applications.
33
34 \note Both physical and logical DPI are expressed in device-independent dots.
35 Multiply by QScreen::devicePixelRatio() to get device-dependent density.
36
37 \inmodule QtGui
38*/
39
40QScreen::QScreen(QPlatformScreen *platformScreen)
41 : QObject(*new QScreenPrivate(), nullptr)
42{
43 Q_D(QScreen);
44
45 d->platformScreen = platformScreen;
46 platformScreen->d_func()->screen = this;
47
48 d->orientation = platformScreen->orientation();
49 d->logicalDpi = QPlatformScreen::overrideDpi(in: platformScreen->logicalDpi());
50 d->refreshRate = platformScreen->refreshRate();
51 // safeguard ourselves against buggy platform behavior...
52 if (d->refreshRate < 1.0)
53 d->refreshRate = 60.0;
54
55 d->updateGeometry();
56 d->updatePrimaryOrientation(); // derived from the geometry
57}
58
59void QScreenPrivate::updateGeometry()
60{
61 qreal scaleFactor = QHighDpiScaling::factor(context: platformScreen);
62 QRect nativeGeometry = platformScreen->geometry();
63 geometry = QRect(nativeGeometry.topLeft(), QHighDpi::fromNative(value: nativeGeometry.size(), scaleFactor));
64 availableGeometry = QHighDpi::fromNative(value: platformScreen->availableGeometry(), scaleFactor, origin: geometry.topLeft());
65}
66
67/*!
68 Destroys the screen.
69
70 \internal
71 */
72QScreen::~QScreen()
73{
74 Q_ASSERT_X(!QGuiApplicationPrivate::screen_list.contains(this), "QScreen",
75 "QScreens should be removed via QWindowSystemInterface::handleScreenRemoved()");
76}
77
78/*!
79 Get the platform screen handle.
80
81 \sa {Qt Platform Abstraction}{Qt Platform Abstraction (QPA)}
82*/
83QPlatformScreen *QScreen::handle() const
84{
85 Q_D(const QScreen);
86 return d->platformScreen;
87}
88
89/*!
90 \property QScreen::name
91 \brief a user presentable string representing the screen
92
93 For example, on X11 these correspond to the XRandr screen names,
94 typically "VGA1", "HDMI1", etc.
95
96 \note The user presentable string is not guaranteed to match the
97 result of any native APIs, and should not be used to uniquely identify
98 a screen.
99*/
100QString QScreen::name() const
101{
102 Q_D(const QScreen);
103 return d->platformScreen->name();
104}
105
106/*!
107 \property QScreen::manufacturer
108 \brief the manufacturer of the screen
109
110 \since 5.9
111*/
112QString QScreen::manufacturer() const
113{
114 Q_D(const QScreen);
115 return d->platformScreen->manufacturer();
116}
117
118/*!
119 \property QScreen::model
120 \brief the model of the screen
121
122 \since 5.9
123*/
124QString QScreen::model() const
125{
126 Q_D(const QScreen);
127 return d->platformScreen->model();
128}
129
130/*!
131 \property QScreen::serialNumber
132 \brief the serial number of the screen
133
134 \since 5.9
135*/
136QString QScreen::serialNumber() const
137{
138 Q_D(const QScreen);
139 return d->platformScreen->serialNumber();
140}
141
142/*!
143 \property QScreen::depth
144 \brief the color depth of the screen
145*/
146int QScreen::depth() const
147{
148 Q_D(const QScreen);
149 return d->platformScreen->depth();
150}
151
152/*!
153 \property QScreen::size
154 \brief the pixel resolution of the screen
155*/
156QSize QScreen::size() const
157{
158 Q_D(const QScreen);
159 return d->geometry.size();
160}
161
162/*!
163 \property QScreen::physicalDotsPerInchX
164 \brief the number of physical dots or pixels per inch in the horizontal direction
165
166 This value represents the actual horizontal pixel density on the screen's display.
167 Depending on what information the underlying system provides the value might not be
168 entirely accurate.
169
170 \note Physical DPI is expressed in device-independent dots. Multiply by QScreen::devicePixelRatio()
171 to get device-dependent density.
172
173 \sa physicalDotsPerInchY()
174*/
175qreal QScreen::physicalDotsPerInchX() const
176{
177 return size().width() / physicalSize().width() * qreal(25.4);
178}
179
180/*!
181 \property QScreen::physicalDotsPerInchY
182 \brief the number of physical dots or pixels per inch in the vertical direction
183
184 This value represents the actual vertical pixel density on the screen's display.
185 Depending on what information the underlying system provides the value might not be
186 entirely accurate.
187
188 \note Physical DPI is expressed in device-independent dots. Multiply by QScreen::devicePixelRatio()
189 to get device-dependent density.
190
191 \sa physicalDotsPerInchX()
192*/
193qreal QScreen::physicalDotsPerInchY() const
194{
195 return size().height() / physicalSize().height() * qreal(25.4);
196}
197
198/*!
199 \property QScreen::physicalDotsPerInch
200 \brief the number of physical dots or pixels per inch
201
202 This value represents the pixel density on the screen's display.
203 Depending on what information the underlying system provides the value might not be
204 entirely accurate.
205
206 This is a convenience property that's simply the average of the physicalDotsPerInchX
207 and physicalDotsPerInchY properties.
208
209 \note Physical DPI is expressed in device-independent dots. Multiply by QScreen::devicePixelRatio()
210 to get device-dependent density.
211
212 \sa physicalDotsPerInchX()
213 \sa physicalDotsPerInchY()
214*/
215qreal QScreen::physicalDotsPerInch() const
216{
217 QSize sz = size();
218 QSizeF psz = physicalSize();
219 return ((sz.height() / psz.height()) + (sz.width() / psz.width())) * qreal(25.4 * 0.5);
220}
221
222/*!
223 \property QScreen::logicalDotsPerInchX
224 \brief the number of logical dots or pixels per inch in the horizontal direction
225
226 This value is used to convert font point sizes to pixel sizes.
227
228 \sa logicalDotsPerInchY()
229*/
230qreal QScreen::logicalDotsPerInchX() const
231{
232 Q_D(const QScreen);
233 if (QHighDpiScaling::isActive())
234 return QHighDpiScaling::logicalDpi(screen: this).first;
235 return d->logicalDpi.first;
236}
237
238/*!
239 \property QScreen::logicalDotsPerInchY
240 \brief the number of logical dots or pixels per inch in the vertical direction
241
242 This value is used to convert font point sizes to pixel sizes.
243
244 \sa logicalDotsPerInchX()
245*/
246qreal QScreen::logicalDotsPerInchY() const
247{
248 Q_D(const QScreen);
249 if (QHighDpiScaling::isActive())
250 return QHighDpiScaling::logicalDpi(screen: this).second;
251 return d->logicalDpi.second;
252}
253
254/*!
255 \property QScreen::logicalDotsPerInch
256 \brief the number of logical dots or pixels per inch
257
258 This value can be used to convert font point sizes to pixel sizes.
259
260 This is a convenience property that's simply the average of the logicalDotsPerInchX
261 and logicalDotsPerInchY properties.
262
263 \sa logicalDotsPerInchX()
264 \sa logicalDotsPerInchY()
265*/
266qreal QScreen::logicalDotsPerInch() const
267{
268 Q_D(const QScreen);
269 QDpi dpi = QHighDpiScaling::isActive() ? QHighDpiScaling::logicalDpi(screen: this) : d->logicalDpi;
270 return (dpi.first + dpi.second) * qreal(0.5);
271}
272
273/*!
274 \property QScreen::devicePixelRatio
275 \brief the screen's ratio between physical pixels and device-independent pixels
276 \since 5.5
277
278 Returns the ratio between physical pixels and device-independent pixels for the screen.
279
280 Common values are 1.0 on normal displays and 2.0 on "retina" displays.
281 Higher values are also possible.
282
283 \note On some platforms the devicePixelRatio of a window and the screen it is on can
284 be different. Use this function only when you don't know which window you are targeting.
285 If you do know the target window, use QWindow::devicePixelRatio() instead.
286
287 \sa QWindow::devicePixelRatio(), QGuiApplication::devicePixelRatio()
288*/
289qreal QScreen::devicePixelRatio() const
290{
291 Q_D(const QScreen);
292 return d->platformScreen->devicePixelRatio() * QHighDpiScaling::factor(context: this);
293}
294
295/*!
296 \property QScreen::physicalSize
297 \brief the screen's physical size (in millimeters)
298
299 The physical size represents the actual physical dimensions of the
300 screen's display.
301
302 Depending on what information the underlying system provides the value
303 might not be entirely accurate.
304*/
305QSizeF QScreen::physicalSize() const
306{
307 Q_D(const QScreen);
308 return d->platformScreen->physicalSize();
309}
310
311/*!
312 \property QScreen::availableSize
313 \brief the screen's available size in pixels
314
315 The available size is the size excluding window manager reserved areas
316 such as task bars and system menus.
317*/
318QSize QScreen::availableSize() const
319{
320 Q_D(const QScreen);
321 return d->availableGeometry.size();
322}
323
324/*!
325 \property QScreen::geometry
326 \brief the screen's geometry in pixels
327
328 As an example this might return QRect(0, 0, 1280, 1024), or in a
329 virtual desktop setting QRect(1280, 0, 1280, 1024).
330*/
331QRect QScreen::geometry() const
332{
333 Q_D(const QScreen);
334 return d->geometry;
335}
336
337/*!
338 \property QScreen::availableGeometry
339 \brief the screen's available geometry in pixels
340
341 The available geometry is the geometry excluding window manager reserved areas
342 such as task bars and system menus.
343
344 Note, on X11 this will return the true available geometry only on systems with one monitor and
345 if window manager has set _NET_WORKAREA atom. In all other cases this is equal to geometry().
346 This is a limitation in X11 window manager specification.
347*/
348QRect QScreen::availableGeometry() const
349{
350 Q_D(const QScreen);
351 return d->availableGeometry;
352}
353
354/*!
355 Get the screen's virtual siblings.
356
357 The virtual siblings are the screen instances sharing the same virtual desktop.
358 They share a common coordinate system, and windows can freely be moved or
359 positioned across them without having to be re-created.
360*/
361QList<QScreen *> QScreen::virtualSiblings() const
362{
363 Q_D(const QScreen);
364 const QList<QPlatformScreen *> platformScreens = d->platformScreen->virtualSiblings();
365 QList<QScreen *> screens;
366 screens.reserve(size: platformScreens.size());
367 for (QPlatformScreen *platformScreen : platformScreens) {
368 // Only consider platform screens that have been added
369 if (auto *knownScreen = platformScreen->screen())
370 screens << knownScreen;
371 }
372 return screens;
373}
374
375/*!
376 \property QScreen::virtualSize
377 \brief the pixel size of the virtual desktop to which this screen belongs
378
379 Returns the pixel size of the virtual desktop corresponding to this screen.
380
381 This is the combined size of the virtual siblings' individual geometries.
382
383 \sa virtualSiblings()
384*/
385QSize QScreen::virtualSize() const
386{
387 return virtualGeometry().size();
388}
389
390/*!
391 \property QScreen::virtualGeometry
392 \brief the pixel geometry of the virtual desktop to which this screen belongs
393
394 Returns the pixel geometry of the virtual desktop corresponding to this screen.
395
396 This is the union of the virtual siblings' individual geometries.
397
398 \sa virtualSiblings()
399*/
400QRect QScreen::virtualGeometry() const
401{
402 QRect result;
403 const auto screens = virtualSiblings();
404 for (QScreen *screen : screens)
405 result |= screen->geometry();
406 return result;
407}
408
409/*!
410 \property QScreen::availableVirtualSize
411 \brief the available size of the virtual desktop to which this screen belongs
412
413 Returns the available pixel size of the virtual desktop corresponding to this screen.
414
415 This is the combined size of the virtual siblings' individual available geometries.
416
417 \sa availableSize(), virtualSiblings()
418*/
419QSize QScreen::availableVirtualSize() const
420{
421 return availableVirtualGeometry().size();
422}
423
424/*!
425 \property QScreen::availableVirtualGeometry
426 \brief the available geometry of the virtual desktop to which this screen belongs
427
428 Returns the available geometry of the virtual desktop corresponding to this screen.
429
430 This is the union of the virtual siblings' individual available geometries.
431
432 \sa availableGeometry(), virtualSiblings()
433*/
434QRect QScreen::availableVirtualGeometry() const
435{
436 QRect result;
437 const auto screens = virtualSiblings();
438 for (QScreen *screen : screens)
439 result |= screen->availableGeometry();
440 return result;
441}
442
443/*!
444 \property QScreen::orientation
445 \brief the screen orientation
446
447 The \c orientation property tells the orientation of the screen from the
448 window system perspective.
449
450 Most mobile devices and tablet computers contain accelerometer sensors.
451 The Qt Sensors module provides the ability to read this sensor directly.
452 However, the windowing system may rotate the entire screen automatically
453 based on how it is being held; in that case, this \c orientation property
454 will change.
455
456 \sa primaryOrientation(), QWindow::contentOrientation()
457*/
458Qt::ScreenOrientation QScreen::orientation() const
459{
460 Q_D(const QScreen);
461 return d->orientation;
462}
463
464/*!
465 \property QScreen::refreshRate
466 \brief the approximate vertical refresh rate of the screen in Hz
467
468 \warning Avoid using the screen's refresh rate to drive animations via a
469 timer such as QChronoTimer. Instead use QWindow::requestUpdate().
470
471 \sa QWindow::requestUpdate()
472*/
473qreal QScreen::refreshRate() const
474{
475 Q_D(const QScreen);
476 return d->refreshRate;
477}
478
479/*!
480 \property QScreen::primaryOrientation
481 \brief the primary screen orientation
482
483 The primary screen orientation is Qt::LandscapeOrientation
484 if the screen geometry's width is greater than or equal to its
485 height, or Qt::PortraitOrientation otherwise. This property might
486 change when the screen orientation was changed (i.e. when the
487 display is rotated).
488 The behavior is however platform dependent and can often be specified in
489 an application manifest file.
490
491*/
492Qt::ScreenOrientation QScreen::primaryOrientation() const
493{
494 Q_D(const QScreen);
495 return d->primaryOrientation;
496}
497
498/*!
499 \property QScreen::nativeOrientation
500 \brief the native screen orientation
501 \since 5.2
502
503 The native orientation of the screen is the orientation where the logo
504 sticker of the device appears the right way up, or Qt::PrimaryOrientation
505 if the platform does not support this functionality.
506
507 The native orientation is a property of the hardware, and does not change.
508*/
509Qt::ScreenOrientation QScreen::nativeOrientation() const
510{
511 Q_D(const QScreen);
512 return d->platformScreen->nativeOrientation();
513}
514
515/*!
516 Convenience function to compute the angle of rotation to get from
517 rotation \a a to rotation \a b.
518
519 The result will be 0, 90, 180, or 270.
520
521 Qt::PrimaryOrientation is interpreted as the screen's primaryOrientation().
522*/
523int QScreen::angleBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b) const
524{
525 if (a == Qt::PrimaryOrientation)
526 a = primaryOrientation();
527
528 if (b == Qt::PrimaryOrientation)
529 b = primaryOrientation();
530
531 return QPlatformScreen::angleBetween(a, b);
532}
533
534/*!
535 Convenience function to compute a transform that maps from the coordinate system
536 defined by orientation \a a into the coordinate system defined by orientation
537 \a b and target dimensions \a target.
538
539 Example, \a a is Qt::Landscape, \a b is Qt::Portrait, and \a target is QRect(0, 0, w, h)
540 the resulting transform will be such that the point QPoint(0, 0) is mapped to QPoint(0, w),
541 and QPoint(h, w) is mapped to QPoint(0, h). Thus, the landscape coordinate system QRect(0, 0, h, w)
542 is mapped (with a 90 degree rotation) into the portrait coordinate system QRect(0, 0, w, h).
543
544 Qt::PrimaryOrientation is interpreted as the screen's primaryOrientation().
545*/
546QTransform QScreen::transformBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b, const QRect &target) const
547{
548 if (a == Qt::PrimaryOrientation)
549 a = primaryOrientation();
550
551 if (b == Qt::PrimaryOrientation)
552 b = primaryOrientation();
553
554 return QPlatformScreen::transformBetween(a, b, target);
555}
556
557/*!
558 Maps the rect between two screen orientations.
559
560 This will flip the x and y dimensions of the rectangle \a{rect} if the orientation \a{a} is
561 Qt::PortraitOrientation or Qt::InvertedPortraitOrientation and orientation \a{b} is
562 Qt::LandscapeOrientation or Qt::InvertedLandscapeOrientation, or vice versa.
563
564 Qt::PrimaryOrientation is interpreted as the screen's primaryOrientation().
565*/
566QRect QScreen::mapBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b, const QRect &rect) const
567{
568 if (a == Qt::PrimaryOrientation)
569 a = primaryOrientation();
570
571 if (b == Qt::PrimaryOrientation)
572 b = primaryOrientation();
573
574 return QPlatformScreen::mapBetween(a, b, rect);
575}
576
577/*!
578 Convenience function that returns \c true if \a o is either portrait or inverted portrait;
579 otherwise returns \c false.
580
581 Qt::PrimaryOrientation is interpreted as the screen's primaryOrientation().
582*/
583bool QScreen::isPortrait(Qt::ScreenOrientation o) const
584{
585 return o == Qt::PortraitOrientation || o == Qt::InvertedPortraitOrientation
586 || (o == Qt::PrimaryOrientation && primaryOrientation() == Qt::PortraitOrientation);
587}
588
589/*!
590 Convenience function that returns \c true if \a o is either landscape or inverted landscape;
591 otherwise returns \c false.
592
593 Qt::PrimaryOrientation is interpreted as the screen's primaryOrientation().
594*/
595bool QScreen::isLandscape(Qt::ScreenOrientation o) const
596{
597 return o == Qt::LandscapeOrientation || o == Qt::InvertedLandscapeOrientation
598 || (o == Qt::PrimaryOrientation && primaryOrientation() == Qt::LandscapeOrientation);
599}
600
601/*!
602 \fn void QScreen::orientationChanged(Qt::ScreenOrientation orientation)
603
604 This signal is emitted when the orientation of the screen
605 changes with \a orientation as an argument.
606
607 \sa orientation()
608*/
609
610/*!
611 \fn void QScreen::primaryOrientationChanged(Qt::ScreenOrientation orientation)
612
613 This signal is emitted when the primary orientation of the screen
614 changes with \a orientation as an argument.
615
616 \sa primaryOrientation()
617*/
618
619void QScreenPrivate::updatePrimaryOrientation()
620{
621 primaryOrientation = geometry.width() >= geometry.height() ? Qt::LandscapeOrientation : Qt::PortraitOrientation;
622}
623
624/*!
625 Returns the screen at \a point within the set of \l QScreen::virtualSiblings(),
626 or \c nullptr if outside of any screen.
627
628 The \a point is in relation to the virtualGeometry() of each set of virtual
629 siblings.
630
631 \since 5.15
632*/
633QScreen *QScreen::virtualSiblingAt(QPoint point)
634{
635 const auto &siblings = virtualSiblings();
636 for (QScreen *sibling : siblings) {
637 if (sibling->geometry().contains(p: point))
638 return sibling;
639 }
640 return nullptr;
641}
642
643/*!
644 Creates and returns a pixmap constructed by grabbing the contents
645 of the given \a window restricted by QRect(\a x, \a y, \a width,
646 \a height). If \a window is 0, then the entire screen will be
647 grabbed.
648
649 The arguments (\a{x}, \a{y}) specify the offset in the window,
650 whereas (\a{width}, \a{height}) specify the area to be copied. If
651 \a width is negative, the function copies everything to the right
652 border of the window. If \a height is negative, the function
653 copies everything to the bottom of the window.
654
655 The offset and size arguments are specified in device independent
656 pixels. The returned pixmap may be larger than the requested size
657 when grabbing from a high-DPI screen. Call QPixmap::devicePixelRatio()
658 to determine if this is the case.
659
660 The window system identifier (\c WId) can be retrieved using the
661 QWidget::winId() function. The rationale for using a window
662 identifier and not a QWidget, is to enable grabbing of windows
663 that are not part of the application, window system frames, and so
664 on.
665
666 \warning Grabbing windows that are not part of the application is
667 not supported on systems such as iOS, where sandboxing/security
668 prevents reading pixels of windows not owned by the application.
669
670 The grabWindow() function grabs pixels from the screen, not from
671 the window, i.e. if there is another window partially or entirely
672 over the one you grab, you get pixels from the overlying window,
673 too. The mouse cursor is generally not grabbed.
674
675 Note on X11 that if the given \a window doesn't have the same depth
676 as the root window, and another window partially or entirely
677 obscures the one you grab, you will \e not get pixels from the
678 overlying window. The contents of the obscured areas in the
679 pixmap will be undefined and uninitialized.
680
681 On Windows Vista and above grabbing a layered window, which is
682 created by setting the Qt::WA_TranslucentBackground attribute, will
683 not work. Instead grabbing the desktop widget should work.
684
685 \warning In general, grabbing an area outside the screen is not
686 safe. This depends on the underlying window system.
687*/
688
689QPixmap QScreen::grabWindow(WId window, int x, int y, int width, int height)
690{
691 const QPlatformScreen *platformScreen = handle();
692 if (!platformScreen) {
693 qWarning(msg: "invoked with handle==0");
694 return QPixmap();
695 }
696 const qreal factor = QHighDpiScaling::factor(context: this);
697 if (qFuzzyCompare(p1: factor, p2: 1))
698 return platformScreen->grabWindow(window, x, y, width, height);
699
700 const QPoint nativePos = QHighDpi::toNative(value: QPoint(x, y), scaleFactor: factor);
701 QSize nativeSize(width, height);
702 if (nativeSize.isValid())
703 nativeSize = QHighDpi::toNative(value: nativeSize, scaleFactor: factor);
704 QPixmap result =
705 platformScreen->grabWindow(window, x: nativePos.x(), y: nativePos.y(),
706 width: nativeSize.width(), height: nativeSize.height());
707 result.setDevicePixelRatio(result.devicePixelRatio() * factor);
708 return result;
709}
710
711/*!
712 \fn template <typename QNativeInterface> QNativeInterface *QScreen::nativeInterface() const
713
714 Returns a native interface of the given type for the screen.
715
716 This function provides access to platform specific functionality
717 of QScreen, as defined in the QNativeInterface namespace:
718
719 \annotatedlist native-interfaces-qscreen
720
721 If the requested interface is not available a \nullptr is returned.
722 */
723
724void *QScreen::resolveInterface(const char *name, int revision) const
725{
726 using namespace QNativeInterface;
727 using namespace QNativeInterface::Private;
728
729 auto *platformScreen = handle();
730 Q_UNUSED(platformScreen);
731 Q_UNUSED(name);
732 Q_UNUSED(revision);
733
734#if QT_CONFIG(xcb)
735 QT_NATIVE_INTERFACE_RETURN_IF(QXcbScreen, platformScreen);
736#endif
737
738#if QT_CONFIG(vsp2)
739 QT_NATIVE_INTERFACE_RETURN_IF(QVsp2Screen, platformScreen);
740#endif
741
742#if defined(Q_OS_WEBOS)
743 QT_NATIVE_INTERFACE_RETURN_IF(QWebOSScreen, platformScreen);
744#endif
745
746#if defined(Q_OS_WIN32)
747 QT_NATIVE_INTERFACE_RETURN_IF(QWindowsScreen, platformScreen);
748#endif
749
750#if defined(Q_OS_ANDROID)
751 QT_NATIVE_INTERFACE_RETURN_IF(QAndroidScreen, platformScreen);
752#endif
753
754#if QT_CONFIG(wayland)
755 QT_NATIVE_INTERFACE_RETURN_IF(QWaylandScreen, platformScreen);
756#endif
757
758 return nullptr;
759}
760
761#ifndef QT_NO_DEBUG_STREAM
762Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QScreen *screen)
763{
764 const QDebugStateSaver saver(debug);
765 debug.nospace();
766 debug << "QScreen(" << (const void *)screen;
767 if (screen) {
768 debug << ", name=" << screen->name();
769 if (debug.verbosity() > 2) {
770 if (screen == QGuiApplication::primaryScreen())
771 debug << ", primary";
772 debug << ", geometry=" << screen->geometry();
773 debug << ", available=" << screen->availableGeometry();
774 debug << ", logical DPI=" << screen->logicalDotsPerInchX()
775 << ',' << screen->logicalDotsPerInchY()
776 << ", physical DPI=" << screen->physicalDotsPerInchX()
777 << ',' << screen->physicalDotsPerInchY()
778 << ", devicePixelRatio=" << screen->devicePixelRatio()
779 << ", orientation=" << screen->orientation()
780 << ", physical size=" << screen->physicalSize().width()
781 << 'x' << screen->physicalSize().height() << "mm";
782 }
783 }
784 debug << ')';
785 return debug;
786}
787#endif // !QT_NO_DEBUG_STREAM
788
789QScreenPrivate::UpdateEmitter::UpdateEmitter(QScreen *screen)
790{
791 initialState.platformScreen = screen->handle();
792
793 // Use public APIs to read out current state, rather
794 // than accessing the QScreenPrivate members, so that
795 // we detect any changes to the high-DPI scale factors
796 // that may be applied in the getters.
797
798 initialState.logicalDpi = QDpi{
799 screen->logicalDotsPerInchX(),
800 screen->logicalDotsPerInchY()
801 };
802 initialState.geometry = screen->geometry();
803 initialState.availableGeometry = screen->availableGeometry();
804 initialState.primaryOrientation = screen->primaryOrientation();
805}
806
807QScreenPrivate::UpdateEmitter::~UpdateEmitter()
808{
809 QScreen *screen = initialState.platformScreen->screen();
810
811 const auto logicalDotsPerInch = QDpi{
812 screen->logicalDotsPerInchX(),
813 screen->logicalDotsPerInchY()
814 };
815 if (logicalDotsPerInch != initialState.logicalDpi)
816 emit screen->logicalDotsPerInchChanged(dpi: screen->logicalDotsPerInch());
817
818 const auto geometry = screen->geometry();
819 const auto geometryChanged = geometry != initialState.geometry;
820 if (geometryChanged)
821 emit screen->geometryChanged(geometry);
822
823 const auto availableGeometry = screen->availableGeometry();
824 const auto availableGeometryChanged = availableGeometry != initialState.availableGeometry;
825 if (availableGeometryChanged)
826 emit screen->availableGeometryChanged(geometry: availableGeometry);
827
828 if (geometryChanged || availableGeometryChanged) {
829 const auto siblings = screen->virtualSiblings();
830 for (QScreen* sibling : siblings)
831 emit sibling->virtualGeometryChanged(rect: sibling->virtualGeometry());
832 }
833
834 if (geometryChanged) {
835 emit screen->physicalDotsPerInchChanged(dpi: screen->physicalDotsPerInch());
836
837 const auto primaryOrientation = screen->primaryOrientation();
838 if (primaryOrientation != initialState.primaryOrientation)
839 emit screen->primaryOrientationChanged(orientation: primaryOrientation);
840 }
841}
842
843QT_END_NAMESPACE
844
845#include "moc_qscreen.cpp"
846

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtbase/src/gui/kernel/qscreen.cpp