| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the QtGui module of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU Lesser General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU Lesser |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
| ** packaging of this file. Please review the following information to |
| ** ensure the GNU Lesser General Public License version 3 requirements |
| ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 2.0 or (at your option) the GNU General |
| ** Public license version 3 or any later version approved by the KDE Free |
| ** Qt Foundation. The licenses are as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
| ** https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include "qscreen.h" |
| #include "qscreen_p.h" |
| #include "qpixmap.h" |
| #include "qguiapplication_p.h" |
| #include <qpa/qplatformscreen.h> |
| #include <qpa/qplatformscreen_p.h> |
| |
| #include <QtCore/QDebug> |
| #include <QtCore/private/qobject_p.h> |
| #include "qhighdpiscaling_p.h" |
| |
| QT_BEGIN_NAMESPACE |
| |
| /*! |
| \class QScreen |
| \since 5.0 |
| \brief The QScreen class is used to query screen properties. |
| \inmodule QtGui |
| |
| A note on logical vs physical dots per inch: physical DPI is based on the |
| actual physical pixel sizes when available, and is useful for print preview |
| and other cases where it's desirable to know the exact physical dimensions |
| of screen displayed contents. |
| |
| Logical dots per inch are used to convert font and user interface elements |
| from point sizes to pixel sizes, and might be different from the physical |
| dots per inch. The logical dots per inch are sometimes user-settable in the |
| desktop environment's settings panel, to let the user globally control UI |
| and font sizes in different applications. |
| |
| \inmodule QtGui |
| */ |
| |
| QScreen::QScreen(QPlatformScreen *screen) |
| : QObject(*new QScreenPrivate(), nullptr) |
| { |
| Q_D(QScreen); |
| d->setPlatformScreen(screen); |
| } |
| |
| void QScreenPrivate::updateGeometriesWithSignals() |
| { |
| const QRect oldGeometry = geometry; |
| const QRect oldAvailableGeometry = availableGeometry; |
| updateHighDpi(); |
| emitGeometryChangeSignals(oldGeometry != geometry, oldAvailableGeometry != availableGeometry); |
| } |
| |
| void QScreenPrivate::emitGeometryChangeSignals(bool geometryChanged, bool availableGeometryChanged) |
| { |
| Q_Q(QScreen); |
| if (availableGeometryChanged) |
| emit q->availableGeometryChanged(availableGeometry); |
| |
| if (geometryChanged || availableGeometryChanged) { |
| const auto siblings = q->virtualSiblings(); |
| for (QScreen* sibling : siblings) |
| emit sibling->virtualGeometryChanged(sibling->virtualGeometry()); |
| } |
| } |
| |
| void QScreenPrivate::setPlatformScreen(QPlatformScreen *screen) |
| { |
| Q_Q(QScreen); |
| platformScreen = screen; |
| platformScreen->d_func()->screen = q; |
| orientation = platformScreen->orientation(); |
| |
| logicalDpi = QPlatformScreen::overrideDpi(platformScreen->logicalDpi()); |
| |
| refreshRate = platformScreen->refreshRate(); |
| // safeguard ourselves against buggy platform behavior... |
| if (refreshRate < 1.0) |
| refreshRate = 60.0; |
| |
| updatePrimaryOrientation(); |
| |
| filteredOrientation = orientation; |
| if (filteredOrientation == Qt::PrimaryOrientation) |
| filteredOrientation = primaryOrientation; |
| |
| updateHighDpi(); |
| } |
| |
| |
| /*! |
| Destroys the screen. |
| */ |
| QScreen::~QScreen() |
| { |
| // Remove screen |
| const bool wasPrimary = QGuiApplication::primaryScreen() == this; |
| QGuiApplicationPrivate::screen_list.removeOne(this); |
| QGuiApplicationPrivate::resetCachedDevicePixelRatio(); |
| |
| if (!qGuiApp) |
| return; |
| |
| QScreen *newPrimaryScreen = QGuiApplication::primaryScreen(); |
| if (wasPrimary && newPrimaryScreen) |
| emit qGuiApp->primaryScreenChanged(newPrimaryScreen); |
| |
| // Allow clients to manage windows that are affected by the screen going |
| // away, before we fall back to moving them to the primary screen. |
| emit qApp->screenRemoved(this); |
| |
| if (QGuiApplication::closingDown()) |
| return; |
| |
| bool movingFromVirtualSibling = newPrimaryScreen |
| && newPrimaryScreen->handle()->virtualSiblings().contains(handle()); |
| |
| // Move any leftover windows to the primary screen |
| const auto allWindows = QGuiApplication::allWindows(); |
| for (QWindow *window : allWindows) { |
| if (!window->isTopLevel() || window->screen() != this) |
| continue; |
| |
| const bool wasVisible = window->isVisible(); |
| window->setScreen(newPrimaryScreen); |
| |
| // Re-show window if moved from a virtual sibling screen. Otherwise |
| // leave it up to the application developer to show the window. |
| if (movingFromVirtualSibling) |
| window->setVisible(wasVisible); |
| } |
| } |
| |
| /*! |
| Get the platform screen handle. |
| |
| \sa {Qt Platform Abstraction}{Qt Platform Abstraction (QPA)} |
| */ |
| QPlatformScreen *QScreen::handle() const |
| { |
| Q_D(const QScreen); |
| return d->platformScreen; |
| } |
| |
| /*! |
| \property QScreen::name |
| \brief a user presentable string representing the screen |
| |
| For example, on X11 these correspond to the XRandr screen names, |
| typically "VGA1", "HDMI1", etc. |
| */ |
| QString QScreen::name() const |
| { |
| Q_D(const QScreen); |
| return d->platformScreen->name(); |
| } |
| |
| /*! |
| \property QScreen::manufacturer |
| \brief the manufacturer of the screen |
| |
| \since 5.9 |
| */ |
| QString QScreen::manufacturer() const |
| { |
| Q_D(const QScreen); |
| return d->platformScreen->manufacturer(); |
| } |
| |
| /*! |
| \property QScreen::model |
| \brief the model of the screen |
| |
| \since 5.9 |
| */ |
| QString QScreen::model() const |
| { |
| Q_D(const QScreen); |
| return d->platformScreen->model(); |
| } |
| |
| /*! |
| \property QScreen::serialNumber |
| \brief the serial number of the screen |
| |
| \since 5.9 |
| */ |
| QString QScreen::serialNumber() const |
| { |
| Q_D(const QScreen); |
| return d->platformScreen->serialNumber(); |
| } |
| |
| /*! |
| \property QScreen::depth |
| \brief the color depth of the screen |
| */ |
| int QScreen::depth() const |
| { |
| Q_D(const QScreen); |
| return d->platformScreen->depth(); |
| } |
| |
| /*! |
| \property QScreen::size |
| \brief the pixel resolution of the screen |
| */ |
| QSize QScreen::size() const |
| { |
| Q_D(const QScreen); |
| return d->geometry.size(); |
| } |
| |
| /*! |
| \property QScreen::physicalDotsPerInchX |
| \brief the number of physical dots or pixels per inch in the horizontal direction |
| |
| This value represents the actual horizontal pixel density on the screen's display. |
| Depending on what information the underlying system provides the value might not be |
| entirely accurate. |
| |
| \sa physicalDotsPerInchY() |
| */ |
| qreal QScreen::physicalDotsPerInchX() const |
| { |
| return size().width() / physicalSize().width() * qreal(25.4); |
| } |
| |
| /*! |
| \property QScreen::physicalDotsPerInchY |
| \brief the number of physical dots or pixels per inch in the vertical direction |
| |
| This value represents the actual vertical pixel density on the screen's display. |
| Depending on what information the underlying system provides the value might not be |
| entirely accurate. |
| |
| \sa physicalDotsPerInchX() |
| */ |
| qreal QScreen::physicalDotsPerInchY() const |
| { |
| return size().height() / physicalSize().height() * qreal(25.4); |
| } |
| |
| /*! |
| \property QScreen::physicalDotsPerInch |
| \brief the number of physical dots or pixels per inch |
| |
| This value represents the pixel density on the screen's display. |
| Depending on what information the underlying system provides the value might not be |
| entirely accurate. |
| |
| This is a convenience property that's simply the average of the physicalDotsPerInchX |
| and physicalDotsPerInchY properties. |
| |
| \sa physicalDotsPerInchX() |
| \sa physicalDotsPerInchY() |
| */ |
| qreal QScreen::physicalDotsPerInch() const |
| { |
| QSize sz = size(); |
| QSizeF psz = physicalSize(); |
| return ((sz.height() / psz.height()) + (sz.width() / psz.width())) * qreal(25.4 * 0.5); |
| } |
| |
| /*! |
| \property QScreen::logicalDotsPerInchX |
| \brief the number of logical dots or pixels per inch in the horizontal direction |
| |
| This value is used to convert font point sizes to pixel sizes. |
| |
| \sa logicalDotsPerInchY() |
| */ |
| qreal QScreen::logicalDotsPerInchX() const |
| { |
| Q_D(const QScreen); |
| if (QHighDpiScaling::isActive()) |
| return QHighDpiScaling::logicalDpi(this).first; |
| return d->logicalDpi.first; |
| } |
| |
| /*! |
| \property QScreen::logicalDotsPerInchY |
| \brief the number of logical dots or pixels per inch in the vertical direction |
| |
| This value is used to convert font point sizes to pixel sizes. |
| |
| \sa logicalDotsPerInchX() |
| */ |
| qreal QScreen::logicalDotsPerInchY() const |
| { |
| Q_D(const QScreen); |
| if (QHighDpiScaling::isActive()) |
| return QHighDpiScaling::logicalDpi(this).second; |
| return d->logicalDpi.second; |
| } |
| |
| /*! |
| \property QScreen::logicalDotsPerInch |
| \brief the number of logical dots or pixels per inch |
| |
| This value can be used to convert font point sizes to pixel sizes. |
| |
| This is a convenience property that's simply the average of the logicalDotsPerInchX |
| and logicalDotsPerInchY properties. |
| |
| \sa logicalDotsPerInchX() |
| \sa logicalDotsPerInchY() |
| */ |
| qreal QScreen::logicalDotsPerInch() const |
| { |
| Q_D(const QScreen); |
| QDpi dpi = QHighDpiScaling::isActive() ? QHighDpiScaling::logicalDpi(this) : d->logicalDpi; |
| return (dpi.first + dpi.second) * qreal(0.5); |
| } |
| |
| /*! |
| \property QScreen::devicePixelRatio |
| \brief the screen's ratio between physical pixels and device-independent pixels |
| \since 5.5 |
| |
| Returns the ratio between physical pixels and device-independent pixels for the screen. |
| |
| Common values are 1.0 on normal displays and 2.0 on "retina" displays. |
| Higher values are also possible. |
| |
| \sa QWindow::devicePixelRatio(), QGuiApplication::devicePixelRatio() |
| */ |
| qreal QScreen::devicePixelRatio() const |
| { |
| Q_D(const QScreen); |
| return d->platformScreen->devicePixelRatio() * QHighDpiScaling::factor(this); |
| } |
| |
| /*! |
| \property QScreen::physicalSize |
| \brief the screen's physical size (in millimeters) |
| |
| The physical size represents the actual physical dimensions of the |
| screen's display. |
| |
| Depending on what information the underlying system provides the value |
| might not be entirely accurate. |
| */ |
| QSizeF QScreen::physicalSize() const |
| { |
| Q_D(const QScreen); |
| return d->platformScreen->physicalSize(); |
| } |
| |
| /*! |
| \property QScreen::availableSize |
| \brief the screen's available size in pixels |
| |
| The available size is the size excluding window manager reserved areas |
| such as task bars and system menus. |
| */ |
| QSize QScreen::availableSize() const |
| { |
| Q_D(const QScreen); |
| return d->availableGeometry.size(); |
| } |
| |
| /*! |
| \property QScreen::geometry |
| \brief the screen's geometry in pixels |
| |
| As an example this might return QRect(0, 0, 1280, 1024), or in a |
| virtual desktop setting QRect(1280, 0, 1280, 1024). |
| */ |
| QRect QScreen::geometry() const |
| { |
| Q_D(const QScreen); |
| return d->geometry; |
| } |
| |
| /*! |
| \property QScreen::availableGeometry |
| \brief the screen's available geometry in pixels |
| |
| The available geometry is the geometry excluding window manager reserved areas |
| such as task bars and system menus. |
| |
| Note, on X11 this will return the true available geometry only on systems with one monitor and |
| if window manager has set _NET_WORKAREA atom. In all other cases this is equal to geometry(). |
| This is a limitation in X11 window manager specification. |
| */ |
| QRect QScreen::availableGeometry() const |
| { |
| Q_D(const QScreen); |
| return d->availableGeometry; |
| } |
| |
| /*! |
| Get the screen's virtual siblings. |
| |
| The virtual siblings are the screen instances sharing the same virtual desktop. |
| They share a common coordinate system, and windows can freely be moved or |
| positioned across them without having to be re-created. |
| */ |
| QList<QScreen *> QScreen::virtualSiblings() const |
| { |
| Q_D(const QScreen); |
| const QList<QPlatformScreen *> platformScreens = d->platformScreen->virtualSiblings(); |
| QList<QScreen *> screens; |
| screens.reserve(platformScreens.count()); |
| for (QPlatformScreen *platformScreen : platformScreens) |
| screens << platformScreen->screen(); |
| return screens; |
| } |
| |
| /*! |
| \property QScreen::virtualSize |
| \brief the pixel size of the virtual desktop to which this screen belongs |
| |
| Returns the pixel size of the virtual desktop corresponding to this screen. |
| |
| This is the combined size of the virtual siblings' individual geometries. |
| |
| \sa virtualSiblings() |
| */ |
| QSize QScreen::virtualSize() const |
| { |
| return virtualGeometry().size(); |
| } |
| |
| /*! |
| \property QScreen::virtualGeometry |
| \brief the pixel geometry of the virtual desktop to which this screen belongs |
| |
| Returns the pixel geometry of the virtual desktop corresponding to this screen. |
| |
| This is the union of the virtual siblings' individual geometries. |
| |
| \sa virtualSiblings() |
| */ |
| QRect QScreen::virtualGeometry() const |
| { |
| QRect result; |
| const auto screens = virtualSiblings(); |
| for (QScreen *screen : screens) |
| result |= screen->geometry(); |
| return result; |
| } |
| |
| /*! |
| \property QScreen::availableVirtualSize |
| \brief the available size of the virtual desktop to which this screen belongs |
| |
| Returns the available pixel size of the virtual desktop corresponding to this screen. |
| |
| This is the combined size of the virtual siblings' individual available geometries. |
| |
| \sa availableSize(), virtualSiblings() |
| */ |
| QSize QScreen::availableVirtualSize() const |
| { |
| return availableVirtualGeometry().size(); |
| } |
| |
| /*! |
| \property QScreen::availableVirtualGeometry |
| \brief the available geometry of the virtual desktop to which this screen belongs |
| |
| Returns the available geometry of the virtual desktop corresponding to this screen. |
| |
| This is the union of the virtual siblings' individual available geometries. |
| |
| \sa availableGeometry(), virtualSiblings() |
| */ |
| QRect QScreen::availableVirtualGeometry() const |
| { |
| QRect result; |
| const auto screens = virtualSiblings(); |
| for (QScreen *screen : screens) |
| result |= screen->availableGeometry(); |
| return result; |
| } |
| |
| /*! |
| Sets the orientations that the application is interested in receiving |
| updates for in conjunction with this screen. |
| |
| For example, to receive orientation() updates and thus have |
| orientationChanged() signals being emitted for LandscapeOrientation and |
| InvertedLandscapeOrientation, call setOrientationUpdateMask() with |
| \a{mask} set to Qt::LandscapeOrientation | Qt::InvertedLandscapeOrientation. |
| |
| The default, 0, means no orientationChanged() signals are fired. |
| */ |
| void QScreen::setOrientationUpdateMask(Qt::ScreenOrientations mask) |
| { |
| Q_D(QScreen); |
| d->orientationUpdateMask = mask; |
| d->platformScreen->setOrientationUpdateMask(mask); |
| QGuiApplicationPrivate::updateFilteredScreenOrientation(this); |
| } |
| |
| /*! |
| Returns the currently set orientation update mask. |
| |
| \sa setOrientationUpdateMask() |
| */ |
| Qt::ScreenOrientations QScreen::orientationUpdateMask() const |
| { |
| Q_D(const QScreen); |
| return d->orientationUpdateMask; |
| } |
| |
| /*! |
| \property QScreen::orientation |
| \brief the screen orientation |
| |
| The screen orientation represents the physical orientation |
| of the display. For example, the screen orientation of a mobile device |
| will change based on how it is being held. A change to the orientation |
| might or might not trigger a change to the primary orientation of the screen. |
| |
| Changes to this property will be filtered by orientationUpdateMask(), |
| so in order to receive orientation updates the application must first |
| call setOrientationUpdateMask() with a mask of the orientations it wants |
| to receive. |
| |
| Qt::PrimaryOrientation is never returned. |
| |
| \sa primaryOrientation() |
| */ |
| Qt::ScreenOrientation QScreen::orientation() const |
| { |
| Q_D(const QScreen); |
| return d->filteredOrientation; |
| } |
| |
| /*! |
| \property QScreen::refreshRate |
| \brief the approximate vertical refresh rate of the screen in Hz |
| */ |
| qreal QScreen::refreshRate() const |
| { |
| Q_D(const QScreen); |
| return d->refreshRate; |
| } |
| |
| /*! |
| \property QScreen::primaryOrientation |
| \brief the primary screen orientation |
| |
| The primary screen orientation is Qt::LandscapeOrientation |
| if the screen geometry's width is greater than or equal to its |
| height, or Qt::PortraitOrientation otherwise. This property might |
| change when the screen orientation was changed (i.e. when the |
| display is rotated). |
| The behavior is however platform dependent and can often be specified in |
| an application manifest file. |
| |
| */ |
| Qt::ScreenOrientation QScreen::primaryOrientation() const |
| { |
| Q_D(const QScreen); |
| return d->primaryOrientation; |
| } |
| |
| /*! |
| \property QScreen::nativeOrientation |
| \brief the native screen orientation |
| \since 5.2 |
| |
| The native orientation of the screen is the orientation where the logo |
| sticker of the device appears the right way up, or Qt::PrimaryOrientation |
| if the platform does not support this functionality. |
| |
| The native orientation is a property of the hardware, and does not change. |
| */ |
| Qt::ScreenOrientation QScreen::nativeOrientation() const |
| { |
| Q_D(const QScreen); |
| return d->platformScreen->nativeOrientation(); |
| } |
| |
| /*! |
| Convenience function to compute the angle of rotation to get from |
| rotation \a a to rotation \a b. |
| |
| The result will be 0, 90, 180, or 270. |
| |
| Qt::PrimaryOrientation is interpreted as the screen's primaryOrientation(). |
| */ |
| int QScreen::angleBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b) const |
| { |
| if (a == Qt::PrimaryOrientation) |
| a = primaryOrientation(); |
| |
| if (b == Qt::PrimaryOrientation) |
| b = primaryOrientation(); |
| |
| return QPlatformScreen::angleBetween(a, b); |
| } |
| |
| /*! |
| Convenience function to compute a transform that maps from the coordinate system |
| defined by orientation \a a into the coordinate system defined by orientation |
| \a b and target dimensions \a target. |
| |
| Example, \a a is Qt::Landscape, \a b is Qt::Portrait, and \a target is QRect(0, 0, w, h) |
| the resulting transform will be such that the point QPoint(0, 0) is mapped to QPoint(0, w), |
| and QPoint(h, w) is mapped to QPoint(0, h). Thus, the landscape coordinate system QRect(0, 0, h, w) |
| is mapped (with a 90 degree rotation) into the portrait coordinate system QRect(0, 0, w, h). |
| |
| Qt::PrimaryOrientation is interpreted as the screen's primaryOrientation(). |
| */ |
| QTransform QScreen::transformBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b, const QRect &target) const |
| { |
| if (a == Qt::PrimaryOrientation) |
| a = primaryOrientation(); |
| |
| if (b == Qt::PrimaryOrientation) |
| b = primaryOrientation(); |
| |
| return QPlatformScreen::transformBetween(a, b, target); |
| } |
| |
| /*! |
| Maps the rect between two screen orientations. |
| |
| This will flip the x and y dimensions of the rectangle \a{rect} if the orientation \a{a} is |
| Qt::PortraitOrientation or Qt::InvertedPortraitOrientation and orientation \a{b} is |
| Qt::LandscapeOrientation or Qt::InvertedLandscapeOrientation, or vice versa. |
| |
| Qt::PrimaryOrientation is interpreted as the screen's primaryOrientation(). |
| */ |
| QRect QScreen::mapBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b, const QRect &rect) const |
| { |
| if (a == Qt::PrimaryOrientation) |
| a = primaryOrientation(); |
| |
| if (b == Qt::PrimaryOrientation) |
| b = primaryOrientation(); |
| |
| return QPlatformScreen::mapBetween(a, b, rect); |
| } |
| |
| /*! |
| Convenience function that returns \c true if \a o is either portrait or inverted portrait; |
| otherwise returns \c false. |
| |
| Qt::PrimaryOrientation is interpreted as the screen's primaryOrientation(). |
| */ |
| bool QScreen::isPortrait(Qt::ScreenOrientation o) const |
| { |
| return o == Qt::PortraitOrientation || o == Qt::InvertedPortraitOrientation |
| || (o == Qt::PrimaryOrientation && primaryOrientation() == Qt::PortraitOrientation); |
| } |
| |
| /*! |
| Convenience function that returns \c true if \a o is either landscape or inverted landscape; |
| otherwise returns \c false. |
| |
| Qt::PrimaryOrientation is interpreted as the screen's primaryOrientation(). |
| */ |
| bool QScreen::isLandscape(Qt::ScreenOrientation o) const |
| { |
| return o == Qt::LandscapeOrientation || o == Qt::InvertedLandscapeOrientation |
| || (o == Qt::PrimaryOrientation && primaryOrientation() == Qt::LandscapeOrientation); |
| } |
| |
| /*! |
| \fn void QScreen::orientationChanged(Qt::ScreenOrientation orientation) |
| |
| This signal is emitted when the orientation of the screen |
| changes with \a orientation as an argument. |
| |
| \sa orientation() |
| */ |
| |
| /*! |
| \fn void QScreen::primaryOrientationChanged(Qt::ScreenOrientation orientation) |
| |
| This signal is emitted when the primary orientation of the screen |
| changes with \a orientation as an argument. |
| |
| \sa primaryOrientation() |
| */ |
| |
| void QScreenPrivate::updatePrimaryOrientation() |
| { |
| primaryOrientation = geometry.width() >= geometry.height() ? Qt::LandscapeOrientation : Qt::PortraitOrientation; |
| } |
| |
| /*! |
| Returns the screen at \a point within the set of \l QScreen::virtualSiblings(), |
| or \c nullptr if outside of any screen. |
| |
| The \a point is in relation to the virtualGeometry() of each set of virtual |
| siblings. |
| |
| \since 5.15 |
| */ |
| QScreen *QScreen::virtualSiblingAt(QPoint point) |
| { |
| const auto &siblings = virtualSiblings(); |
| for (QScreen *sibling : siblings) { |
| if (sibling->geometry().contains(point)) |
| return sibling; |
| } |
| return nullptr; |
| } |
| |
| /*! |
| Creates and returns a pixmap constructed by grabbing the contents |
| of the given \a window restricted by QRect(\a x, \a y, \a width, |
| \a height). |
| |
| The arguments (\a{x}, \a{y}) specify the offset in the window, |
| whereas (\a{width}, \a{height}) specify the area to be copied. If |
| \a width is negative, the function copies everything to the right |
| border of the window. If \a height is negative, the function |
| copies everything to the bottom of the window. |
| |
| The offset and size arguments are specified in device independent |
| pixels. The returned pixmap may be larger than the requested size |
| when grabbing from a high-DPI screen. Call QPixmap::devicePixelRatio() |
| to determine if this is the case. |
| |
| The window system identifier (\c WId) can be retrieved using the |
| QWidget::winId() function. The rationale for using a window |
| identifier and not a QWidget, is to enable grabbing of windows |
| that are not part of the application, window system frames, and so |
| on. |
| |
| \warning Grabbing windows that are not part of the application is |
| not supported on systems such as iOS, where sandboxing/security |
| prevents reading pixels of windows not owned by the application. |
| |
| The grabWindow() function grabs pixels from the screen, not from |
| the window, i.e. if there is another window partially or entirely |
| over the one you grab, you get pixels from the overlying window, |
| too. The mouse cursor is generally not grabbed. |
| |
| Note on X11 that if the given \a window doesn't have the same depth |
| as the root window, and another window partially or entirely |
| obscures the one you grab, you will \e not get pixels from the |
| overlying window. The contents of the obscured areas in the |
| pixmap will be undefined and uninitialized. |
| |
| On Windows Vista and above grabbing a layered window, which is |
| created by setting the Qt::WA_TranslucentBackground attribute, will |
| not work. Instead grabbing the desktop widget should work. |
| |
| \warning In general, grabbing an area outside the screen is not |
| safe. This depends on the underlying window system. |
| */ |
| |
| QPixmap QScreen::grabWindow(WId window, int x, int y, int width, int height) |
| { |
| const QPlatformScreen *platformScreen = handle(); |
| if (!platformScreen) { |
| qWarning("invoked with handle==0"); |
| return QPixmap(); |
| } |
| const qreal factor = QHighDpiScaling::factor(this); |
| if (qFuzzyCompare(factor, 1)) |
| return platformScreen->grabWindow(window, x, y, width, height); |
| |
| const QPoint nativePos = QHighDpi::toNative(QPoint(x, y), factor); |
| QSize nativeSize(width, height); |
| if (nativeSize.isValid()) |
| nativeSize = QHighDpi::toNative(nativeSize, factor); |
| QPixmap result = |
| platformScreen->grabWindow(window, nativePos.x(), nativePos.y(), |
| nativeSize.width(), nativeSize.height()); |
| result.setDevicePixelRatio(result.devicePixelRatio() * factor); |
| return result; |
| } |
| |
| #ifndef QT_NO_DEBUG_STREAM |
| |
| static inline void formatRect(QDebug &debug, const QRect r) |
| { |
| debug << r.width() << 'x' << r.height() |
| << Qt::forcesign << r.x() << r.y() << Qt::noforcesign; |
| } |
| |
| Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QScreen *screen) |
| { |
| const QDebugStateSaver saver(debug); |
| debug.nospace(); |
| debug << "QScreen(" << (const void *)screen; |
| if (screen) { |
| debug << ", name=" << screen->name(); |
| if (debug.verbosity() > 2) { |
| if (screen == QGuiApplication::primaryScreen()) |
| debug << ", primary"; |
| debug << ", geometry="; |
| formatRect(debug, screen->geometry()); |
| debug << ", available="; |
| formatRect(debug, screen->availableGeometry()); |
| debug << ", logical DPI=" << screen->logicalDotsPerInchX() |
| << ',' << screen->logicalDotsPerInchY() |
| << ", physical DPI=" << screen->physicalDotsPerInchX() |
| << ',' << screen->physicalDotsPerInchY() |
| << ", devicePixelRatio=" << screen->devicePixelRatio() |
| << ", orientation=" << screen->orientation() |
| << ", physical size=" << screen->physicalSize().width() |
| << 'x' << screen->physicalSize().height() << "mm"; |
| } |
| } |
| debug << ')'; |
| return debug; |
| } |
| #endif // !QT_NO_DEBUG_STREAM |
| |
| QT_END_NAMESPACE |