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