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