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

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