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