Added QScreen::setOrientationUpdateMask().
authorSamuel Rødal <samuel.rodal@nokia.com>
Tue, 5 Jun 2012 12:17:24 +0000 (14:17 +0200)
committerQt by Nokia <qt-info@nokia.com>
Wed, 6 Jun 2012 05:41:17 +0000 (07:41 +0200)
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 <ian.monroe@nokia.com>
Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Reviewed-by: Gunnar Sletta <gunnar.sletta@nokia.com>
Reviewed-by: Kevin Ottens <kevin.ottens.qnx@kdab.com>
src/gui/kernel/qguiapplication.cpp
src/gui/kernel/qguiapplication_p.h
src/gui/kernel/qplatformscreen.h
src/gui/kernel/qplatformscreen_qpa.cpp
src/gui/kernel/qscreen.cpp
src/gui/kernel/qscreen.h
src/gui/kernel/qscreen_p.h
tests/auto/gui/kernel/qscreen/tst_qscreen.cpp

index f71e611..3e999be 100644 (file)
@@ -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(
index e79c2af..d538c39 100644 (file)
@@ -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);
index 4baf0f6..31d459d 100644 (file)
@@ -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<QPlatformScreen *> virtualSiblings() const;
index fdb5d32..d946e4f 100644 (file)
@@ -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();
index 2e0df43..fe8b15e 100644 (file)
@@ -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;
 }
 
 /*!
index 17f3cd3..6c14216 100644 (file)
@@ -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;
index b0e1b86..ca29acd 100644 (file)
@@ -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
index 475b6ca..e6c2886 100644 (file)
@@ -177,13 +177,26 @@ void tst_QScreen::transformBetween()
 
 void tst_QScreen::orientationChange()
 {
+    qRegisterMetaType<Qt::ScreenOrientation>("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 <tst_qscreen.moc>