Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qplatformscreen.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
6#include <QtCore/qdebug.h>
7#include <QtGui/qguiapplication.h>
8#include <qpa/qplatformcursor.h>
9#include <QtGui/private/qguiapplication_p.h>
10#include <qpa/qplatformscreen_p.h>
11#include <qpa/qplatformintegration.h>
12#include <QtGui/qscreen.h>
13#include <QtGui/qwindow.h>
14#include <private/qhighdpiscaling_p.h>
15#include <private/qwindow_p.h>
16
18
19QPlatformScreen::QPlatformScreen()
20 : d_ptr(new QPlatformScreenPrivate)
21{
22 Q_D(QPlatformScreen);
23 d->screen = nullptr;
24}
25
26QPlatformScreen::~QPlatformScreen()
27{
28 Q_D(QPlatformScreen);
29 Q_ASSERT_X(!d->screen, "QPlatformScreen",
30 "QPlatformScreens should be removed via QWindowSystemInterface::handleScreenRemoved()");
31}
32
33/*!
34 This function is called when Qt needs to be able to grab the content of a window.
35
36 Returns the content of the window specified with the WId handle within the boundaries of
37 QRect(x,y,width,height).
38*/
39QPixmap QPlatformScreen::grabWindow(WId window, int x, int y, int width, int height) const
40{
41 Q_UNUSED(window);
42 Q_UNUSED(x);
43 Q_UNUSED(y);
44 Q_UNUSED(width);
45 Q_UNUSED(height);
46 return QPixmap();
47}
48
49/*!
50 Return the given top level window for a given position.
51
52 Default implementation retrieves a list of all top level windows and finds the first window
53 which contains point \a pos
54*/
55QWindow *QPlatformScreen::topLevelAt(const QPoint & pos) const
56{
57 const QWindowList list = QGuiApplication::topLevelWindows();
58 const auto crend = list.crend();
59 for (auto it = list.crbegin(); it != crend; ++it) {
60 QWindow *w = *it;
61 if (w->isVisible() && QHighDpi::toNativePixels(w->geometry(), w).contains(pos))
62 return w;
63 }
64
65 return nullptr;
66}
67
68/*!
69 Return all windows residing on this screen.
70*/
71QWindowList QPlatformScreen::windows() const
72{
73 QWindowList windows;
74 for (QWindow *window : QGuiApplication::allWindows()) {
75 if (platformScreenForWindow(window) != this)
76 continue;
77 windows.append(window);
78 }
79 return windows;
80}
81
82/*!
83 Find the sibling screen corresponding to \a globalPos.
84
85 Returns this screen if no suitable screen is found at the position.
86 */
87const QPlatformScreen *QPlatformScreen::screenForPosition(const QPoint &point) const
88{
89 if (!geometry().contains(point)) {
90 const auto screens = virtualSiblings();
91 for (const QPlatformScreen *screen : screens) {
92 if (screen->geometry().contains(point))
93 return screen;
94 }
95 }
96 return this;
97}
98
99
100/*!
101 Returns a list of all the platform screens that are part of the same
102 virtual desktop.
103
104 Screens part of the same virtual desktop share a common coordinate system,
105 and windows can be freely moved between them.
106*/
107QList<QPlatformScreen *> QPlatformScreen::virtualSiblings() const
108{
109 QList<QPlatformScreen *> list;
110 list << const_cast<QPlatformScreen *>(this);
111 return list;
112}
113
114QScreen *QPlatformScreen::screen() const
115{
116 Q_D(const QPlatformScreen);
117 return d->screen;
118}
119
120/*!
121 Reimplement this function in subclass to return the physical size of the
122 screen, in millimeters. The physical size represents the actual physical
123 dimensions of the display.
124
125 The default implementation takes the pixel size of the screen, considers a
126 resolution of 100 dots per inch, and returns the calculated physical size.
127 A device with a screen that has different resolutions will need to be
128 supported by a suitable reimplementation of this function.
129
130 \sa logcalDpi
131*/
132QSizeF QPlatformScreen::physicalSize() const
133{
134 static const int dpi = 100;
135 return QSizeF(geometry().size()) / dpi * qreal(25.4);
136}
137
138/*!
139 Reimplement this function in subclass to return the logical horizontal
140 and vertical dots per inch metrics of the screen.
141
142 The logical dots per inch metrics are used by Qt to scale the user interface.
143
144 The default implementation returns logicalBaseDpi(), which results in a
145 UI scale factor of 1.0.
146
147 \sa physicalSize
148*/
149QDpi QPlatformScreen::logicalDpi() const
150{
151 return logicalBaseDpi();
152}
153
154// Helper function for accessing the platform screen logical dpi
155// which accounts for QT_FONT_DPI.
156QDpi QPlatformScreen::overrideDpi(const QDpi &in)
157{
158 static const int overrideDpi = qEnvironmentVariableIntValue("QT_FONT_DPI");
159 return overrideDpi > 0 ? QDpi(overrideDpi, overrideDpi) : in;
160}
161
162/*!
163 Reimplement to return the base logical DPI for the platform. This
164 DPI value should correspond to a standard-DPI (1x) display. The
165 default implementation returns 96.
166
167 QtGui will use this value (together with logicalDpi) to compute
168 the scale factor when high-DPI scaling is enabled, as follows:
169 factor = logicalDPI / baseDPI
170*/
171QDpi QPlatformScreen::logicalBaseDpi() const
172{
173 return QDpi(96, 96);
174}
175
176/*!
177 Reimplement this function in subclass to return the device pixel ratio
178 for the screen. This is the ratio between physical pixels and the
179 device-independent pixels of the windowing system. The default
180 implementation returns 1.0.
181
182 \sa QPlatformWindow::devicePixelRatio()
183*/
184qreal QPlatformScreen::devicePixelRatio() const
185{
186 return 1.0;
187}
188
189/*!
190 Reimplement this function in subclass to return the vertical refresh rate
191 of the screen, in Hz.
192
193 The default returns 60, a sensible default for modern displays.
194*/
195qreal QPlatformScreen::refreshRate() const
196{
197 return 60;
198}
199
200/*!
201 Reimplement this function in subclass to return the native orientation
202 of the screen, e.g. the orientation where the logo sticker of the device
203 appears the right way up.
204
205 The default implementation returns Qt::PrimaryOrientation.
206*/
207Qt::ScreenOrientation QPlatformScreen::nativeOrientation() const
208{
209 return Qt::PrimaryOrientation;
210}
211
212/*!
213 Reimplement this function in subclass to return the current orientation
214 of the screen, for example based on accelerometer data to determine
215 the device orientation.
216
217 The default implementation returns Qt::PrimaryOrientation.
218*/
219Qt::ScreenOrientation QPlatformScreen::orientation() const
220{
221 return Qt::PrimaryOrientation;
222}
223
224QPlatformScreen * QPlatformScreen::platformScreenForWindow(const QWindow *window)
225{
226 // QTBUG 32681: It can happen during the transition between screens
227 // when one screen is disconnected that the window doesn't have a screen.
228 if (!window->screen())
229 return nullptr;
230 return window->screen()->handle();
231}
232
233/*!
234 Reimplement this function in subclass to return the manufacturer
235 of this screen.
236
237 The default implementation returns an empty string.
238
239 \since 5.9
240*/
241QString QPlatformScreen::manufacturer() const
242{
243 return QString();
244}
245
246/*!
247 Reimplement this function in subclass to return the model
248 of this screen.
249
250 The default implementation returns an empty string.
251
252 \since 5.9
253*/
254QString QPlatformScreen::model() const
255{
256 return QString();
257}
258
259/*!
260 Reimplement this function in subclass to return the serial number
261 of this screen.
262
263 The default implementation returns an empty string.
264
265 \since 5.9
266*/
267QString QPlatformScreen::serialNumber() const
268{
269 return QString();
270}
271
272/*!
273 \class QPlatformScreen
274 \since 4.8
275 \internal
276 \preliminary
277 \ingroup qpa
278
279 \brief The QPlatformScreen class provides an abstraction for visual displays.
280
281 Many window systems has support for retrieving information on the attached displays. To be able
282 to query the display QPA uses QPlatformScreen. Qt its self is most dependent on the
283 physicalSize() function, since this is the function it uses to calculate the dpi to use when
284 converting point sizes to pixels sizes. However, this is unfortunate on some systems, as the
285 native system fakes its dpi size.
286 */
287
288/*! \fn QRect QPlatformScreen::geometry() const = 0
289 Reimplement in subclass to return the pixel geometry of the screen
290*/
291
292/*! \fn QRect QPlatformScreen::availableGeometry() const
293 Reimplement in subclass to return the pixel geometry of the available space
294 This normally is the desktop screen minus the task manager, global menubar etc.
295*/
296
297/*! \fn int QPlatformScreen::depth() const = 0
298 Reimplement in subclass to return current depth of the screen
299*/
300
301/*! \fn QImage::Format QPlatformScreen::format() const = 0
302 Reimplement in subclass to return the image format which corresponds to the screen format
303*/
304
305/*!
306 Reimplement this function in subclass to return the cursor of the screen.
307
308 The default implementation returns \nullptr.
309*/
310QPlatformCursor *QPlatformScreen::cursor() const
311{
312 return nullptr;
313}
314
315/*!
316 Convenience method to resize all the maximized and fullscreen windows
317 of this platform screen.
318*/
319void QPlatformScreen::resizeMaximizedWindows()
320{
321 // 'screen()' still has the old geometry (in device independent pixels),
322 // while 'this' has the new geometry (in native pixels)
323 const QRect oldGeometry = screen()->geometry();
324 const QRect oldAvailableGeometry = screen()->availableGeometry();
325 const QRect newNativeGeometry = this->geometry();
326 const QRect newNativeAvailableGeometry = this->availableGeometry();
327
328 const bool supportsMaximizeUsingFullscreen = QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::MaximizeUsingFullscreenGeometry);
329
330 for (QWindow *w : windows()) {
331 // Skip non-platform windows, e.g., offscreen windows.
332 if (!w->handle())
333 continue;
334
335 // Set QPlatformWindow size in native pixels, and let the platform's geometry
336 // change signals update the QWindow geomeyry. This way we make sure that the
337 // platform window geometry covers the entire (available) platform screen geometry,
338 // also when fractional DPRs introduce rounding errors in the device independent
339 // QWindow and QScreen sizes.
340 if (supportsMaximizeUsingFullscreen
341 && w->windowState() & Qt::WindowMaximized
342 && w->flags() & Qt::ExpandedClientAreaHint) {
343 w->handle()->setGeometry(newNativeGeometry);
344 } else if (w->windowState() & Qt::WindowMaximized || w->geometry() == oldAvailableGeometry) {
345 w->handle()->setGeometry(newNativeAvailableGeometry);
346 } else if (w->windowState() & Qt::WindowFullScreen || w->geometry() == oldGeometry) {
347 w->handle()->setGeometry(newNativeGeometry);
348 }
349 }
350}
351
352// i must be power of two
353static int log2(uint i)
354{
355 if (i == 0)
356 return -1;
357
358 int result = 0;
359 while (!(i & 1)) {
360 ++result;
361 i >>= 1;
362 }
363 return result;
364}
365
366int QPlatformScreen::angleBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b)
367{
368 if (a == Qt::PrimaryOrientation || b == Qt::PrimaryOrientation) {
369 qWarning("Use QScreen version of %sBetween() when passing Qt::PrimaryOrientation", "angle");
370 return 0;
371 }
372
373 if (a == b)
374 return 0;
375
376 int ia = log2(uint(a));
377 int ib = log2(uint(b));
378
379 int delta = ia - ib;
380
381 if (delta < 0)
382 delta = delta + 4;
383
384 int angles[] = { 0, 90, 180, 270 };
385 return angles[delta];
386}
387
388QTransform QPlatformScreen::transformBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b, const QRect &target)
389{
390 if (a == Qt::PrimaryOrientation || b == Qt::PrimaryOrientation) {
391 qWarning("Use QScreen version of %sBetween() when passing Qt::PrimaryOrientation", "transform");
392 return QTransform();
393 }
394
395 if (a == b)
396 return QTransform();
397
398 int angle = angleBetween(a, b);
399
400 QTransform result;
401 switch (angle) {
402 case 90:
403 result.translate(target.width(), 0);
404 break;
405 case 180:
406 result.translate(target.width(), target.height());
407 break;
408 case 270:
409 result.translate(0, target.height());
410 break;
411 default:
412 Q_ASSERT(false);
413 }
414 result.rotate(angle);
415
416 return result;
417}
418
419QRect QPlatformScreen::mapBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b, const QRect &rect)
420{
421 if (a == Qt::PrimaryOrientation || b == Qt::PrimaryOrientation) {
422 qWarning("Use QScreen version of %sBetween() when passing Qt::PrimaryOrientation", "map");
423 return rect;
424 }
425
426 if (a == b)
427 return rect;
428
429 if ((a == Qt::PortraitOrientation || a == Qt::InvertedPortraitOrientation)
430 != (b == Qt::PortraitOrientation || b == Qt::InvertedPortraitOrientation))
431 {
432 return QRect(rect.y(), rect.x(), rect.height(), rect.width());
433 }
434
435 return rect;
436}
437
438/*!
439 Returns a hint about this screen's subpixel layout structure.
440
441 The default implementation queries the \b{QT_SUBPIXEL_AA_TYPE} env variable.
442 This is just a hint because most platforms don't have a way to retrieve the correct value from hardware
443 and instead rely on font configurations.
444*/
445QPlatformScreen::SubpixelAntialiasingType QPlatformScreen::subpixelAntialiasingTypeHint() const
446{
447 static int type = -1;
448 if (type == -1) {
449 QByteArray env = qgetenv("QT_SUBPIXEL_AA_TYPE");
450 if (env == "RGB")
451 type = QPlatformScreen::Subpixel_RGB;
452 else if (env == "BGR")
453 type = QPlatformScreen::Subpixel_BGR;
454 else if (env == "VRGB")
455 type = QPlatformScreen::Subpixel_VRGB;
456 else if (env == "VBGR")
457 type = QPlatformScreen::Subpixel_VBGR;
458 else
459 type = QPlatformScreen::Subpixel_None;
460 }
461
462 return static_cast<QPlatformScreen::SubpixelAntialiasingType>(type);
463}
464
465/*!
466 Returns the current power state.
467
468 The default implementation always returns PowerStateOn.
469*/
470QPlatformScreen::PowerState QPlatformScreen::powerState() const
471{
472 return PowerStateOn;
473}
474
475/*!
476 Sets the power state for this screen.
477*/
478void QPlatformScreen::setPowerState(PowerState state)
479{
480 Q_UNUSED(state);
481}
482
483/*!
484 Reimplement this function in subclass to return the list
485 of modes for this screen.
486
487 The default implementation returns a list with
488 only one mode from the current screen size and refresh rate.
489
490 \sa QPlatformScreen::geometry
491 \sa QPlatformScreen::refreshRate
492
493 \since 5.9
494*/
495QList<QPlatformScreen::Mode> QPlatformScreen::modes() const
496{
497 QList<QPlatformScreen::Mode> list;
498 list.append({geometry().size(), refreshRate()});
499 return list;
500}
501
502/*!
503 Reimplement this function in subclass to return the
504 index of the current mode from the modes list.
505
506 The default implementation returns 0.
507
508 \sa QPlatformScreen::modes
509
510 \since 5.9
511*/
512int QPlatformScreen::currentMode() const
513{
514 return 0;
515}
516
517/*!
518 Reimplement this function in subclass to return the preferred
519 mode index from the modes list.
520
521 The default implementation returns 0.
522
523 \sa QPlatformScreen::modes
524
525 \since 5.9
526*/
527int QPlatformScreen::preferredMode() const
528{
529 return 0;
530}
531
532QList<QPlatformScreen *> QPlatformPlaceholderScreen::virtualSiblings() const
533{
534 QList<QPlatformScreen *> siblings;
535
536 if (!m_virtualSibling)
537 return siblings;
538
539 for (QScreen *screen : QGuiApplication::screens()) {
540 if (screen->handle() && screen->handle() != this)
541 siblings << screen->handle();
542 }
543 return siblings;
544}
545
546QT_END_NAMESPACE
Combined button and popup list for selecting options.
static int log2(uint i)