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 QtQuick 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 "qquickscreen_p.h"
41
42#include "qquickitem.h"
43#include "qquickitem_p.h"
44#include "qquickwindow.h"
45
46#include <QGuiApplication>
47#include <QScreen>
48
49QT_BEGIN_NAMESPACE
50
51/*!
52 \qmltype Screen
53 \instantiates QQuickScreenAttached
54 \inqmlmodule QtQuick.Window
55 \ingroup qtquick-visual-utility
56 \brief The Screen attached object provides information about the Screen an Item or Window is displayed on.
57
58 The Screen attached object is valid inside Item or Item derived types,
59 after component completion. Inside these items it refers to the screen that
60 the item is currently being displayed on.
61
62 The attached object is also valid inside Window or Window derived types,
63 after component completion. In that case it refers to the screen where the
64 Window was created. It is generally better to access the Screen from the
65 relevant Item instead, because on a multi-screen desktop computer, the user
66 can drag a Window into a position where it spans across multiple screens.
67 In that case some Items will be on one screen, and others on a different
68 screen.
69
70 To use this type, you will need to import the module with the following line:
71 \code
72 import QtQuick.Window 2.2
73 \endcode
74 It is a separate import in order to allow you to have a QML environment
75 without access to window system features.
76
77 Note that the Screen type is not valid at Component.onCompleted, because
78 the Item or Window has not been displayed on a screen by this time.
79*/
80
81/*!
82 \qmlattachedproperty string Screen::name
83 \readonly
84 \since 5.1
85
86 The name of the screen.
87*/
88/*!
89 \qmlattachedproperty int Screen::virtualX
90 \readonly
91 \since 5.9
92
93 The x coordinate of the screen within the virtual desktop.
94*/
95/*!
96 \qmlattachedproperty int Screen::virtualY
97 \readonly
98 \since 5.9
99
100 The y coordinate of the screen within the virtual desktop.
101*/
102/*!
103 \qmlattachedproperty string Screen::manufacturer
104 \readonly
105 \since 5.10
106
107 The manufacturer of the screen.
108*/
109/*!
110 \qmlattachedproperty string Screen::model
111 \readonly
112 \since 5.10
113
114 The model of the screen.
115*/
116/*!
117 \qmlattachedproperty string Screen::serialNumber
118 \readonly
119 \since 5.10
120
121 The serial number of the screen.
122*/
123/*!
124 \qmlattachedproperty int Screen::width
125 \readonly
126
127 This contains the width of the screen in pixels.
128*/
129/*!
130 \qmlattachedproperty int Screen::height
131 \readonly
132
133 This contains the height of the screen in pixels.
134*/
135/*!
136 \qmlattachedproperty int Screen::desktopAvailableWidth
137 \readonly
138 \since 5.1
139
140 This contains the available width of the collection of screens which make
141 up the virtual desktop, in pixels, excluding window manager reserved areas
142 such as task bars and system menus. If you want to position a Window at
143 the right of the desktop, you can bind to it like this:
144
145 \code
146 x: Screen.desktopAvailableWidth - width
147 \endcode
148*/
149/*!
150 \qmlattachedproperty int Screen::desktopAvailableHeight
151 \readonly
152 \since 5.1
153
154 This contains the available height of the collection of screens which make
155 up the virtual desktop, in pixels, excluding window manager reserved areas
156 such as task bars and system menus. If you want to position a Window at
157 the bottom of the desktop, you can bind to it like this:
158
159 \code
160 y: Screen.desktopAvailableHeight - height
161 \endcode
162*/
163/*!
164 \qmlattachedproperty real Screen::logicalPixelDensity
165 \readonly
166 \since 5.1
167 \deprecated
168
169 The number of logical pixels per millimeter. This is the effective pixel
170 density provided by the platform to use in image scaling calculations.
171
172 Due to inconsistencies in how logical pixel density is handled across
173 the various platforms Qt supports, it is recommended to
174 use physical pixels instead (via the \c pixelDensity property) for
175 portability.
176
177 \sa pixelDensity
178*/
179/*!
180 \qmlattachedproperty real Screen::pixelDensity
181 \readonly
182 \since 5.2
183
184 The number of physical pixels per millimeter.
185*/
186/*!
187 \qmlattachedproperty real Screen::devicePixelRatio
188 \readonly
189 \since 5.4
190
191 The ratio between physical pixels and device-independent pixels for the screen.
192
193 Common values are 1.0 on normal displays and 2.0 on Apple "retina" displays.
194*/
195/*!
196 \qmlattachedproperty Qt::ScreenOrientation Screen::primaryOrientation
197 \readonly
198
199 This contains the primary orientation of the screen. If the
200 screen's height is greater than its width, then the orientation is
201 Qt.PortraitOrientation; otherwise it is Qt.LandscapeOrientation.
202
203 If you are designing an application which changes its layout depending on
204 device orientation, you probably want to use primaryOrientation to
205 determine the layout. That is because on a desktop computer, you can expect
206 primaryOrientation to change when the user rotates the screen via the
207 operating system's control panel, even if the computer does not contain an
208 accelerometer. Likewise on most handheld computers which do have
209 accelerometers, the operating system will rotate the whole screen
210 automatically, so again you will see the primaryOrientation change.
211*/
212/*!
213 \qmlattachedproperty Qt::ScreenOrientation Screen::orientation
214 \readonly
215
216 This contains the current orientation of the screen, from the accelerometer
217 (if any). On a desktop computer, this value typically does not change.
218
219 If primaryOrientation == orientation, it means that the screen
220 automatically rotates all content which is displayed, depending on how you
221 hold it. But if orientation changes while primaryOrientation does NOT
222 change, then probably you are using a device which does not rotate its own
223 display. In that case you may need to use \l {Item::rotation}{Item.rotation} or
224 \l {Item::transform}{Item.transform} to rotate your content.
225
226 \note This property does not update unless a Screen::orientationUpdateMask
227 is set to a value other than \c 0.
228*/
229/*!
230 \qmlattachedmethod int Screen::angleBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b)
231
232 Returns the rotation angle, in degrees, between the specified screen
233 orientations \a a and \a b.
234*/
235
236/*!
237 \qmlattachedproperty Qt::ScreenOrientations Screen::orientationUpdateMask
238 \since 5.4
239
240 This contains the update mask for the orientation. Screen::orientation
241 only emits changes for the screen orientations matching this mask.
242
243 By default it is set to the value of the QScreen that the window uses.
244*/
245
246QQuickScreenInfo::QQuickScreenInfo(QObject *parent, QScreen *wrappedScreen)
247 : QObject(parent)
248 , m_screen(wrappedScreen)
249{
250}
251
252QString QQuickScreenInfo::name() const
253{
254 if (!m_screen)
255 return QString();
256 return m_screen->name();
257}
258
259QString QQuickScreenInfo::manufacturer() const
260{
261 if (!m_screen)
262 return QString();
263 return m_screen->manufacturer();
264}
265
266QString QQuickScreenInfo::model() const
267{
268 if (!m_screen)
269 return QString();
270 return m_screen->model();
271}
272
273QString QQuickScreenInfo::serialNumber() const
274{
275 if (!m_screen)
276 return QString();
277 return m_screen->serialNumber();
278}
279
280int QQuickScreenInfo::width() const
281{
282 if (!m_screen)
283 return 0;
284 return m_screen->size().width();
285}
286
287int QQuickScreenInfo::height() const
288{
289 if (!m_screen)
290 return 0;
291 return m_screen->size().height();
292}
293
294int QQuickScreenInfo::desktopAvailableWidth() const
295{
296 if (!m_screen)
297 return 0;
298 return m_screen->availableVirtualSize().width();
299}
300
301int QQuickScreenInfo::desktopAvailableHeight() const
302{
303 if (!m_screen)
304 return 0;
305 return m_screen->availableVirtualSize().height();
306}
307
308qreal QQuickScreenInfo::logicalPixelDensity() const
309{
310 if (!m_screen)
311 return 0.0;
312 return m_screen->logicalDotsPerInch() / 25.4;
313}
314
315qreal QQuickScreenInfo::pixelDensity() const
316{
317 if (!m_screen)
318 return 0.0;
319 return m_screen->physicalDotsPerInch() / 25.4;
320}
321
322qreal QQuickScreenInfo::devicePixelRatio() const
323{
324 if (!m_screen)
325 return 1.0;
326 return m_screen->devicePixelRatio();
327}
328
329Qt::ScreenOrientation QQuickScreenInfo::primaryOrientation() const
330{
331 if (!m_screen)
332 return Qt::PrimaryOrientation;
333 return m_screen->primaryOrientation();
334}
335
336Qt::ScreenOrientation QQuickScreenInfo::orientation() const
337{
338 if (!m_screen)
339 return Qt::PrimaryOrientation;
340 return m_screen->orientation();
341}
342
343int QQuickScreenInfo::virtualX() const
344{
345 if (!m_screen)
346 return 0;
347 return m_screen->geometry().topLeft().x();
348}
349
350int QQuickScreenInfo::virtualY() const
351{
352 if (!m_screen)
353 return 0;
354 return m_screen->geometry().topLeft().y();
355}
356
357void QQuickScreenInfo::setWrappedScreen(QScreen *screen)
358{
359 if (screen == m_screen)
360 return;
361
362 QScreen *oldScreen = m_screen;
363 m_screen = screen;
364
365 if (oldScreen)
366 oldScreen->disconnect(receiver: this);
367
368 if (!screen) //Don't bother emitting signals, because the new values are garbage anyways
369 return;
370
371 if (!oldScreen || screen->geometry() != oldScreen->geometry()) {
372 emit virtualXChanged();
373 emit virtualYChanged();
374 }
375 if (!oldScreen || screen->size() != oldScreen->size()) {
376 emit widthChanged();
377 emit heightChanged();
378 }
379 if (!oldScreen || screen->name() != oldScreen->name())
380 emit nameChanged();
381 if (!oldScreen || screen->manufacturer() != oldScreen->manufacturer())
382 emit manufacturerChanged();
383 if (!oldScreen || screen->model() != oldScreen->model())
384 emit modelChanged();
385 if (!oldScreen || screen->serialNumber() != oldScreen->serialNumber())
386 emit serialNumberChanged();
387 if (!oldScreen || screen->orientation() != oldScreen->orientation())
388 emit orientationChanged();
389 if (!oldScreen || screen->primaryOrientation() != oldScreen->primaryOrientation())
390 emit primaryOrientationChanged();
391 if (!oldScreen || screen->availableVirtualGeometry() != oldScreen->availableVirtualGeometry())
392 emit desktopGeometryChanged();
393 if (!oldScreen || screen->logicalDotsPerInch() != oldScreen->logicalDotsPerInch())
394 emit logicalPixelDensityChanged();
395 if (!oldScreen || screen->physicalDotsPerInch() != oldScreen->physicalDotsPerInch())
396 emit pixelDensityChanged();
397 if (!oldScreen || screen->devicePixelRatio() != oldScreen->devicePixelRatio())
398 emit devicePixelRatioChanged();
399
400 qmlobject_connect(screen, QScreen, SIGNAL(geometryChanged(QRect)),
401 this, QQuickScreenInfo, SIGNAL(widthChanged()));
402 qmlobject_connect(screen, QScreen, SIGNAL(geometryChanged(QRect)),
403 this, QQuickScreenInfo, SIGNAL(heightChanged()));
404 qmlobject_connect(screen, QScreen, SIGNAL(geometryChanged(QRect)),
405 this, QQuickScreenInfo, SIGNAL(virtualXChanged()));
406 qmlobject_connect(screen, QScreen, SIGNAL(geometryChanged(QRect)),
407 this, QQuickScreenInfo, SIGNAL(virtualYChanged()));
408 qmlobject_connect(screen, QScreen, SIGNAL(orientationChanged(Qt::ScreenOrientation)),
409 this, QQuickScreenInfo, SIGNAL(orientationChanged()));
410 qmlobject_connect(screen, QScreen, SIGNAL(primaryOrientationChanged(Qt::ScreenOrientation)),
411 this, QQuickScreenInfo, SIGNAL(primaryOrientationChanged()));
412 qmlobject_connect(screen, QScreen, SIGNAL(virtualGeometryChanged(QRect)),
413 this, QQuickScreenInfo, SIGNAL(desktopGeometryChanged()));
414 qmlobject_connect(screen, QScreen, SIGNAL(logicalDotsPerInchChanged(qreal)),
415 this, QQuickScreenInfo, SIGNAL(logicalPixelDensityChanged()));
416 qmlobject_connect(screen, QScreen, SIGNAL(physicalDotsPerInchChanged(qreal)),
417 this, QQuickScreenInfo, SIGNAL(pixelDensityChanged()));
418}
419
420QScreen *QQuickScreenInfo::wrappedScreen() const
421{
422 return m_screen;
423}
424
425QQuickScreenAttached::QQuickScreenAttached(QObject* attachee)
426 : QQuickScreenInfo(attachee)
427{
428 m_attachee = qobject_cast<QQuickItem*>(object: attachee);
429
430 if (m_attachee) {
431 QQuickItemPrivate::get(item: m_attachee)->extra.value().screenAttached = this;
432
433 if (m_attachee->window()) //It might not be assigned to a window yet
434 windowChanged(m_attachee->window());
435 } else {
436 QQuickWindow *window = qobject_cast<QQuickWindow*>(object: attachee);
437 if (window)
438 windowChanged(window);
439 }
440
441 if (!m_screen)
442 screenChanged(QGuiApplication::primaryScreen());
443}
444
445Qt::ScreenOrientations QQuickScreenAttached::orientationUpdateMask() const
446{
447 return m_updateMask;
448}
449
450void QQuickScreenAttached::setOrientationUpdateMask(Qt::ScreenOrientations mask)
451{
452 m_updateMaskSet = true;
453 if (m_updateMask == mask)
454 return;
455
456 m_updateMask = mask;
457
458 if (m_screen)
459 m_screen->setOrientationUpdateMask(m_updateMask);
460
461 emit orientationUpdateMaskChanged();
462}
463
464int QQuickScreenAttached::angleBetween(int a, int b)
465{
466 if (!m_screen)
467 return Qt::PrimaryOrientation;
468 return m_screen->angleBetween(a: (Qt::ScreenOrientation)a,b: (Qt::ScreenOrientation)b);
469}
470
471void QQuickScreenAttached::windowChanged(QQuickWindow* c)
472{
473 if (m_window)
474 qmlobject_disconnect(m_window, QQuickWindow, SIGNAL(screenChanged(QScreen*)), this, QQuickScreenAttached, SLOT(screenChanged(QScreen*)));
475 m_window = c;
476 screenChanged(c ? c->screen() : nullptr);
477 if (c)
478 qmlobject_connect(c, QQuickWindow, SIGNAL(screenChanged(QScreen*)), this, QQuickScreenAttached, SLOT(screenChanged(QScreen*)));
479}
480
481void QQuickScreenAttached::screenChanged(QScreen *screen)
482{
483 //qDebug() << "QQuickScreenAttached::screenChanged" << (screen ? screen->name() : QString::fromLatin1("null"));
484 if (screen != m_screen) {
485 setWrappedScreen(screen);
486 if (!m_screen)
487 return;
488 if (m_updateMaskSet) {
489 m_screen->setOrientationUpdateMask(m_updateMask);
490 } else if (m_updateMask != m_screen->orientationUpdateMask()) {
491 m_updateMask = m_screen->orientationUpdateMask();
492 emit orientationUpdateMaskChanged();
493 }
494 }
495}
496
497QT_END_NAMESPACE
498
499#include "moc_qquickscreen_p.cpp"
500

source code of qtdeclarative/src/quick/items/qquickscreen.cpp