From 80653bf4ce8d03f4af2fe8cc2f3751d32bd31d75 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Samuel=20R=C3=B8dal?= Date: Tue, 5 Jun 2012 14:17:24 +0200 Subject: [PATCH] Added QScreen::setOrientationUpdateMask(). It might be too expensive to always have an accelerometer sensor running, so introduce API so that the application has to explictly ask to get the orientation updates it's interested in. Change-Id: Ib7dc5ad8807718409f744ebef53f4476aa05175d Reviewed-by: Ian Monroe Reviewed-by: Sean Harmer Reviewed-by: Gunnar Sletta Reviewed-by: Kevin Ottens --- src/gui/kernel/qguiapplication.cpp | 19 +++++++++++--- src/gui/kernel/qguiapplication_p.h | 1 + src/gui/kernel/qplatformscreen.h | 1 + src/gui/kernel/qplatformscreen_qpa.cpp | 23 +++++++++++++++++ src/gui/kernel/qscreen.cpp | 36 ++++++++++++++++++++++++++- src/gui/kernel/qscreen.h | 3 +++ src/gui/kernel/qscreen_p.h | 11 ++++++-- tests/auto/gui/kernel/qscreen/tst_qscreen.cpp | 13 ++++++++++ 8 files changed, 101 insertions(+), 6 deletions(-) diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index f71e611..3e999be 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1796,6 +1796,20 @@ void QGuiApplicationPrivate::reportScreenOrientationChange(QWindowSystemInterfac QScreen *s = e->screen.data(); s->d_func()->orientation = e->orientation; + updateFilteredScreenOrientation(s); +} + +void QGuiApplicationPrivate::updateFilteredScreenOrientation(QScreen *s) +{ + Qt::ScreenOrientation o = s->d_func()->orientation; + if (o == Qt::PrimaryOrientation) + o = s->primaryOrientation(); + o = Qt::ScreenOrientation(o & s->orientationUpdateMask()); + if (o == Qt::PrimaryOrientation) + return; + if (o == s->d_func()->filteredOrientation) + return; + s->d_func()->filteredOrientation = o; reportScreenOrientationChange(s); } @@ -1820,7 +1834,6 @@ void QGuiApplicationPrivate::reportGeometryChange(QWindowSystemInterfacePrivate: s->d_func()->geometry = e->geometry; Qt::ScreenOrientation primaryOrientation = s->primaryOrientation(); - Qt::ScreenOrientation orientation = s->orientation(); s->d_func()->updatePrimaryOrientation(); emit s->sizeChanged(s->size()); @@ -1834,8 +1847,8 @@ void QGuiApplicationPrivate::reportGeometryChange(QWindowSystemInterfacePrivate: if (s->primaryOrientation() != primaryOrientation) emit s->primaryOrientationChanged(s->primaryOrientation()); - if (s->orientation() != orientation) - reportScreenOrientationChange(s); + if (s->d_func()->orientation == Qt::PrimaryOrientation) + updateFilteredScreenOrientation(s); } void QGuiApplicationPrivate::reportAvailableGeometryChange( diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h index e79c2af..d538c39 100644 --- a/src/gui/kernel/qguiapplication_p.h +++ b/src/gui/kernel/qguiapplication_p.h @@ -112,6 +112,7 @@ public: static void processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e); + static void updateFilteredScreenOrientation(QScreen *screen); static void reportScreenOrientationChange(QScreen *screen); static void reportScreenOrientationChange(QWindowSystemInterfacePrivate::ScreenOrientationEvent *e); static void reportGeometryChange(QWindowSystemInterfacePrivate::ScreenGeometryEvent *e); diff --git a/src/gui/kernel/qplatformscreen.h b/src/gui/kernel/qplatformscreen.h index 4baf0f6..31d459d 100644 --- a/src/gui/kernel/qplatformscreen.h +++ b/src/gui/kernel/qplatformscreen.h @@ -103,6 +103,7 @@ public: virtual Qt::ScreenOrientation nativeOrientation() const; virtual Qt::ScreenOrientation orientation() const; + virtual void setOrientationUpdateMask(Qt::ScreenOrientations mask); virtual QWindow *topLevelAt(const QPoint &point) const; virtual QList virtualSiblings() const; diff --git a/src/gui/kernel/qplatformscreen_qpa.cpp b/src/gui/kernel/qplatformscreen_qpa.cpp index fdb5d32..d946e4f 100644 --- a/src/gui/kernel/qplatformscreen_qpa.cpp +++ b/src/gui/kernel/qplatformscreen_qpa.cpp @@ -195,6 +195,29 @@ Qt::ScreenOrientation QPlatformScreen::orientation() const return Qt::PrimaryOrientation; } +/* + Reimplement this function in subclass to filter out unneeded screen + orientation updates. + + The orientations will anyway be filtered before QScreen::orientationChanged() + is emitted, but the mask can be used by the platform plugin for example to + prevent having to have an accelerometer sensor running all the time, or to + improve the reported values. As an example of the latter, in case of only + Landscape | InvertedLandscape being set in the mask, on a platform that gets + its orientation readings from an accelerometer sensor embedded in a handheld + device, the platform can report transitions between the two even when the + device is held in an orientation that's closer to portrait. + + By default, the orientation update mask is empty, so unless this function + has been called with a non-empty mask the platform does not need to report + any orientation updates through + QWindowSystemInterface::handleScreenOrientationChange(). +*/ +void QPlatformScreen::setOrientationUpdateMask(Qt::ScreenOrientations mask) +{ + Q_UNUSED(mask); +} + QPlatformScreen * QPlatformScreen::platformScreenForWindow(const QWindow *window) { return window->screen()->handle(); diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp index 2e0df43..fe8b15e 100644 --- a/src/gui/kernel/qscreen.cpp +++ b/src/gui/kernel/qscreen.cpp @@ -345,6 +345,35 @@ QRect QScreen::availableVirtualGeometry() const } /*! + 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 the + argument 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); +} + +/*! + 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 @@ -353,6 +382,11 @@ QRect QScreen::availableVirtualGeometry() const will change based on the device is being held, and a desktop display might be rotated so that it's in portrait mode. + 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(), orientationChanged() @@ -360,7 +394,7 @@ QRect QScreen::availableVirtualGeometry() const Qt::ScreenOrientation QScreen::orientation() const { Q_D(const QScreen); - return d->orientation == Qt::PrimaryOrientation ? primaryOrientation() : d->orientation; + return d->filteredOrientation; } /*! diff --git a/src/gui/kernel/qscreen.h b/src/gui/kernel/qscreen.h index 17f3cd3..6c14216 100644 --- a/src/gui/kernel/qscreen.h +++ b/src/gui/kernel/qscreen.h @@ -119,6 +119,9 @@ public: Qt::ScreenOrientation primaryOrientation() const; Qt::ScreenOrientation orientation() const; + Qt::ScreenOrientations orientationUpdateMask() const; + void setOrientationUpdateMask(Qt::ScreenOrientations mask); + int angleBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b) const; QTransform transformBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b, const QRect &target) const; QRect mapBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b, const QRect &rect) const; diff --git a/src/gui/kernel/qscreen_p.h b/src/gui/kernel/qscreen_p.h index b0e1b86..ca29acd 100644 --- a/src/gui/kernel/qscreen_p.h +++ b/src/gui/kernel/qscreen_p.h @@ -58,6 +58,7 @@ class QScreenPrivate : public QObjectPrivate public: QScreenPrivate(QPlatformScreen *screen) : platformScreen(screen) + , orientationUpdateMask(0) { orientation = screen->orientation(); geometry = screen->geometry(); @@ -66,18 +67,24 @@ public: refreshRate = screen->refreshRate(); updatePrimaryOrientation(); + + filteredOrientation = orientation; + if (filteredOrientation == Qt::PrimaryOrientation) + filteredOrientation = primaryOrientation; } void updatePrimaryOrientation(); + QPlatformScreen *platformScreen; + + Qt::ScreenOrientations orientationUpdateMask; Qt::ScreenOrientation orientation; + Qt::ScreenOrientation filteredOrientation; Qt::ScreenOrientation primaryOrientation; QRect geometry; QRect availableGeometry; QDpi logicalDpi; qreal refreshRate; - - QPlatformScreen *platformScreen; }; QT_END_NAMESPACE diff --git a/tests/auto/gui/kernel/qscreen/tst_qscreen.cpp b/tests/auto/gui/kernel/qscreen/tst_qscreen.cpp index 475b6ca..e6c2886 100644 --- a/tests/auto/gui/kernel/qscreen/tst_qscreen.cpp +++ b/tests/auto/gui/kernel/qscreen/tst_qscreen.cpp @@ -177,13 +177,26 @@ void tst_QScreen::transformBetween() void tst_QScreen::orientationChange() { + qRegisterMetaType("Qt::ScreenOrientation"); + QScreen *screen = QGuiApplication::primaryScreen(); + screen->setOrientationUpdateMask(Qt::LandscapeOrientation | Qt::PortraitOrientation); + QWindowSystemInterface::handleScreenOrientationChange(screen, Qt::LandscapeOrientation); QTRY_COMPARE(screen->orientation(), Qt::LandscapeOrientation); QWindowSystemInterface::handleScreenOrientationChange(screen, Qt::PortraitOrientation); QTRY_COMPARE(screen->orientation(), Qt::PortraitOrientation); + + QSignalSpy spy(screen, SIGNAL(orientationChanged(Qt::ScreenOrientation))); + + QWindowSystemInterface::handleScreenOrientationChange(screen, Qt::InvertedLandscapeOrientation); + QWindowSystemInterface::handleScreenOrientationChange(screen, Qt::InvertedPortraitOrientation); + QWindowSystemInterface::handleScreenOrientationChange(screen, Qt::LandscapeOrientation); + + QTRY_COMPARE(screen->orientation(), Qt::LandscapeOrientation); + QCOMPARE(spy.count(), 1); } #include -- 2.7.4