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