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