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
51QT_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
73QScreen::QScreen(QPlatformScreen *screen)
74 : QObject(*new QScreenPrivate(), nullptr)
75{
76 Q_D(QScreen);
77 d->setPlatformScreen(screen);
78}
79
80void QScreenPrivate::updateGeometriesWithSignals()
81{
82 const QRect oldGeometry = geometry;
83 const QRect oldAvailableGeometry = availableGeometry;
84 updateHighDpi();
85 emitGeometryChangeSignals(geometryChanged: oldGeometry != geometry, availableGeometryChanged: oldAvailableGeometry != availableGeometry);
86}
87
88void 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(geometry: availableGeometry);
96
97 if (geometryChanged || availableGeometryChanged) {
98 const auto siblings = q->virtualSiblings();
99 for (QScreen* sibling : siblings)
100 emit sibling->virtualGeometryChanged(rect: sibling->virtualGeometry());
101 }
102
103 if (geometryChanged)
104 emit q->physicalDotsPerInchChanged(dpi: q->physicalDotsPerInch());
105}
106
107void 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(in: 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 */
134QScreen::~QScreen()
135{
136 // Remove screen
137 const bool wasPrimary = QGuiApplication::primaryScreen() == this;
138 QGuiApplicationPrivate::screen_list.removeOne(t: this);
139 QGuiApplicationPrivate::resetCachedDevicePixelRatio();
140
141 if (!qGuiApp)
142 return;
143
144 QScreen *newPrimaryScreen = QGuiApplication::primaryScreen();
145 if (wasPrimary && newPrimaryScreen)
146 emit qGuiApp->primaryScreenChanged(screen: 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(screen: this);
151
152 if (QGuiApplication::closingDown())
153 return;
154
155 bool movingFromVirtualSibling = newPrimaryScreen
156 && newPrimaryScreen->handle()->virtualSiblings().contains(t: 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*/
179QPlatformScreen *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*/
192QString 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*/
204QString 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*/
216QString 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*/
228QString 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*/
238int 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*/
248QSize 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*/
264qreal 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*/
279qreal 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*/
298qreal 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*/
313qreal QScreen::logicalDotsPerInchX() const
314{
315 Q_D(const QScreen);
316 if (QHighDpiScaling::isActive())
317 return QHighDpiScaling::logicalDpi(screen: 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*/
329qreal QScreen::logicalDotsPerInchY() const
330{
331 Q_D(const QScreen);
332 if (QHighDpiScaling::isActive())
333 return QHighDpiScaling::logicalDpi(screen: 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*/
349qreal QScreen::logicalDotsPerInch() const
350{
351 Q_D(const QScreen);
352 QDpi dpi = QHighDpiScaling::isActive() ? QHighDpiScaling::logicalDpi(screen: 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*/
368qreal QScreen::devicePixelRatio() const
369{
370 Q_D(const QScreen);
371 return d->platformScreen->devicePixelRatio() * QHighDpiScaling::factor(context: 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*/
384QSizeF 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*/
397QSize 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*/
410QRect 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*/
427QRect 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*/
440QList<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(alloc: 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*/
461QSize 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*/
476QRect 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*/
495QSize 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*/
510QRect 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*/
530void QScreen::setOrientationUpdateMask(Qt::ScreenOrientations mask)
531{
532 Q_D(QScreen);
533 d->orientationUpdateMask = mask;
534 d->platformScreen->setOrientationUpdateMask(mask);
535 QGuiApplicationPrivate::updateFilteredScreenOrientation(screen: this);
536}
537
538/*!
539 Returns the currently set orientation update mask.
540
541 \sa setOrientationUpdateMask()
542*/
543Qt::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*/
567Qt::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*/
577qreal 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*/
596Qt::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*/
613Qt::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*/
627int 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*/
650QTransform 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*/
670QRect 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*/
687bool 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*/
699bool 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
723void 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*/
737QScreen *QScreen::virtualSiblingAt(QPoint point)
738{
739 const auto &siblings = virtualSiblings();
740 for (QScreen *sibling : siblings) {
741 if (sibling->geometry().contains(p: 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
792QPixmap QScreen::grabWindow(WId window, int x, int y, int width, int height)
793{
794 const QPlatformScreen *platformScreen = handle();
795 if (!platformScreen) {
796 qWarning(msg: "invoked with handle==0");
797 return QPixmap();
798 }
799 const qreal factor = QHighDpiScaling::factor(context: this);
800 if (qFuzzyCompare(p1: factor, p2: 1))
801 return platformScreen->grabWindow(window, x, y, width, height);
802
803 const QPoint nativePos = QHighDpi::toNative(value: QPoint(x, y), scaleFactor: factor);
804 QSize nativeSize(width, height);
805 if (nativeSize.isValid())
806 nativeSize = QHighDpi::toNative(value: nativeSize, scaleFactor: factor);
807 QPixmap result =
808 platformScreen->grabWindow(window, x: nativePos.x(), y: nativePos.y(),
809 width: nativeSize.width(), height: nativeSize.height());
810 result.setDevicePixelRatio(result.devicePixelRatio() * factor);
811 return result;
812}
813
814#ifndef QT_NO_DEBUG_STREAM
815
816static 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
822Q_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, r: screen->geometry());
834 debug << ", available=";
835 formatRect(debug, r: 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
851QT_END_NAMESPACE
852

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