diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/qml/qqmlengine.cpp | 14 | ||||
-rw-r--r-- | src/quick/items/qquickscreen.cpp | 195 | ||||
-rw-r--r-- | src/quick/items/qquickscreen_p.h | 48 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 22 | ||||
-rw-r--r-- | src/quick/items/qquickwindowmodule.cpp | 25 | ||||
-rw-r--r-- | src/quick/items/qquickwindowmodule_p.h | 5 | ||||
-rw-r--r-- | src/quick/util/qquickapplication.cpp | 34 | ||||
-rw-r--r-- | src/quick/util/qquickapplication_p.h | 9 |
8 files changed, 261 insertions, 91 deletions
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 01f1f93b81..daa12fae26 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -554,6 +554,18 @@ The following functions are also on the Qt object. \li This read-only property can be used to determine whether or not the platform supports multiple windows. Some embedded platforms do not support multiple windows, for example. + + \row + \li \c application.screens + \li An array containing the descriptions of all connected screens. The + elements of the array are objects with the same properties as the + \l{Screen} attached object. In practice the array corresponds to the screen + list returned by QGuiApplication::screens(). In addition to examining + properties like name, width, height, etc., the array elements can also be + assigned to the targetScreen property of Window items, thus serving as an + alternative to the C++ side's QWindow::setScreen(). This property has been + added in Qt 5.9. + \endtable The object also has one signal, aboutToQuit(), which is the same as \l QCoreApplication::aboutToQuit(). @@ -570,6 +582,8 @@ The following functions are also on the Qt object. \li application.layoutDirection \li application.font \endlist + + \sa Screen, Window, Window.targetScreen */ /*! diff --git a/src/quick/items/qquickscreen.cpp b/src/quick/items/qquickscreen.cpp index 5d01a2af9d..9347b55c70 100644 --- a/src/quick/items/qquickscreen.cpp +++ b/src/quick/items/qquickscreen.cpp @@ -207,100 +207,181 @@ QT_BEGIN_NAMESPACE By default it is set to the value of the QScreen that the window uses. */ -QQuickScreenAttached::QQuickScreenAttached(QObject* attachee) - : QObject(attachee) - , m_screen(NULL) - , m_window(NULL) - , m_updateMask(0) - , m_updateMaskSet(false) +QQuickScreenInfo::QQuickScreenInfo(QObject *parent) + : QObject(parent), + m_screen(nullptr) { - m_attachee = qobject_cast<QQuickItem*>(attachee); - - if (m_attachee) { - QQuickItemPrivate::get(m_attachee)->extra.value().screenAttached = this; - - if (m_attachee->window()) //It might not be assigned to a window yet - windowChanged(m_attachee->window()); - } else { - QQuickWindow *window = qobject_cast<QQuickWindow*>(attachee); - if (window) - windowChanged(window); - } - - if (!m_screen) - screenChanged(QGuiApplication::primaryScreen()); } -QString QQuickScreenAttached::name() const +QString QQuickScreenInfo::name() const { if (!m_screen) return QString(); return m_screen->name(); } -int QQuickScreenAttached::width() const +int QQuickScreenInfo::width() const { if (!m_screen) return 0; return m_screen->size().width(); } -int QQuickScreenAttached::height() const +int QQuickScreenInfo::height() const { if (!m_screen) return 0; return m_screen->size().height(); } -int QQuickScreenAttached::desktopAvailableWidth() const +int QQuickScreenInfo::desktopAvailableWidth() const { if (!m_screen) return 0; return m_screen->availableVirtualSize().width(); } -int QQuickScreenAttached::desktopAvailableHeight() const +int QQuickScreenInfo::desktopAvailableHeight() const { if (!m_screen) return 0; return m_screen->availableVirtualSize().height(); } -qreal QQuickScreenAttached::logicalPixelDensity() const +qreal QQuickScreenInfo::logicalPixelDensity() const { if (!m_screen) return 0.0; return m_screen->logicalDotsPerInch() / 25.4; } -qreal QQuickScreenAttached::pixelDensity() const +qreal QQuickScreenInfo::pixelDensity() const { if (!m_screen) return 0.0; return m_screen->physicalDotsPerInch() / 25.4; } -qreal QQuickScreenAttached::devicePixelRatio() const +qreal QQuickScreenInfo::devicePixelRatio() const { if (!m_screen) return 1.0; return m_screen->devicePixelRatio(); } -Qt::ScreenOrientation QQuickScreenAttached::primaryOrientation() const +Qt::ScreenOrientation QQuickScreenInfo::primaryOrientation() const { if (!m_screen) return Qt::PrimaryOrientation; return m_screen->primaryOrientation(); } -Qt::ScreenOrientation QQuickScreenAttached::orientation() const +Qt::ScreenOrientation QQuickScreenInfo::orientation() const { if (!m_screen) return Qt::PrimaryOrientation; return m_screen->orientation(); } +int QQuickScreenInfo::virtualX() const +{ + if (!m_screen) + return 0; + return m_screen->geometry().topLeft().x(); +} + +int QQuickScreenInfo::virtualY() const +{ + if (!m_screen) + return 0; + return m_screen->geometry().topLeft().y(); +} + +void QQuickScreenInfo::setWrappedScreen(QScreen *screen) +{ + if (screen == m_screen) + return; + + QScreen *oldScreen = m_screen; + m_screen = screen; + + if (oldScreen) + oldScreen->disconnect(this); + + if (!screen) //Don't bother emitting signals, because the new values are garbage anyways + return; + + if (!oldScreen || screen->geometry() != oldScreen->geometry()) { + emit virtualXChanged(); + emit virtualYChanged(); + } + if (!oldScreen || screen->size() != oldScreen->size()) { + emit widthChanged(); + emit heightChanged(); + } + if (!oldScreen || screen->name() != oldScreen->name()) + emit nameChanged(); + if (!oldScreen || screen->orientation() != oldScreen->orientation()) + emit orientationChanged(); + if (!oldScreen || screen->primaryOrientation() != oldScreen->primaryOrientation()) + emit primaryOrientationChanged(); + if (!oldScreen || screen->availableVirtualGeometry() != oldScreen->availableVirtualGeometry()) + emit desktopGeometryChanged(); + if (!oldScreen || screen->logicalDotsPerInch() != oldScreen->logicalDotsPerInch()) + emit logicalPixelDensityChanged(); + if (!oldScreen || screen->physicalDotsPerInch() != oldScreen->physicalDotsPerInch()) + emit pixelDensityChanged(); + if (!oldScreen || screen->devicePixelRatio() != oldScreen->devicePixelRatio()) + emit devicePixelRatioChanged(); + + connect(screen, SIGNAL(geometryChanged(QRect)), + this, SIGNAL(widthChanged())); + connect(screen, SIGNAL(geometryChanged(QRect)), + this, SIGNAL(heightChanged())); + connect(screen, SIGNAL(geometryChanged(QRect)), + this, SIGNAL(virtualXChanged())); + connect(screen, SIGNAL(geometryChanged(QRect)), + this, SIGNAL(virtualYChanged())); + connect(screen, SIGNAL(orientationChanged(Qt::ScreenOrientation)), + this, SIGNAL(orientationChanged())); + connect(screen, SIGNAL(primaryOrientationChanged(Qt::ScreenOrientation)), + this, SIGNAL(primaryOrientationChanged())); + connect(screen, SIGNAL(virtualGeometryChanged(QRect)), + this, SIGNAL(desktopGeometryChanged())); + connect(screen, SIGNAL(logicalDotsPerInchChanged(qreal)), + this, SIGNAL(logicalPixelDensityChanged())); + connect(screen, SIGNAL(physicalDotsPerInchChanged(qreal)), + this, SIGNAL(pixelDensityChanged())); +} + +QScreen *QQuickScreenInfo::wrappedScreen() const +{ + return m_screen; +} + +QQuickScreenAttached::QQuickScreenAttached(QObject* attachee) + : QQuickScreenInfo(attachee) + , m_window(NULL) + , m_updateMask(0) + , m_updateMaskSet(false) +{ + m_attachee = qobject_cast<QQuickItem*>(attachee); + + if (m_attachee) { + QQuickItemPrivate::get(m_attachee)->extra.value().screenAttached = this; + + if (m_attachee->window()) //It might not be assigned to a window yet + windowChanged(m_attachee->window()); + } else { + QQuickWindow *window = qobject_cast<QQuickWindow*>(attachee); + if (window) + windowChanged(window); + } + + if (!m_screen) + screenChanged(QGuiApplication::primaryScreen()); +} + Qt::ScreenOrientations QQuickScreenAttached::orientationUpdateMask() const { return m_updateMask; @@ -341,55 +422,15 @@ void QQuickScreenAttached::screenChanged(QScreen *screen) { //qDebug() << "QQuickScreenAttached::screenChanged" << (screen ? screen->name() : QString::fromLatin1("null")); if (screen != m_screen) { - QScreen* oldScreen = m_screen; - m_screen = screen; - - if (oldScreen) - oldScreen->disconnect(this); - - if (!screen) - return; //Don't bother emitting signals, because the new values are garbage anyways - + setWrappedScreen(screen); + if (!m_screen) + return; if (m_updateMaskSet) { - screen->setOrientationUpdateMask(m_updateMask); - } else if (m_updateMask != screen->orientationUpdateMask()) { - m_updateMask = screen->orientationUpdateMask(); + m_screen->setOrientationUpdateMask(m_updateMask); + } else if (m_updateMask != m_screen->orientationUpdateMask()) { + m_updateMask = m_screen->orientationUpdateMask(); emit orientationUpdateMaskChanged(); } - - if (!oldScreen || screen->size() != oldScreen->size()) { - emit widthChanged(); - emit heightChanged(); - } - if (!oldScreen || screen->name() != oldScreen->name()) - emit nameChanged(); - if (!oldScreen || screen->orientation() != oldScreen->orientation()) - emit orientationChanged(); - if (!oldScreen || screen->primaryOrientation() != oldScreen->primaryOrientation()) - emit primaryOrientationChanged(); - if (!oldScreen || screen->availableVirtualGeometry() != oldScreen->availableVirtualGeometry()) - emit desktopGeometryChanged(); - if (!oldScreen || screen->logicalDotsPerInch() != oldScreen->logicalDotsPerInch()) - emit logicalPixelDensityChanged(); - if (!oldScreen || screen->physicalDotsPerInch() != oldScreen->physicalDotsPerInch()) - emit pixelDensityChanged(); - if (!oldScreen || screen->devicePixelRatio() != oldScreen->devicePixelRatio()) - emit devicePixelRatioChanged(); - - connect(screen, SIGNAL(geometryChanged(QRect)), - this, SIGNAL(widthChanged())); - connect(screen, SIGNAL(geometryChanged(QRect)), - this, SIGNAL(heightChanged())); - connect(screen, SIGNAL(orientationChanged(Qt::ScreenOrientation)), - this, SIGNAL(orientationChanged())); - connect(screen, SIGNAL(primaryOrientationChanged(Qt::ScreenOrientation)), - this, SIGNAL(primaryOrientationChanged())); - connect(screen, SIGNAL(virtualGeometryChanged(QRect)), - this, SIGNAL(desktopGeometryChanged())); - connect(screen, SIGNAL(logicalDotsPerInchChanged(qreal)), - this, SIGNAL(logicalPixelDensityChanged())); - connect(screen, SIGNAL(physicalDotsPerInchChanged(qreal)), - this, SIGNAL(pixelDensityChanged())); } } diff --git a/src/quick/items/qquickscreen_p.h b/src/quick/items/qquickscreen_p.h index 06d9a06070..06efb3ab45 100644 --- a/src/quick/items/qquickscreen_p.h +++ b/src/quick/items/qquickscreen_p.h @@ -63,10 +63,10 @@ class QQuickItem; class QQuickWindow; class QScreen; -class Q_AUTOTEST_EXPORT QQuickScreenAttached : public QObject + +class Q_AUTOTEST_EXPORT QQuickScreenInfo : public QObject { Q_OBJECT - Q_PROPERTY(QString name READ name NOTIFY nameChanged) Q_PROPERTY(int width READ width NOTIFY widthChanged) Q_PROPERTY(int height READ height NOTIFY heightChanged) @@ -79,11 +79,12 @@ class Q_AUTOTEST_EXPORT QQuickScreenAttached : public QObject Q_PROPERTY(Qt::ScreenOrientation primaryOrientation READ primaryOrientation NOTIFY primaryOrientationChanged) // TODO Qt 6 Remove this orientation -> incomplete device orientation -> better use OrientationSensor Q_PROPERTY(Qt::ScreenOrientation orientation READ orientation NOTIFY orientationChanged) - Q_PROPERTY(Qt::ScreenOrientations orientationUpdateMask READ orientationUpdateMask - WRITE setOrientationUpdateMask NOTIFY orientationUpdateMaskChanged) + + Q_PROPERTY(int virtualX READ virtualX NOTIFY virtualXChanged REVISION 1) + Q_PROPERTY(int virtualY READ virtualY NOTIFY virtualYChanged REVISION 1) public: - QQuickScreenAttached(QObject* attachee); + QQuickScreenInfo(QObject *parent = nullptr); QString name() const; int width() const; @@ -95,13 +96,11 @@ public: qreal devicePixelRatio() const; Qt::ScreenOrientation primaryOrientation() const; Qt::ScreenOrientation orientation() const; - Qt::ScreenOrientations orientationUpdateMask() const; - void setOrientationUpdateMask(Qt::ScreenOrientations mask); + int virtualX() const; + int virtualY() const; - //Treats int as Qt::ScreenOrientation, due to QTBUG-20639 - Q_INVOKABLE int angleBetween(int a, int b); - - void windowChanged(QQuickWindow*); + void setWrappedScreen(QScreen *screen); + QScreen *wrappedScreen() const; Q_SIGNALS: void nameChanged(); @@ -113,13 +112,37 @@ Q_SIGNALS: void devicePixelRatioChanged(); void primaryOrientationChanged(); void orientationChanged(); + Q_REVISION(1) void virtualXChanged(); + Q_REVISION(1) void virtualYChanged(); + +protected: + QPointer<QScreen> m_screen; +}; + +class Q_AUTOTEST_EXPORT QQuickScreenAttached : public QQuickScreenInfo +{ + Q_OBJECT + Q_PROPERTY(Qt::ScreenOrientations orientationUpdateMask READ orientationUpdateMask + WRITE setOrientationUpdateMask NOTIFY orientationUpdateMaskChanged) + +public: + QQuickScreenAttached(QObject* attachee); + + Qt::ScreenOrientations orientationUpdateMask() const; + void setOrientationUpdateMask(Qt::ScreenOrientations mask); + + //Treats int as Qt::ScreenOrientation, due to QTBUG-20639 + Q_INVOKABLE int angleBetween(int a, int b); + + void windowChanged(QQuickWindow*); + +Q_SIGNALS: void orientationUpdateMaskChanged(); protected Q_SLOTS: void screenChanged(QScreen*); private: - QPointer<QScreen> m_screen; QQuickWindow* m_window; QQuickItem* m_attachee; Qt::ScreenOrientations m_updateMask; @@ -136,5 +159,6 @@ public: QT_END_NAMESPACE QML_DECLARE_TYPEINFO(QQuickScreen, QML_HAS_ATTACHED_PROPERTIES) +QML_DECLARE_TYPE(QQuickScreenInfo) #endif diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 45341643be..dc0bd51a9a 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -4146,6 +4146,28 @@ void QQuickWindow::resetOpenGLState() */ /*! + \qmlproperty variant Window::targetScreen + + Specifies the screen the window should be placed on. Equivalent to + QWindow::setScreen(). + + The value must be an element from the Qt.application.screens array. + + By default the value is null which leads to using the primary screen. + + \note To ensure that the window is associated with the desired screen right + upon the underlying native window's initial creation, make sure this + property is set as early as possible and that the setting of its value is + not deferred. This can be particularly important on embedded platforms + without a windowing system, where only one window per screen is allowed at a + time. + + \since 5.9 + + \sa QWindow::setScreen(), QScreen, Qt.application + */ + +/*! \qmlproperty Item Window::activeFocusItem \since 5.1 diff --git a/src/quick/items/qquickwindowmodule.cpp b/src/quick/items/qquickwindowmodule.cpp index c624d162a9..8ab2cee96f 100644 --- a/src/quick/items/qquickwindowmodule.cpp +++ b/src/quick/items/qquickwindowmodule.cpp @@ -58,6 +58,7 @@ public: : complete(false) , visible(false) , visibility(QQuickWindow::AutomaticVisibility) + , targetScreen(nullptr) { } @@ -65,6 +66,7 @@ public: bool visible; QQuickWindow::Visibility visibility; QV4::PersistentValue rootItemMarker; + QObject *targetScreen; }; QQuickWindowQmlImpl::QQuickWindowQmlImpl(QWindow *parent) @@ -170,6 +172,26 @@ void QQuickWindowQmlImpl::setWindowVisibility() } } +QObject *QQuickWindowQmlImpl::targetScreen() const +{ + Q_D(const QQuickWindowQmlImpl); + return d->targetScreen; +} + +void QQuickWindowQmlImpl::setTargetScreen(QObject *screen) +{ + Q_D(QQuickWindowQmlImpl); + if (d->targetScreen != screen) { + d->targetScreen = screen; + emit targetScreenChanged(); + QQuickScreenInfo *screenWrapper = qobject_cast<QQuickScreenInfo *>(screen); + if (screenWrapper) + setScreen(screenWrapper->wrappedScreen()); + else + setScreen(nullptr); + } +} + void QQuickWindowModule::defineModule() { const char uri[] = "QtQuick.Window"; @@ -181,7 +203,10 @@ void QQuickWindowModule::defineModule() qmlRegisterRevision<QQuickWindow,2>(uri, 2, 2); qmlRegisterType<QQuickWindowQmlImpl>(uri, 2, 1, "Window"); qmlRegisterType<QQuickWindowQmlImpl,1>(uri, 2, 2, "Window"); + qmlRegisterType<QQuickWindowQmlImpl,2>(uri, 2, 3, "Window"); qmlRegisterUncreatableType<QQuickScreen>(uri, 2, 0, "Screen", QStringLiteral("Screen can only be used via the attached property.")); + qmlRegisterUncreatableType<QQuickScreen,1>(uri, 2, 3, "Screen", QStringLiteral("Screen can only be used via the attached property.")); + qmlRegisterUncreatableType<QQuickScreenInfo,2>(uri, 2, 3, "ScreenInfo", QStringLiteral("ScreenInfo can only be used via the attached property.")); } QT_END_NAMESPACE diff --git a/src/quick/items/qquickwindowmodule_p.h b/src/quick/items/qquickwindowmodule_p.h index 8a6bbac412..7ca29880ea 100644 --- a/src/quick/items/qquickwindowmodule_p.h +++ b/src/quick/items/qquickwindowmodule_p.h @@ -67,6 +67,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickWindowQmlImpl : public QQuickWindow, public Q Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged) Q_PROPERTY(Visibility visibility READ visibility WRITE setVisibility NOTIFY visibilityChanged) + Q_PROPERTY(QObject *targetScreen READ targetScreen WRITE setTargetScreen NOTIFY targetScreenChanged REVISION 2) public: QQuickWindowQmlImpl(QWindow *parent = Q_NULLPTR); @@ -74,11 +75,15 @@ public: void setVisible(bool visible); void setVisibility(Visibility visibility); + QObject *targetScreen() const; + void setTargetScreen(QObject *screen); + static QQuickWindowAttached *qmlAttachedProperties(QObject *object); Q_SIGNALS: void visibleChanged(bool arg); void visibilityChanged(QWindow::Visibility visibility); + Q_REVISION(2) void targetScreenChanged(); protected: void classBegin() Q_DECL_OVERRIDE; diff --git a/src/quick/util/qquickapplication.cpp b/src/quick/util/qquickapplication.cpp index 5c26b23ff7..ca4a5bfb56 100644 --- a/src/quick/util/qquickapplication.cpp +++ b/src/quick/util/qquickapplication.cpp @@ -38,7 +38,7 @@ ****************************************************************************/ #include "qquickapplication_p.h" - +#include <private/qquickscreen_p.h> #include <private/qobject_p.h> #include <private/qguiapplication_p.h> #include <qpa/qplatformintegration.h> @@ -63,6 +63,10 @@ QQuickApplication::QQuickApplication(QObject *parent) this, SIGNAL(stateChanged(Qt::ApplicationState))); connect(qApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SIGNAL(activeChanged())); + + connect(qApp, &QGuiApplication::screenAdded, this, &QQuickApplication::updateScreens); + connect(qApp, &QGuiApplication::screenRemoved, this, &QQuickApplication::updateScreens); + updateScreens(); } } @@ -95,4 +99,32 @@ QFont QQuickApplication::font() const return QGuiApplication::font(); } +int screens_count(QQmlListProperty<QQuickScreenInfo> *prop) +{ + return static_cast<QVector<QQuickScreenInfo *> *>(prop->data)->count(); +} + +QQuickScreenInfo *screens_at(QQmlListProperty<QQuickScreenInfo> *prop, int idx) +{ + return static_cast<QVector<QQuickScreenInfo *> *>(prop->data)->at(idx); +} + +QQmlListProperty<QQuickScreenInfo> QQuickApplication::screens() +{ + return QQmlListProperty<QQuickScreenInfo>(this, + const_cast<QVector<QQuickScreenInfo *> *>(&m_screens), &screens_count, &screens_at); +} + +void QQuickApplication::updateScreens() +{ + const QList<QScreen *> screenList = QGuiApplication::screens(); + m_screens.resize(screenList.count()); + for (int i = 0; i < screenList.count(); ++i) { + if (!m_screens[i]) + m_screens[i] = new QQuickScreenInfo(this); + m_screens[i]->setWrappedScreen(screenList[i]); + } + emit screensChanged(); +} + QT_END_NAMESPACE diff --git a/src/quick/util/qquickapplication_p.h b/src/quick/util/qquickapplication_p.h index 091cb094ed..70381553b4 100644 --- a/src/quick/util/qquickapplication_p.h +++ b/src/quick/util/qquickapplication_p.h @@ -56,10 +56,10 @@ #include <qqml.h> #include <QtQml/private/qqmlglobal_p.h> #include <private/qtquickglobal_p.h> +#include "../items/qquickscreen_p.h" QT_BEGIN_NAMESPACE - class Q_AUTOTEST_EXPORT QQuickApplication : public QQmlApplication { Q_OBJECT @@ -68,6 +68,7 @@ class Q_AUTOTEST_EXPORT QQuickApplication : public QQmlApplication Q_PROPERTY(bool supportsMultipleWindows READ supportsMultipleWindows CONSTANT) Q_PROPERTY(Qt::ApplicationState state READ state NOTIFY stateChanged) Q_PROPERTY(QFont font READ font CONSTANT) + Q_PROPERTY(QQmlListProperty<QQuickScreenInfo> screens READ screens NOTIFY screensChanged) public: explicit QQuickApplication(QObject *parent = 0); @@ -77,14 +78,20 @@ public: bool supportsMultipleWindows() const; Qt::ApplicationState state() const; QFont font() const; + QQmlListProperty<QQuickScreenInfo> screens(); Q_SIGNALS: void activeChanged(); void layoutDirectionChanged(); void stateChanged(Qt::ApplicationState state); + void screensChanged(); + +private Q_SLOTS: + void updateScreens(); private: Q_DISABLE_COPY(QQuickApplication) + QVector<QQuickScreenInfo *> m_screens; }; QT_END_NAMESPACE |