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 \sa QWindow::devicePixelRatio(), QGuiApplication::devicePixelRatio()
284*/
285qreal QScreen::devicePixelRatio() const
286{
287 Q_D(const QScreen);
288 return d->platformScreen->devicePixelRatio() * QHighDpiScaling::factor(context: this);
289}
290
291/*!
292 \property QScreen::physicalSize
293 \brief the screen's physical size (in millimeters)
294
295 The physical size represents the actual physical dimensions of the
296 screen's display.
297
298 Depending on what information the underlying system provides the value
299 might not be entirely accurate.
300*/
301QSizeF QScreen::physicalSize() const
302{
303 Q_D(const QScreen);
304 return d->platformScreen->physicalSize();
305}
306
307/*!
308 \property QScreen::availableSize
309 \brief the screen's available size in pixels
310
311 The available size is the size excluding window manager reserved areas
312 such as task bars and system menus.
313*/
314QSize QScreen::availableSize() const
315{
316 Q_D(const QScreen);
317 return d->availableGeometry.size();
318}
319
320/*!
321 \property QScreen::geometry
322 \brief the screen's geometry in pixels
323
324 As an example this might return QRect(0, 0, 1280, 1024), or in a
325 virtual desktop setting QRect(1280, 0, 1280, 1024).
326*/
327QRect QScreen::geometry() const
328{
329 Q_D(const QScreen);
330 return d->geometry;
331}
332
333/*!
334 \property QScreen::availableGeometry
335 \brief the screen's available geometry in pixels
336
337 The available geometry is the geometry excluding window manager reserved areas
338 such as task bars and system menus.
339
340 Note, on X11 this will return the true available geometry only on systems with one monitor and
341 if window manager has set _NET_WORKAREA atom. In all other cases this is equal to geometry().
342 This is a limitation in X11 window manager specification.
343*/
344QRect QScreen::availableGeometry() const
345{
346 Q_D(const QScreen);
347 return d->availableGeometry;
348}
349
350/*!
351 Get the screen's virtual siblings.
352
353 The virtual siblings are the screen instances sharing the same virtual desktop.
354 They share a common coordinate system, and windows can freely be moved or
355 positioned across them without having to be re-created.
356*/
357QList<QScreen *> QScreen::virtualSiblings() const
358{
359 Q_D(const QScreen);
360 const QList<QPlatformScreen *> platformScreens = d->platformScreen->virtualSiblings();
361 QList<QScreen *> screens;
362 screens.reserve(size: platformScreens.size());
363 for (QPlatformScreen *platformScreen : platformScreens) {
364 // Only consider platform screens that have been added
365 if (auto *knownScreen = platformScreen->screen())
366 screens << knownScreen;
367 }
368 return screens;
369}
370
371/*!
372 \property QScreen::virtualSize
373 \brief the pixel size of the virtual desktop to which this screen belongs
374
375 Returns the pixel size of the virtual desktop corresponding to this screen.
376
377 This is the combined size of the virtual siblings' individual geometries.
378
379 \sa virtualSiblings()
380*/
381QSize QScreen::virtualSize() const
382{
383 return virtualGeometry().size();
384}
385
386/*!
387 \property QScreen::virtualGeometry
388 \brief the pixel geometry of the virtual desktop to which this screen belongs
389
390 Returns the pixel geometry of the virtual desktop corresponding to this screen.
391
392 This is the union of the virtual siblings' individual geometries.
393
394 \sa virtualSiblings()
395*/
396QRect QScreen::virtualGeometry() const
397{
398 QRect result;
399 const auto screens = virtualSiblings();
400 for (QScreen *screen : screens)
401 result |= screen->geometry();
402 return result;
403}
404
405/*!
406 \property QScreen::availableVirtualSize
407 \brief the available size of the virtual desktop to which this screen belongs
408
409 Returns the available pixel size of the virtual desktop corresponding to this screen.
410
411 This is the combined size of the virtual siblings' individual available geometries.
412
413 \sa availableSize(), virtualSiblings()
414*/
415QSize QScreen::availableVirtualSize() const
416{
417 return availableVirtualGeometry().size();
418}
419
420/*!
421 \property QScreen::availableVirtualGeometry
422 \brief the available geometry of the virtual desktop to which this screen belongs
423
424 Returns the available geometry of the virtual desktop corresponding to this screen.
425
426 This is the union of the virtual siblings' individual available geometries.
427
428 \sa availableGeometry(), virtualSiblings()
429*/
430QRect QScreen::availableVirtualGeometry() const
431{
432 QRect result;
433 const auto screens = virtualSiblings();
434 for (QScreen *screen : screens)
435 result |= screen->availableGeometry();
436 return result;
437}
438
439/*!
440 \property QScreen::orientation
441 \brief the screen orientation
442
443 The \c orientation property tells the orientation of the screen from the
444 window system perspective.
445
446 Most mobile devices and tablet computers contain accelerometer sensors.
447 The Qt Sensors module provides the ability to read this sensor directly.
448 However, the windowing system may rotate the entire screen automatically
449 based on how it is being held; in that case, this \c orientation property
450 will change.
451
452 \sa primaryOrientation(), QWindow::contentOrientation()
453*/
454Qt::ScreenOrientation QScreen::orientation() const
455{
456 Q_D(const QScreen);
457 return d->orientation;
458}
459
460/*!
461 \property QScreen::refreshRate
462 \brief the approximate vertical refresh rate of the screen in Hz
463
464 \warning Avoid using the screen's refresh rate to drive animations
465 via a timer such as QTimer. Instead use QWindow::requestUpdate().
466
467 \sa QWindow::requestUpdate()
468*/
469qreal QScreen::refreshRate() const
470{
471 Q_D(const QScreen);
472 return d->refreshRate;
473}
474
475/*!
476 \property QScreen::primaryOrientation
477 \brief the primary screen orientation
478
479 The primary screen orientation is Qt::LandscapeOrientation
480 if the screen geometry's width is greater than or equal to its
481 height, or Qt::PortraitOrientation otherwise. This property might
482 change when the screen orientation was changed (i.e. when the
483 display is rotated).
484 The behavior is however platform dependent and can often be specified in
485 an application manifest file.
486
487*/
488Qt::ScreenOrientation QScreen::primaryOrientation() const
489{
490 Q_D(const QScreen);
491 return d->primaryOrientation;
492}
493
494/*!
495 \property QScreen::nativeOrientation
496 \brief the native screen orientation
497 \since 5.2
498
499 The native orientation of the screen is the orientation where the logo
500 sticker of the device appears the right way up, or Qt::PrimaryOrientation
501 if the platform does not support this functionality.
502
503 The native orientation is a property of the hardware, and does not change.
504*/
505Qt::ScreenOrientation QScreen::nativeOrientation() const
506{
507 Q_D(const QScreen);
508 return d->platformScreen->nativeOrientation();
509}
510
511/*!
512 Convenience function to compute the angle of rotation to get from
513 rotation \a a to rotation \a b.
514
515 The result will be 0, 90, 180, or 270.
516
517 Qt::PrimaryOrientation is interpreted as the screen's primaryOrientation().
518*/
519int QScreen::angleBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b) const
520{
521 if (a == Qt::PrimaryOrientation)
522 a = primaryOrientation();
523
524 if (b == Qt::PrimaryOrientation)
525 b = primaryOrientation();
526
527 return QPlatformScreen::angleBetween(a, b);
528}
529
530/*!
531 Convenience function to compute a transform that maps from the coordinate system
532 defined by orientation \a a into the coordinate system defined by orientation
533 \a b and target dimensions \a target.
534
535 Example, \a a is Qt::Landscape, \a b is Qt::Portrait, and \a target is QRect(0, 0, w, h)
536 the resulting transform will be such that the point QPoint(0, 0) is mapped to QPoint(0, w),
537 and QPoint(h, w) is mapped to QPoint(0, h). Thus, the landscape coordinate system QRect(0, 0, h, w)
538 is mapped (with a 90 degree rotation) into the portrait coordinate system QRect(0, 0, w, h).
539
540 Qt::PrimaryOrientation is interpreted as the screen's primaryOrientation().
541*/
542QTransform QScreen::transformBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b, const QRect &target) const
543{
544 if (a == Qt::PrimaryOrientation)
545 a = primaryOrientation();
546
547 if (b == Qt::PrimaryOrientation)
548 b = primaryOrientation();
549
550 return QPlatformScreen::transformBetween(a, b, target);
551}
552
553/*!
554 Maps the rect between two screen orientations.
555
556 This will flip the x and y dimensions of the rectangle \a{rect} if the orientation \a{a} is
557 Qt::PortraitOrientation or Qt::InvertedPortraitOrientation and orientation \a{b} is
558 Qt::LandscapeOrientation or Qt::InvertedLandscapeOrientation, or vice versa.
559
560 Qt::PrimaryOrientation is interpreted as the screen's primaryOrientation().
561*/
562QRect QScreen::mapBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b, const QRect &rect) const
563{
564 if (a == Qt::PrimaryOrientation)
565 a = primaryOrientation();
566
567 if (b == Qt::PrimaryOrientation)
568 b = primaryOrientation();
569
570 return QPlatformScreen::mapBetween(a, b, rect);
571}
572
573/*!
574 Convenience function that returns \c true if \a o is either portrait or inverted portrait;
575 otherwise returns \c false.
576
577 Qt::PrimaryOrientation is interpreted as the screen's primaryOrientation().
578*/
579bool QScreen::isPortrait(Qt::ScreenOrientation o) const
580{
581 return o == Qt::PortraitOrientation || o == Qt::InvertedPortraitOrientation
582 || (o == Qt::PrimaryOrientation && primaryOrientation() == Qt::PortraitOrientation);
583}
584
585/*!
586 Convenience function that returns \c true if \a o is either landscape or inverted landscape;
587 otherwise returns \c false.
588
589 Qt::PrimaryOrientation is interpreted as the screen's primaryOrientation().
590*/
591bool QScreen::isLandscape(Qt::ScreenOrientation o) const
592{
593 return o == Qt::LandscapeOrientation || o == Qt::InvertedLandscapeOrientation
594 || (o == Qt::PrimaryOrientation && primaryOrientation() == Qt::LandscapeOrientation);
595}
596
597/*!
598 \fn void QScreen::orientationChanged(Qt::ScreenOrientation orientation)
599
600 This signal is emitted when the orientation of the screen
601 changes with \a orientation as an argument.
602
603 \sa orientation()
604*/
605
606/*!
607 \fn void QScreen::primaryOrientationChanged(Qt::ScreenOrientation orientation)
608
609 This signal is emitted when the primary orientation of the screen
610 changes with \a orientation as an argument.
611
612 \sa primaryOrientation()
613*/
614
615void QScreenPrivate::updatePrimaryOrientation()
616{
617 primaryOrientation = geometry.width() >= geometry.height() ? Qt::LandscapeOrientation : Qt::PortraitOrientation;
618}
619
620/*!
621 Returns the screen at \a point within the set of \l QScreen::virtualSiblings(),
622 or \c nullptr if outside of any screen.
623
624 The \a point is in relation to the virtualGeometry() of each set of virtual
625 siblings.
626
627 \since 5.15
628*/
629QScreen *QScreen::virtualSiblingAt(QPoint point)
630{
631 const auto &siblings = virtualSiblings();
632 for (QScreen *sibling : siblings) {
633 if (sibling->geometry().contains(p: point))
634 return sibling;
635 }
636 return nullptr;
637}
638
639/*!
640 Creates and returns a pixmap constructed by grabbing the contents
641 of the given \a window restricted by QRect(\a x, \a y, \a width,
642 \a height). If \a window is 0, then the entire screen will be
643 grabbed.
644
645 The arguments (\a{x}, \a{y}) specify the offset in the window,
646 whereas (\a{width}, \a{height}) specify the area to be copied. If
647 \a width is negative, the function copies everything to the right
648 border of the window. If \a height is negative, the function
649 copies everything to the bottom of the window.
650
651 The offset and size arguments are specified in device independent
652 pixels. The returned pixmap may be larger than the requested size
653 when grabbing from a high-DPI screen. Call QPixmap::devicePixelRatio()
654 to determine if this is the case.
655
656 The window system identifier (\c WId) can be retrieved using the
657 QWidget::winId() function. The rationale for using a window
658 identifier and not a QWidget, is to enable grabbing of windows
659 that are not part of the application, window system frames, and so
660 on.
661
662 \warning Grabbing windows that are not part of the application is
663 not supported on systems such as iOS, where sandboxing/security
664 prevents reading pixels of windows not owned by the application.
665
666 The grabWindow() function grabs pixels from the screen, not from
667 the window, i.e. if there is another window partially or entirely
668 over the one you grab, you get pixels from the overlying window,
669 too. The mouse cursor is generally not grabbed.
670
671 Note on X11 that if the given \a window doesn't have the same depth
672 as the root window, and another window partially or entirely
673 obscures the one you grab, you will \e not get pixels from the
674 overlying window. The contents of the obscured areas in the
675 pixmap will be undefined and uninitialized.
676
677 On Windows Vista and above grabbing a layered window, which is
678 created by setting the Qt::WA_TranslucentBackground attribute, will
679 not work. Instead grabbing the desktop widget should work.
680
681 \warning In general, grabbing an area outside the screen is not
682 safe. This depends on the underlying window system.
683*/
684
685QPixmap QScreen::grabWindow(WId window, int x, int y, int width, int height)
686{
687 const QPlatformScreen *platformScreen = handle();
688 if (!platformScreen) {
689 qWarning(msg: "invoked with handle==0");
690 return QPixmap();
691 }
692 const qreal factor = QHighDpiScaling::factor(context: this);
693 if (qFuzzyCompare(p1: factor, p2: 1))
694 return platformScreen->grabWindow(window, x, y, width, height);
695
696 const QPoint nativePos = QHighDpi::toNative(value: QPoint(x, y), scaleFactor: factor);
697 QSize nativeSize(width, height);
698 if (nativeSize.isValid())
699 nativeSize = QHighDpi::toNative(value: nativeSize, scaleFactor: factor);
700 QPixmap result =
701 platformScreen->grabWindow(window, x: nativePos.x(), y: nativePos.y(),
702 width: nativeSize.width(), height: nativeSize.height());
703 result.setDevicePixelRatio(result.devicePixelRatio() * factor);
704 return result;
705}
706void *QScreen::resolveInterface(const char *name, int revision) const
707{
708 using namespace QNativeInterface::Private;
709
710 auto *platformScreen = handle();
711 Q_UNUSED(platformScreen);
712 Q_UNUSED(name);
713 Q_UNUSED(revision);
714
715#if QT_CONFIG(xcb)
716 QT_NATIVE_INTERFACE_RETURN_IF(QXcbScreen, platformScreen);
717#endif
718
719#if QT_CONFIG(vsp2)
720 QT_NATIVE_INTERFACE_RETURN_IF(QVsp2Screen, platformScreen);
721#endif
722
723#if defined(Q_OS_WEBOS)
724 QT_NATIVE_INTERFACE_RETURN_IF(QWebOSScreen, platformScreen);
725#endif
726
727#if defined(Q_OS_WIN32)
728 QT_NATIVE_INTERFACE_RETURN_IF(QWindowsScreen, platformScreen);
729#endif
730
731#if defined(Q_OS_ANDROID)
732 QT_NATIVE_INTERFACE_RETURN_IF(QAndroidScreen, platformScreen);
733#endif
734
735#if defined(Q_OS_UNIX)
736 QT_NATIVE_INTERFACE_RETURN_IF(QWaylandScreen, platformScreen);
737#endif
738
739 return nullptr;
740}
741
742#ifndef QT_NO_DEBUG_STREAM
743Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QScreen *screen)
744{
745 const QDebugStateSaver saver(debug);
746 debug.nospace();
747 debug << "QScreen(" << (const void *)screen;
748 if (screen) {
749 debug << ", name=" << screen->name();
750 if (debug.verbosity() > 2) {
751 if (screen == QGuiApplication::primaryScreen())
752 debug << ", primary";
753 debug << ", geometry=" << screen->geometry();
754 debug << ", available=" << screen->availableGeometry();
755 debug << ", logical DPI=" << screen->logicalDotsPerInchX()
756 << ',' << screen->logicalDotsPerInchY()
757 << ", physical DPI=" << screen->physicalDotsPerInchX()
758 << ',' << screen->physicalDotsPerInchY()
759 << ", devicePixelRatio=" << screen->devicePixelRatio()
760 << ", orientation=" << screen->orientation()
761 << ", physical size=" << screen->physicalSize().width()
762 << 'x' << screen->physicalSize().height() << "mm";
763 }
764 }
765 debug << ')';
766 return debug;
767}
768#endif // !QT_NO_DEBUG_STREAM
769
770QScreenPrivate::UpdateEmitter::UpdateEmitter(QScreen *screen)
771{
772 initialState.platformScreen = screen->handle();
773
774 // Use public APIs to read out current state, rather
775 // than accessing the QScreenPrivate members, so that
776 // we detect any changes to the high-DPI scale factors
777 // that may be applied in the getters.
778
779 initialState.logicalDpi = QDpi{
780 screen->logicalDotsPerInchX(),
781 screen->logicalDotsPerInchY()
782 };
783 initialState.geometry = screen->geometry();
784 initialState.availableGeometry = screen->availableGeometry();
785 initialState.primaryOrientation = screen->primaryOrientation();
786}
787
788QScreenPrivate::UpdateEmitter::~UpdateEmitter()
789{
790 QScreen *screen = initialState.platformScreen->screen();
791
792 const auto logicalDotsPerInch = QDpi{
793 screen->logicalDotsPerInchX(),
794 screen->logicalDotsPerInchY()
795 };
796 if (logicalDotsPerInch != initialState.logicalDpi)
797 emit screen->logicalDotsPerInchChanged(dpi: screen->logicalDotsPerInch());
798
799 const auto geometry = screen->geometry();
800 const auto geometryChanged = geometry != initialState.geometry;
801 if (geometryChanged)
802 emit screen->geometryChanged(geometry);
803
804 const auto availableGeometry = screen->availableGeometry();
805 const auto availableGeometryChanged = availableGeometry != initialState.availableGeometry;
806 if (availableGeometryChanged)
807 emit screen->availableGeometryChanged(geometry: availableGeometry);
808
809 if (geometryChanged || availableGeometryChanged) {
810 const auto siblings = screen->virtualSiblings();
811 for (QScreen* sibling : siblings)
812 emit sibling->virtualGeometryChanged(rect: sibling->virtualGeometry());
813 }
814
815 if (geometryChanged) {
816 emit screen->physicalDotsPerInchChanged(dpi: screen->physicalDotsPerInch());
817
818 const auto primaryOrientation = screen->primaryOrientation();
819 if (primaryOrientation != initialState.primaryOrientation)
820 emit screen->primaryOrientationChanged(orientation: primaryOrientation);
821 }
822}
823
824QT_END_NAMESPACE
825
826#include "moc_qscreen.cpp"
827

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