/src/qtbase/src/gui/kernel/qscreen.cpp
Line | Count | Source |
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 | | // Qt-Security score:significant reason:default |
4 | | |
5 | | #include "qscreen.h" |
6 | | #include "qscreen_p.h" |
7 | | #include "qpixmap.h" |
8 | | #include "qguiapplication_p.h" |
9 | | #include <qpa/qplatformscreen.h> |
10 | | #include <qpa/qplatformscreen_p.h> |
11 | | |
12 | | #include <QtCore/QDebug> |
13 | | #include <QtCore/private/qobject_p.h> |
14 | | #include "qhighdpiscaling_p.h" |
15 | | |
16 | | QT_BEGIN_NAMESPACE |
17 | | |
18 | | /*! |
19 | | \class QScreen |
20 | | \since 5.0 |
21 | | \brief The QScreen class is used to query screen properties. |
22 | | \inmodule QtGui |
23 | | |
24 | | A note on logical vs physical dots per inch: physical DPI is based on the |
25 | | actual physical pixel sizes when available, and is useful for print preview |
26 | | and other cases where it's desirable to know the exact physical dimensions |
27 | | of screen displayed contents. |
28 | | |
29 | | Logical dots per inch are used to convert font and user interface elements |
30 | | from point sizes to pixel sizes, and might be different from the physical |
31 | | dots per inch. The logical dots per inch are sometimes user-settable in the |
32 | | desktop environment's settings panel, to let the user globally control UI |
33 | | and font sizes in different applications. |
34 | | |
35 | | \note Both physical and logical DPI are expressed in device-independent dots. |
36 | | Multiply by QScreen::devicePixelRatio() to get device-dependent density. |
37 | | |
38 | | To obtain a QScreen object, use QGuiApplication::primaryScreen() for the |
39 | | primary screen, or QGuiApplication::screens() to get a list of all screens. |
40 | | |
41 | | \sa QGuiApplication::primaryScreen() |
42 | | \sa QGuiApplication::screens() |
43 | | |
44 | | \inmodule QtGui |
45 | | */ |
46 | | |
47 | | QScreen::QScreen(QPlatformScreen *platformScreen) |
48 | 0 | : QObject(*new QScreenPrivate(), nullptr) |
49 | 0 | { |
50 | 0 | Q_D(QScreen); |
51 | |
|
52 | 0 | d->platformScreen = platformScreen; |
53 | 0 | platformScreen->d_func()->screen = this; |
54 | |
|
55 | 0 | d->orientation = platformScreen->orientation(); |
56 | 0 | d->logicalDpi = QPlatformScreen::overrideDpi(platformScreen->logicalDpi()); |
57 | 0 | d->refreshRate = platformScreen->refreshRate(); |
58 | | // safeguard ourselves against buggy platform behavior... |
59 | 0 | if (d->refreshRate < 1.0) |
60 | 0 | d->refreshRate = 60.0; |
61 | |
|
62 | 0 | d->updateGeometry(); |
63 | 0 | d->updatePrimaryOrientation(); // derived from the geometry |
64 | 0 | } |
65 | | |
66 | | void QScreenPrivate::updateGeometry() |
67 | 0 | { |
68 | 0 | geometry = QHighDpi::fromNativeGlobalPosition(platformScreen->geometry(), platformScreen); |
69 | 0 | availableGeometry = QHighDpi::fromNativeGlobalPosition(platformScreen->availableGeometry(), platformScreen); |
70 | 0 | } |
71 | | |
72 | | /*! |
73 | | Destroys the screen. |
74 | | |
75 | | \internal |
76 | | */ |
77 | | QScreen::~QScreen() |
78 | 0 | { |
79 | 0 | Q_ASSERT_X(!QGuiApplicationPrivate::screen_list.contains(this), "QScreen", |
80 | 0 | "QScreens should be removed via QWindowSystemInterface::handleScreenRemoved()"); |
81 | 0 | } |
82 | | |
83 | | /*! |
84 | | Get the platform screen handle. |
85 | | |
86 | | \sa {Qt Platform Abstraction}{Qt Platform Abstraction (QPA)} |
87 | | */ |
88 | | QPlatformScreen *QScreen::handle() const |
89 | 0 | { |
90 | 0 | Q_D(const QScreen); |
91 | 0 | return d->platformScreen; |
92 | 0 | } |
93 | | |
94 | | /*! |
95 | | \property QScreen::name |
96 | | \brief a user presentable string representing the screen |
97 | | |
98 | | For example, on X11 these correspond to the XRandr screen names, |
99 | | typically "VGA1", "HDMI1", etc. |
100 | | |
101 | | \note The user presentable string is not guaranteed to match the |
102 | | result of any native APIs, and should not be used to uniquely identify |
103 | | a screen. |
104 | | */ |
105 | | QString QScreen::name() const |
106 | 0 | { |
107 | 0 | Q_D(const QScreen); |
108 | 0 | return d->platformScreen->name(); |
109 | 0 | } |
110 | | |
111 | | /*! |
112 | | \property QScreen::manufacturer |
113 | | \brief the manufacturer of the screen |
114 | | |
115 | | \since 5.9 |
116 | | */ |
117 | | QString QScreen::manufacturer() const |
118 | 0 | { |
119 | 0 | Q_D(const QScreen); |
120 | 0 | return d->platformScreen->manufacturer(); |
121 | 0 | } |
122 | | |
123 | | /*! |
124 | | \property QScreen::model |
125 | | \brief the model of the screen |
126 | | |
127 | | \since 5.9 |
128 | | */ |
129 | | QString QScreen::model() const |
130 | 0 | { |
131 | 0 | Q_D(const QScreen); |
132 | 0 | return d->platformScreen->model(); |
133 | 0 | } |
134 | | |
135 | | /*! |
136 | | \property QScreen::serialNumber |
137 | | \brief the serial number of the screen |
138 | | |
139 | | \since 5.9 |
140 | | */ |
141 | | QString QScreen::serialNumber() const |
142 | 0 | { |
143 | 0 | Q_D(const QScreen); |
144 | 0 | return d->platformScreen->serialNumber(); |
145 | 0 | } |
146 | | |
147 | | /*! |
148 | | \property QScreen::depth |
149 | | \brief the color depth of the screen |
150 | | */ |
151 | | int QScreen::depth() const |
152 | 0 | { |
153 | 0 | Q_D(const QScreen); |
154 | 0 | return d->platformScreen->depth(); |
155 | 0 | } |
156 | | |
157 | | /*! |
158 | | \property QScreen::size |
159 | | \brief the pixel resolution of the screen |
160 | | */ |
161 | | QSize QScreen::size() const |
162 | 0 | { |
163 | 0 | Q_D(const QScreen); |
164 | 0 | return d->geometry.size(); |
165 | 0 | } |
166 | | |
167 | | /*! |
168 | | \property QScreen::physicalDotsPerInchX |
169 | | \brief the number of physical dots or pixels per inch in the horizontal direction |
170 | | |
171 | | This value represents the actual horizontal pixel density on the screen's display. |
172 | | Depending on what information the underlying system provides the value might not be |
173 | | entirely accurate. |
174 | | |
175 | | \note Physical DPI is expressed in device-independent dots. Multiply by QScreen::devicePixelRatio() |
176 | | to get device-dependent density. |
177 | | |
178 | | \sa physicalDotsPerInchY() |
179 | | */ |
180 | | qreal QScreen::physicalDotsPerInchX() const |
181 | 0 | { |
182 | 0 | return size().width() / physicalSize().width() * qreal(25.4); |
183 | 0 | } |
184 | | |
185 | | /*! |
186 | | \property QScreen::physicalDotsPerInchY |
187 | | \brief the number of physical dots or pixels per inch in the vertical direction |
188 | | |
189 | | This value represents the actual vertical pixel density on the screen's display. |
190 | | Depending on what information the underlying system provides the value might not be |
191 | | entirely accurate. |
192 | | |
193 | | \note Physical DPI is expressed in device-independent dots. Multiply by QScreen::devicePixelRatio() |
194 | | to get device-dependent density. |
195 | | |
196 | | \sa physicalDotsPerInchX() |
197 | | */ |
198 | | qreal QScreen::physicalDotsPerInchY() const |
199 | 0 | { |
200 | 0 | return size().height() / physicalSize().height() * qreal(25.4); |
201 | 0 | } |
202 | | |
203 | | /*! |
204 | | \property QScreen::physicalDotsPerInch |
205 | | \brief the number of physical dots or pixels per inch |
206 | | |
207 | | This value represents the pixel density on the screen's display. |
208 | | Depending on what information the underlying system provides the value might not be |
209 | | entirely accurate. |
210 | | |
211 | | This is a convenience property that's simply the average of the physicalDotsPerInchX |
212 | | and physicalDotsPerInchY properties. |
213 | | |
214 | | \note Physical DPI is expressed in device-independent dots. Multiply by QScreen::devicePixelRatio() |
215 | | to get device-dependent density. |
216 | | |
217 | | \sa physicalDotsPerInchX() |
218 | | \sa physicalDotsPerInchY() |
219 | | */ |
220 | | qreal QScreen::physicalDotsPerInch() const |
221 | 0 | { |
222 | 0 | QSize sz = size(); |
223 | 0 | QSizeF psz = physicalSize(); |
224 | 0 | return ((sz.height() / psz.height()) + (sz.width() / psz.width())) * qreal(25.4 * 0.5); |
225 | 0 | } |
226 | | |
227 | | /*! |
228 | | \property QScreen::logicalDotsPerInchX |
229 | | \brief the number of logical dots or pixels per inch in the horizontal direction |
230 | | |
231 | | This value is used to convert font point sizes to pixel sizes. |
232 | | |
233 | | \sa logicalDotsPerInchY() |
234 | | */ |
235 | | qreal QScreen::logicalDotsPerInchX() const |
236 | 0 | { |
237 | 0 | Q_D(const QScreen); |
238 | 0 | if (QHighDpiScaling::isActive()) |
239 | 0 | return QHighDpiScaling::logicalDpi(this).first; |
240 | 0 | return d->logicalDpi.first; |
241 | 0 | } |
242 | | |
243 | | /*! |
244 | | \property QScreen::logicalDotsPerInchY |
245 | | \brief the number of logical dots or pixels per inch in the vertical direction |
246 | | |
247 | | This value is used to convert font point sizes to pixel sizes. |
248 | | |
249 | | \sa logicalDotsPerInchX() |
250 | | */ |
251 | | qreal QScreen::logicalDotsPerInchY() const |
252 | 0 | { |
253 | 0 | Q_D(const QScreen); |
254 | 0 | if (QHighDpiScaling::isActive()) |
255 | 0 | return QHighDpiScaling::logicalDpi(this).second; |
256 | 0 | return d->logicalDpi.second; |
257 | 0 | } |
258 | | |
259 | | /*! |
260 | | \property QScreen::logicalDotsPerInch |
261 | | \brief the number of logical dots or pixels per inch |
262 | | |
263 | | This value can be used to convert font point sizes to pixel sizes. |
264 | | |
265 | | This is a convenience property that's simply the average of the logicalDotsPerInchX |
266 | | and logicalDotsPerInchY properties. |
267 | | |
268 | | \sa logicalDotsPerInchX() |
269 | | \sa logicalDotsPerInchY() |
270 | | */ |
271 | | qreal QScreen::logicalDotsPerInch() const |
272 | 0 | { |
273 | 0 | Q_D(const QScreen); |
274 | 0 | QDpi dpi = QHighDpiScaling::isActive() ? QHighDpiScaling::logicalDpi(this) : d->logicalDpi; |
275 | 0 | return (dpi.first + dpi.second) * qreal(0.5); |
276 | 0 | } |
277 | | |
278 | | /*! |
279 | | \property QScreen::devicePixelRatio |
280 | | \brief the screen's ratio between physical pixels and device-independent pixels |
281 | | \since 5.5 |
282 | | |
283 | | Returns the ratio between physical pixels and device-independent pixels for the screen. |
284 | | |
285 | | This function may return a value that differs from QWindow::devicePixelRatio(), |
286 | | for instance on Wayland when using fractional scaling, or if window properties |
287 | | that affect surface resolution are set. Prefer using QWindow::devicePixelRatio(). |
288 | | |
289 | | \note On some platforms the devicePixelRatio of a window and the screen it is on can |
290 | | be different. Use this function only when you don't know which window you are targeting. |
291 | | If you do know the target window, use QWindow::devicePixelRatio() instead. |
292 | | |
293 | | \sa QWindow::devicePixelRatio(), QGuiApplication::devicePixelRatio() |
294 | | */ |
295 | | qreal QScreen::devicePixelRatio() const |
296 | 0 | { |
297 | 0 | Q_D(const QScreen); |
298 | 0 | return d->platformScreen->devicePixelRatio() * QHighDpiScaling::factor(this); |
299 | 0 | } |
300 | | |
301 | | /*! |
302 | | \property QScreen::physicalSize |
303 | | \brief the screen's physical size (in millimeters) |
304 | | |
305 | | The physical size represents the actual physical dimensions of the |
306 | | screen's display. |
307 | | |
308 | | Depending on what information the underlying system provides the value |
309 | | might not be entirely accurate. |
310 | | */ |
311 | | QSizeF QScreen::physicalSize() const |
312 | 0 | { |
313 | 0 | Q_D(const QScreen); |
314 | 0 | return d->platformScreen->physicalSize(); |
315 | 0 | } |
316 | | |
317 | | /*! |
318 | | \property QScreen::availableSize |
319 | | \brief the screen's available size in pixels |
320 | | |
321 | | The available size is the size excluding window manager reserved areas |
322 | | such as task bars and system menus. |
323 | | */ |
324 | | QSize QScreen::availableSize() const |
325 | 0 | { |
326 | 0 | Q_D(const QScreen); |
327 | 0 | return d->availableGeometry.size(); |
328 | 0 | } |
329 | | |
330 | | /*! |
331 | | \property QScreen::geometry |
332 | | \brief the screen's geometry in pixels |
333 | | |
334 | | As an example this might return QRect(0, 0, 1280, 1024), or in a |
335 | | virtual desktop setting QRect(1280, 0, 1280, 1024). |
336 | | */ |
337 | | QRect QScreen::geometry() const |
338 | 0 | { |
339 | 0 | Q_D(const QScreen); |
340 | 0 | return d->geometry; |
341 | 0 | } |
342 | | |
343 | | /*! |
344 | | \property QScreen::availableGeometry |
345 | | \brief the screen's available geometry in pixels |
346 | | |
347 | | The available geometry is the geometry excluding window manager reserved areas |
348 | | such as task bars and system menus. |
349 | | |
350 | | Note, on X11 this will return the true available geometry only on systems with one monitor and |
351 | | if window manager has set _NET_WORKAREA atom. In all other cases this is equal to geometry(). |
352 | | This is a limitation in X11 window manager specification. |
353 | | */ |
354 | | QRect QScreen::availableGeometry() const |
355 | 0 | { |
356 | 0 | Q_D(const QScreen); |
357 | 0 | return d->availableGeometry; |
358 | 0 | } |
359 | | |
360 | | /*! |
361 | | Get the screen's virtual siblings. |
362 | | |
363 | | The virtual siblings are the screen instances sharing the same virtual desktop. |
364 | | They share a common coordinate system, and windows can freely be moved or |
365 | | positioned across them without having to be re-created. |
366 | | */ |
367 | | QList<QScreen *> QScreen::virtualSiblings() const |
368 | 0 | { |
369 | 0 | Q_D(const QScreen); |
370 | 0 | const QList<QPlatformScreen *> platformScreens = d->platformScreen->virtualSiblings(); |
371 | 0 | QList<QScreen *> screens; |
372 | 0 | screens.reserve(platformScreens.size()); |
373 | 0 | for (QPlatformScreen *platformScreen : platformScreens) { |
374 | | // Only consider platform screens that have been added |
375 | 0 | if (auto *knownScreen = platformScreen->screen()) |
376 | 0 | screens << knownScreen; |
377 | 0 | } |
378 | 0 | return screens; |
379 | 0 | } |
380 | | |
381 | | /*! |
382 | | \property QScreen::virtualSize |
383 | | \brief the pixel size of the virtual desktop to which this screen belongs |
384 | | |
385 | | Returns the pixel size of the virtual desktop corresponding to this screen. |
386 | | |
387 | | This is the combined size of the virtual siblings' individual geometries. |
388 | | |
389 | | \sa virtualSiblings() |
390 | | */ |
391 | | QSize QScreen::virtualSize() const |
392 | 0 | { |
393 | 0 | return virtualGeometry().size(); |
394 | 0 | } |
395 | | |
396 | | /*! |
397 | | \property QScreen::virtualGeometry |
398 | | \brief the pixel geometry of the virtual desktop to which this screen belongs |
399 | | |
400 | | Returns the pixel geometry of the virtual desktop corresponding to this screen. |
401 | | |
402 | | This is the union of the virtual siblings' individual geometries. |
403 | | |
404 | | \sa virtualSiblings() |
405 | | */ |
406 | | QRect QScreen::virtualGeometry() const |
407 | 0 | { |
408 | 0 | QRect result; |
409 | 0 | const auto screens = virtualSiblings(); |
410 | 0 | for (QScreen *screen : screens) |
411 | 0 | result |= screen->geometry(); |
412 | 0 | return result; |
413 | 0 | } |
414 | | |
415 | | /*! |
416 | | \property QScreen::availableVirtualSize |
417 | | \brief the available size of the virtual desktop to which this screen belongs |
418 | | |
419 | | Returns the available pixel size of the virtual desktop corresponding to this screen. |
420 | | |
421 | | This is the combined size of the virtual siblings' individual available geometries. |
422 | | |
423 | | \sa availableSize(), virtualSiblings() |
424 | | */ |
425 | | QSize QScreen::availableVirtualSize() const |
426 | 0 | { |
427 | 0 | return availableVirtualGeometry().size(); |
428 | 0 | } |
429 | | |
430 | | /*! |
431 | | \property QScreen::availableVirtualGeometry |
432 | | \brief the available geometry of the virtual desktop to which this screen belongs |
433 | | |
434 | | Returns the available geometry of the virtual desktop corresponding to this screen. |
435 | | |
436 | | This is the union of the virtual siblings' individual available geometries. |
437 | | |
438 | | \sa availableGeometry(), virtualSiblings() |
439 | | */ |
440 | | QRect QScreen::availableVirtualGeometry() const |
441 | 0 | { |
442 | 0 | QRect result; |
443 | 0 | const auto screens = virtualSiblings(); |
444 | 0 | for (QScreen *screen : screens) |
445 | 0 | result |= screen->availableGeometry(); |
446 | 0 | return result; |
447 | 0 | } |
448 | | |
449 | | /*! |
450 | | \property QScreen::orientation |
451 | | \brief the screen orientation |
452 | | |
453 | | The \c orientation property tells the orientation of the screen from the |
454 | | window system perspective. |
455 | | |
456 | | Most mobile devices and tablet computers contain accelerometer sensors. |
457 | | The Qt Sensors module provides the ability to read this sensor directly. |
458 | | However, the windowing system may rotate the entire screen automatically |
459 | | based on how it is being held; in that case, this \c orientation property |
460 | | will change. |
461 | | |
462 | | \sa primaryOrientation(), QWindow::contentOrientation() |
463 | | */ |
464 | | Qt::ScreenOrientation QScreen::orientation() const |
465 | 0 | { |
466 | 0 | Q_D(const QScreen); |
467 | 0 | return d->orientation; |
468 | 0 | } |
469 | | |
470 | | /*! |
471 | | \property QScreen::refreshRate |
472 | | \brief the approximate vertical refresh rate of the screen in Hz |
473 | | |
474 | | \warning Avoid using the screen's refresh rate to drive animations via a |
475 | | timer such as QChronoTimer. Instead use QWindow::requestUpdate(). |
476 | | |
477 | | \sa QWindow::requestUpdate() |
478 | | */ |
479 | | qreal QScreen::refreshRate() const |
480 | 0 | { |
481 | 0 | Q_D(const QScreen); |
482 | 0 | return d->refreshRate; |
483 | 0 | } |
484 | | |
485 | | /*! |
486 | | \property QScreen::primaryOrientation |
487 | | \brief the primary screen orientation |
488 | | |
489 | | The primary screen orientation is Qt::LandscapeOrientation |
490 | | if the screen geometry's width is greater than or equal to its |
491 | | height, or Qt::PortraitOrientation otherwise. This property might |
492 | | change when the screen orientation was changed (i.e. when the |
493 | | display is rotated). |
494 | | The behavior is however platform dependent and can often be specified in |
495 | | an application manifest file. |
496 | | |
497 | | */ |
498 | | Qt::ScreenOrientation QScreen::primaryOrientation() const |
499 | 0 | { |
500 | 0 | Q_D(const QScreen); |
501 | 0 | return d->primaryOrientation; |
502 | 0 | } |
503 | | |
504 | | /*! |
505 | | \property QScreen::nativeOrientation |
506 | | \brief the native screen orientation |
507 | | \since 5.2 |
508 | | |
509 | | The native orientation of the screen is the orientation where the logo |
510 | | sticker of the device appears the right way up, or Qt::PrimaryOrientation |
511 | | if the platform does not support this functionality. |
512 | | |
513 | | The native orientation is a property of the hardware, and does not change. |
514 | | */ |
515 | | Qt::ScreenOrientation QScreen::nativeOrientation() const |
516 | 0 | { |
517 | 0 | Q_D(const QScreen); |
518 | 0 | return d->platformScreen->nativeOrientation(); |
519 | 0 | } |
520 | | |
521 | | /*! |
522 | | Convenience function to compute the angle of rotation to get from |
523 | | rotation \a a to rotation \a b. |
524 | | |
525 | | The result will be 0, 90, 180, or 270. |
526 | | |
527 | | Qt::PrimaryOrientation is interpreted as the screen's primaryOrientation(). |
528 | | */ |
529 | | int QScreen::angleBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b) const |
530 | 0 | { |
531 | 0 | if (a == Qt::PrimaryOrientation) |
532 | 0 | a = primaryOrientation(); |
533 | |
|
534 | 0 | if (b == Qt::PrimaryOrientation) |
535 | 0 | b = primaryOrientation(); |
536 | |
|
537 | 0 | return QPlatformScreen::angleBetween(a, b); |
538 | 0 | } |
539 | | |
540 | | /*! |
541 | | Convenience function to compute a transform that maps from the coordinate system |
542 | | defined by orientation \a a into the coordinate system defined by orientation |
543 | | \a b and target dimensions \a target. |
544 | | |
545 | | Example, \a a is Qt::Landscape, \a b is Qt::Portrait, and \a target is QRect(0, 0, w, h) |
546 | | the resulting transform will be such that the point QPoint(0, 0) is mapped to QPoint(0, w), |
547 | | and QPoint(h, w) is mapped to QPoint(0, h). Thus, the landscape coordinate system QRect(0, 0, h, w) |
548 | | is mapped (with a 90 degree rotation) into the portrait coordinate system QRect(0, 0, w, h). |
549 | | |
550 | | Qt::PrimaryOrientation is interpreted as the screen's primaryOrientation(). |
551 | | */ |
552 | | QTransform QScreen::transformBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b, const QRect &target) const |
553 | 0 | { |
554 | 0 | if (a == Qt::PrimaryOrientation) |
555 | 0 | a = primaryOrientation(); |
556 | |
|
557 | 0 | if (b == Qt::PrimaryOrientation) |
558 | 0 | b = primaryOrientation(); |
559 | |
|
560 | 0 | return QPlatformScreen::transformBetween(a, b, target); |
561 | 0 | } |
562 | | |
563 | | /*! |
564 | | Maps the rect between two screen orientations. |
565 | | |
566 | | This will flip the x and y dimensions of the rectangle \a{rect} if the orientation \a{a} is |
567 | | Qt::PortraitOrientation or Qt::InvertedPortraitOrientation and orientation \a{b} is |
568 | | Qt::LandscapeOrientation or Qt::InvertedLandscapeOrientation, or vice versa. |
569 | | |
570 | | Qt::PrimaryOrientation is interpreted as the screen's primaryOrientation(). |
571 | | */ |
572 | | QRect QScreen::mapBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b, const QRect &rect) const |
573 | 0 | { |
574 | 0 | if (a == Qt::PrimaryOrientation) |
575 | 0 | a = primaryOrientation(); |
576 | |
|
577 | 0 | if (b == Qt::PrimaryOrientation) |
578 | 0 | b = primaryOrientation(); |
579 | |
|
580 | 0 | return QPlatformScreen::mapBetween(a, b, rect); |
581 | 0 | } |
582 | | |
583 | | /*! |
584 | | Convenience function that returns \c true if \a o is either portrait or inverted portrait; |
585 | | otherwise returns \c false. |
586 | | |
587 | | Qt::PrimaryOrientation is interpreted as the screen's primaryOrientation(). |
588 | | */ |
589 | | bool QScreen::isPortrait(Qt::ScreenOrientation o) const |
590 | 0 | { |
591 | 0 | return o == Qt::PortraitOrientation || o == Qt::InvertedPortraitOrientation |
592 | 0 | || (o == Qt::PrimaryOrientation && primaryOrientation() == Qt::PortraitOrientation); |
593 | 0 | } |
594 | | |
595 | | /*! |
596 | | Convenience function that returns \c true if \a o is either landscape or inverted landscape; |
597 | | otherwise returns \c false. |
598 | | |
599 | | Qt::PrimaryOrientation is interpreted as the screen's primaryOrientation(). |
600 | | */ |
601 | | bool QScreen::isLandscape(Qt::ScreenOrientation o) const |
602 | 0 | { |
603 | 0 | return o == Qt::LandscapeOrientation || o == Qt::InvertedLandscapeOrientation |
604 | 0 | || (o == Qt::PrimaryOrientation && primaryOrientation() == Qt::LandscapeOrientation); |
605 | 0 | } |
606 | | |
607 | | /*! |
608 | | \fn void QScreen::orientationChanged(Qt::ScreenOrientation orientation) |
609 | | |
610 | | This signal is emitted when the orientation of the screen |
611 | | changes with \a orientation as an argument. |
612 | | |
613 | | \sa orientation() |
614 | | */ |
615 | | |
616 | | /*! |
617 | | \fn void QScreen::primaryOrientationChanged(Qt::ScreenOrientation orientation) |
618 | | |
619 | | This signal is emitted when the primary orientation of the screen |
620 | | changes with \a orientation as an argument. |
621 | | |
622 | | \sa primaryOrientation() |
623 | | */ |
624 | | |
625 | | void QScreenPrivate::updatePrimaryOrientation() |
626 | 0 | { |
627 | 0 | primaryOrientation = geometry.width() >= geometry.height() ? Qt::LandscapeOrientation : Qt::PortraitOrientation; |
628 | 0 | } |
629 | | |
630 | | /*! |
631 | | Returns the screen at \a point within the set of \l QScreen::virtualSiblings(), |
632 | | or \c nullptr if outside of any screen. |
633 | | |
634 | | The \a point is in relation to the virtualGeometry() of each set of virtual |
635 | | siblings. |
636 | | |
637 | | \since 5.15 |
638 | | */ |
639 | | QScreen *QScreen::virtualSiblingAt(QPoint point) |
640 | 0 | { |
641 | 0 | const auto &siblings = virtualSiblings(); |
642 | 0 | for (QScreen *sibling : siblings) { |
643 | 0 | if (sibling->geometry().contains(point)) |
644 | 0 | return sibling; |
645 | 0 | } |
646 | 0 | return nullptr; |
647 | 0 | } |
648 | | |
649 | | /*! |
650 | | Creates and returns a pixmap constructed by grabbing the contents |
651 | | of the given \a window restricted by QRect(\a x, \a y, \a width, |
652 | | \a height). If \a window is 0, then the entire screen will be |
653 | | grabbed. |
654 | | |
655 | | The arguments (\a{x}, \a{y}) specify the offset in the window, |
656 | | whereas (\a{width}, \a{height}) specify the area to be copied. If |
657 | | \a width is negative, the function copies everything to the right |
658 | | border of the window. If \a height is negative, the function |
659 | | copies everything to the bottom of the window. |
660 | | |
661 | | The offset and size arguments are specified in device independent |
662 | | pixels. The returned pixmap may be larger than the requested size |
663 | | when grabbing from a high-DPI screen. Call QPixmap::devicePixelRatio() |
664 | | to determine if this is the case. |
665 | | |
666 | | The window system identifier (\c WId) can be retrieved using the |
667 | | QWidget::winId() function. The rationale for using a window |
668 | | identifier and not a QWidget, is to enable grabbing of windows |
669 | | that are not part of the application, window system frames, and so |
670 | | on. |
671 | | |
672 | | When \a window is \e{0}, the behavior is platform-dependent. |
673 | | \list |
674 | | \li On platforms where coordinates are screen-local (Windows, X11), |
675 | | (\a{x}, \a{y}) are relative to this screen's origin. |
676 | | \li On platforms where coordinates are global (macOS), |
677 | | (\a{x}, \a{y}) are relative to the virtual desktop. |
678 | | This requires callers to subtract \c{screen->geometry().topLeft()} |
679 | | to achieve the same result as on Windows. |
680 | | \endlist |
681 | | |
682 | | To grab the entire screen portably across platforms, use \c{grabWindow(0)} |
683 | | without specifying coordinates. Code that grabs a sub-area must account for |
684 | | this difference explicitly. |
685 | | |
686 | | \warning Grabbing windows that are not part of the application is |
687 | | not supported on systems such as iOS, where sandboxing/security |
688 | | prevents reading pixels of windows not owned by the application. |
689 | | |
690 | | The grabWindow() function grabs pixels from the screen, not from |
691 | | the window, i.e. if there is another window partially or entirely |
692 | | over the one you grab, you get pixels from the overlying window, |
693 | | too. The mouse cursor is generally not grabbed. |
694 | | |
695 | | Note on X11 that if the given \a window doesn't have the same depth |
696 | | as the root window, and another window partially or entirely |
697 | | obscures the one you grab, you will \e not get pixels from the |
698 | | overlying window. The contents of the obscured areas in the |
699 | | pixmap will be undefined and uninitialized. |
700 | | |
701 | | On Windows Vista and above grabbing a layered window, which is |
702 | | created by setting the Qt::WA_TranslucentBackground attribute, will |
703 | | not work. Instead grabbing the desktop widget should work. |
704 | | |
705 | | \warning In general, grabbing an area outside the screen is not |
706 | | safe. This depends on the underlying window system. |
707 | | */ |
708 | | |
709 | | QPixmap QScreen::grabWindow(WId window, int x, int y, int width, int height) |
710 | 0 | { |
711 | 0 | const QPlatformScreen *platformScreen = handle(); |
712 | 0 | if (!platformScreen) { |
713 | 0 | qWarning("invoked with handle==0"); |
714 | 0 | return QPixmap(); |
715 | 0 | } |
716 | 0 | const qreal factor = QHighDpiScaling::factor(this); |
717 | 0 | if (qFuzzyCompare(factor, 1)) |
718 | 0 | return platformScreen->grabWindow(window, x, y, width, height); |
719 | | |
720 | 0 | const QPoint nativePos = QHighDpi::toNative(QPoint(x, y), factor); |
721 | 0 | QSize nativeSize(width, height); |
722 | 0 | if (nativeSize.isValid()) |
723 | 0 | nativeSize = QHighDpi::toNative(nativeSize, factor); |
724 | 0 | QPixmap result = |
725 | 0 | platformScreen->grabWindow(window, nativePos.x(), nativePos.y(), |
726 | 0 | nativeSize.width(), nativeSize.height()); |
727 | 0 | result.setDevicePixelRatio(result.devicePixelRatio() * factor); |
728 | 0 | return result; |
729 | 0 | } |
730 | | |
731 | | /*! |
732 | | \fn template <typename QNativeInterface> QNativeInterface *QScreen::nativeInterface() const |
733 | | |
734 | | Returns a native interface of the given type for the screen. |
735 | | |
736 | | This function provides access to platform specific functionality |
737 | | of QScreen, as defined in the QNativeInterface namespace: |
738 | | |
739 | | \annotatedlist native-interfaces-qscreen |
740 | | |
741 | | If the requested interface is not available a \nullptr is returned. |
742 | | */ |
743 | | |
744 | | void *QScreen::resolveInterface(const char *name, int revision) const |
745 | 0 | { |
746 | 0 | using namespace QNativeInterface; |
747 | 0 | using namespace QNativeInterface::Private; |
748 | |
|
749 | 0 | auto *platformScreen = handle(); |
750 | 0 | Q_UNUSED(platformScreen); |
751 | 0 | Q_UNUSED(name); |
752 | 0 | Q_UNUSED(revision); |
753 | |
|
754 | | #if QT_CONFIG(xcb) |
755 | | QT_NATIVE_INTERFACE_RETURN_IF(QXcbScreen, platformScreen); |
756 | | #endif |
757 | |
|
758 | | #if QT_CONFIG(vsp2) |
759 | | QT_NATIVE_INTERFACE_RETURN_IF(QVsp2Screen, platformScreen); |
760 | | #endif |
761 | |
|
762 | | #if defined(Q_OS_WEBOS) |
763 | | QT_NATIVE_INTERFACE_RETURN_IF(QWebOSScreen, platformScreen); |
764 | | #endif |
765 | |
|
766 | | #if defined(Q_OS_WIN32) |
767 | | QT_NATIVE_INTERFACE_RETURN_IF(QWindowsScreen, platformScreen); |
768 | | #endif |
769 | |
|
770 | | #if defined(Q_OS_ANDROID) |
771 | | QT_NATIVE_INTERFACE_RETURN_IF(QAndroidScreen, platformScreen); |
772 | | #endif |
773 | |
|
774 | | #if QT_CONFIG(wayland) |
775 | | QT_NATIVE_INTERFACE_RETURN_IF(QWaylandScreen, platformScreen); |
776 | | #endif |
777 | |
|
778 | | #if defined(Q_OS_MACOS) |
779 | | QT_NATIVE_INTERFACE_RETURN_IF(QCocoaScreen, platformScreen); |
780 | | #endif |
781 | |
|
782 | 0 | return nullptr; |
783 | 0 | } |
784 | | |
785 | | #ifndef QT_NO_DEBUG_STREAM |
786 | | Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QScreen *screen) |
787 | 0 | { |
788 | 0 | const QDebugStateSaver saver(debug); |
789 | 0 | debug.nospace(); |
790 | 0 | debug << "QScreen(" << (const void *)screen; |
791 | 0 | if (screen) { |
792 | 0 | debug << ", name=" << screen->name(); |
793 | 0 | if (debug.verbosity() > 2) { |
794 | 0 | if (screen == QGuiApplication::primaryScreen()) |
795 | 0 | debug << ", primary"; |
796 | 0 | debug << ", geometry=" << screen->geometry(); |
797 | 0 | debug << ", available=" << screen->availableGeometry(); |
798 | 0 | debug << ", logical DPI=" << screen->logicalDotsPerInchX() |
799 | 0 | << ',' << screen->logicalDotsPerInchY() |
800 | 0 | << ", physical DPI=" << screen->physicalDotsPerInchX() |
801 | 0 | << ',' << screen->physicalDotsPerInchY() |
802 | 0 | << ", devicePixelRatio=" << screen->devicePixelRatio() |
803 | 0 | << ", orientation=" << screen->orientation() |
804 | 0 | << ", physical size=" << screen->physicalSize().width() |
805 | 0 | << 'x' << screen->physicalSize().height() << "mm"; |
806 | 0 | } |
807 | 0 | } |
808 | 0 | debug << ')'; |
809 | 0 | return debug; |
810 | 0 | } |
811 | | #endif // !QT_NO_DEBUG_STREAM |
812 | | |
813 | | QScreenPrivate::UpdateEmitter::UpdateEmitter(QScreen *screen) |
814 | 0 | { |
815 | 0 | initialState.platformScreen = screen->handle(); |
816 | | |
817 | | // Use public APIs to read out current state, rather |
818 | | // than accessing the QScreenPrivate members, so that |
819 | | // we detect any changes to the high-DPI scale factors |
820 | | // that may be applied in the getters. |
821 | |
|
822 | 0 | initialState.logicalDpi = QDpi{ |
823 | 0 | screen->logicalDotsPerInchX(), |
824 | 0 | screen->logicalDotsPerInchY() |
825 | 0 | }; |
826 | 0 | initialState.geometry = screen->geometry(); |
827 | 0 | initialState.availableGeometry = screen->availableGeometry(); |
828 | 0 | initialState.primaryOrientation = screen->primaryOrientation(); |
829 | 0 | } |
830 | | |
831 | | QScreenPrivate::UpdateEmitter::~UpdateEmitter() |
832 | 0 | { |
833 | 0 | QScreen *screen = initialState.platformScreen->screen(); |
834 | |
|
835 | 0 | const auto logicalDotsPerInch = QDpi{ |
836 | 0 | screen->logicalDotsPerInchX(), |
837 | 0 | screen->logicalDotsPerInchY() |
838 | 0 | }; |
839 | 0 | if (logicalDotsPerInch != initialState.logicalDpi) |
840 | 0 | emit screen->logicalDotsPerInchChanged(screen->logicalDotsPerInch()); |
841 | |
|
842 | 0 | const auto geometry = screen->geometry(); |
843 | 0 | const auto geometryChanged = geometry != initialState.geometry; |
844 | 0 | if (geometryChanged) |
845 | 0 | emit screen->geometryChanged(geometry); |
846 | |
|
847 | 0 | const auto availableGeometry = screen->availableGeometry(); |
848 | 0 | const auto availableGeometryChanged = availableGeometry != initialState.availableGeometry; |
849 | 0 | if (availableGeometryChanged) |
850 | 0 | emit screen->availableGeometryChanged(availableGeometry); |
851 | |
|
852 | 0 | if (geometryChanged || availableGeometryChanged) { |
853 | 0 | const auto siblings = screen->virtualSiblings(); |
854 | 0 | for (QScreen* sibling : siblings) |
855 | 0 | emit sibling->virtualGeometryChanged(sibling->virtualGeometry()); |
856 | 0 | } |
857 | |
|
858 | 0 | if (geometryChanged) { |
859 | 0 | emit screen->physicalDotsPerInchChanged(screen->physicalDotsPerInch()); |
860 | |
|
861 | 0 | const auto primaryOrientation = screen->primaryOrientation(); |
862 | 0 | if (primaryOrientation != initialState.primaryOrientation) |
863 | 0 | emit screen->primaryOrientationChanged(primaryOrientation); |
864 | 0 | } |
865 | 0 | } |
866 | | |
867 | | QT_END_NAMESPACE |
868 | | |
869 | | #include "moc_qscreen.cpp" |