aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/qml/qqmlengine.cpp53
-rw-r--r--src/quick/util/qquickapplication.cpp8
-rw-r--r--src/quick/util/qquickapplication_p.h5
-rw-r--r--tests/auto/quick/qquickapplication/tst_qquickapplication.cpp66
4 files changed, 123 insertions, 9 deletions
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 39c3399917..5b39aba65e 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -411,14 +411,50 @@ The following functions are also on the Qt object.
\row
\li \c application.active
\li
- This read-only property indicates whether the application is the top-most and focused
- application, and the user is able to interact with the application. The property
- is false when the application is in the background, the device keylock or screen
- saver is active, the screen backlight is turned off, or the global system dialog
- is being displayed on top of the application. It can be used for stopping and
- pausing animations, timers and active processing of data in order to save device
- battery power and free device memory and processor load when the application is not
- active.
+ Deprecated, use Qt.application.state == Qt.ApplicationActive instead.
+
+ \row
+ \li \c application.state
+ \li
+ This read-only property indicates the current state of the application.
+
+ Possible values are:
+
+ \list
+ \li Qt.ApplicationActive - The application is the top-most and focused application, and the
+ user is able to interact with the application.
+ \li Qt.ApplicationInactive - The application is visible or partially visible, but not selected
+ to be in front, the user cannot interact with the application.
+ On desktop platforms, this typically means that the user activated
+ another application. On mobile platforms, it is more common to
+ enter this state when the OS is interrupting the user with for
+ example incoming calls, SMS-messages or dialogs. This is usually a
+ transient state during which the application is paused. The user
+ may return focus to your application, but most of the time it will
+ be the first indication that the application is going to be suspended.
+ While in this state, consider pausing or stopping any activity that
+ should not continue when the user cannot interact with your
+ application, such as a video, a game, animations, or sensors.
+ You should also avoid performing CPU-intensive tasks which might
+ slow down the application in front.
+ \li Qt.ApplicationSuspended - The application is suspended and not visible to the user. On
+ mobile platforms, the application typically enters this state when
+ the user returns to the home screen or switches to another
+ application. While in this state, the application should ensure
+ that the user perceives it as always alive and does not lose his
+ progress, saving any persistent data. The application should cease
+ all activities and be prepared for code execution to stop. While
+ suspended, the application can be killed at any time without
+ further warnings (for example when low memory forces the OS to purge
+ suspended applications).
+ \li Qt.ApplicationHidden - The application is hidden and runs in the background. This is the
+ normal state for applications that need to do background processing,
+ like playing music, while the user interacts with other applications.
+ The application should free up all graphical resources when entering
+ this state. A Qt Quick application should not usually handle this state
+ at the QML level. Instead, you should unload the entire UI and reload
+ the QML files whenever the application becomes active again.
+ \endlist
\row
\li \c application.layoutDirection
@@ -469,6 +505,7 @@ The following functions are also on the Qt object.
Note that when using QML without a QGuiApplication, the following properties will be undefined:
\list
\li application.active
+ \li application.state
\li application.layoutDirection
\endlist
*/
diff --git a/src/quick/util/qquickapplication.cpp b/src/quick/util/qquickapplication.cpp
index 2de28a9509..244e13888c 100644
--- a/src/quick/util/qquickapplication.cpp
+++ b/src/quick/util/qquickapplication.cpp
@@ -75,6 +75,9 @@ QQuickApplication::QQuickApplication(QObject *parent)
{
if (qApp) {
qApp->installEventFilter(this);
+
+ connect(qApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)),
+ this, SIGNAL(stateChanged(Qt::ApplicationState)));
}
}
@@ -99,6 +102,11 @@ bool QQuickApplication::supportsMultipleWindows() const
return QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::MultipleWindows);
}
+Qt::ApplicationState QQuickApplication::state() const
+{
+ return QGuiApplication::applicationState();
+}
+
bool QQuickApplication::eventFilter(QObject *, QEvent *event)
{
Q_D(QQuickApplication);
diff --git a/src/quick/util/qquickapplication_p.h b/src/quick/util/qquickapplication_p.h
index cccc024282..780fb1ffa6 100644
--- a/src/quick/util/qquickapplication_p.h
+++ b/src/quick/util/qquickapplication_p.h
@@ -54,9 +54,10 @@ class QQuickApplicationPrivate;
class Q_AUTOTEST_EXPORT QQuickApplication : public QQmlApplication
{
Q_OBJECT
- Q_PROPERTY(bool active READ active NOTIFY activeChanged)
+ Q_PROPERTY(bool active READ active NOTIFY activeChanged) // deprecated, use 'state' instead
Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection NOTIFY layoutDirectionChanged)
Q_PROPERTY(bool supportsMultipleWindows READ supportsMultipleWindows CONSTANT)
+ Q_PROPERTY(Qt::ApplicationState state READ state NOTIFY stateChanged)
public:
explicit QQuickApplication(QObject *parent = 0);
@@ -64,10 +65,12 @@ public:
bool active() const;
Qt::LayoutDirection layoutDirection() const;
bool supportsMultipleWindows() const;
+ Qt::ApplicationState state() const;
Q_SIGNALS:
void activeChanged();
void layoutDirectionChanged();
+ void stateChanged(Qt::ApplicationState state);
private:
bool eventFilter(QObject *, QEvent *event);
diff --git a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
index b8986fbf85..ef27445920 100644
--- a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
+++ b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
@@ -46,6 +46,8 @@
#include <QtQuick/qquickview.h>
#include <QtGui/qinputmethod.h>
#include <qpa/qwindowsysteminterface.h>
+#include <qpa/qplatformintegration.h>
+#include <private/qguiapplication_p.h>
class tst_qquickapplication : public QObject
{
@@ -55,6 +57,7 @@ public:
private slots:
void active();
+ void state();
void layoutDirection();
void inputMethod();
@@ -103,6 +106,69 @@ void tst_qquickapplication::active()
QVERIFY(!item->property("active2").toBool());
}
+void tst_qquickapplication::state()
+{
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick 2.0; "
+ "Item { "
+ " property int state: Qt.application.state; "
+ " property int state2: Qt.ApplicationInactive; "
+ " Connections { "
+ " target: Qt.application; "
+ " onStateChanged: state2 = Qt.application.state; "
+ " } "
+ "}", QUrl::fromLocalFile(""));
+ QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
+ QVERIFY(item);
+ QQuickWindow window;
+ item->setParentItem(window.contentItem());
+
+ // initial state should be ApplicationInactive
+ QCOMPARE(Qt::ApplicationState(item->property("state").toInt()), Qt::ApplicationInactive);
+ QCOMPARE(Qt::ApplicationState(item->property("state2").toInt()), Qt::ApplicationInactive);
+
+ // If the platform plugin has the ApplicationState capability, state changes originate from it
+ // as a result of a system event. We therefore have to simulate these events here.
+ if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ApplicationState)) {
+
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive);
+ QTest::waitForEvents();
+ QCOMPARE(Qt::ApplicationState(item->property("state").toInt()), Qt::ApplicationActive);
+ QCOMPARE(Qt::ApplicationState(item->property("state2").toInt()), Qt::ApplicationActive);
+
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive);
+ QTest::waitForEvents();
+ QCOMPARE(Qt::ApplicationState(item->property("state").toInt()), Qt::ApplicationInactive);
+ QCOMPARE(Qt::ApplicationState(item->property("state2").toInt()), Qt::ApplicationInactive);
+
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationSuspended);
+ QTest::waitForEvents();
+ QCOMPARE(Qt::ApplicationState(item->property("state").toInt()), Qt::ApplicationSuspended);
+ QCOMPARE(Qt::ApplicationState(item->property("state2").toInt()), Qt::ApplicationSuspended);
+
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationHidden);
+ QTest::waitForEvents();
+ QCOMPARE(Qt::ApplicationState(item->property("state").toInt()), Qt::ApplicationHidden);
+ QCOMPARE(Qt::ApplicationState(item->property("state2").toInt()), Qt::ApplicationHidden);
+
+ } else {
+ // Otherwise, the application can only be in two states, Active and Inactive. These are
+ // triggered by window activation.
+ window.show();
+ window.requestActivate();
+ QTest::qWaitForWindowActive(&window);
+ QVERIFY(QGuiApplication::focusWindow() == &window);
+ QCOMPARE(Qt::ApplicationState(item->property("state").toInt()), Qt::ApplicationActive);
+ QCOMPARE(Qt::ApplicationState(item->property("state2").toInt()), Qt::ApplicationActive);
+
+ // not active again
+ QWindowSystemInterface::handleWindowActivated(0);
+ QTRY_VERIFY(QGuiApplication::focusWindow() != &window);
+ QCOMPARE(Qt::ApplicationState(item->property("state").toInt()), Qt::ApplicationInactive);
+ QCOMPARE(Qt::ApplicationState(item->property("state2").toInt()), Qt::ApplicationInactive);
+ }
+}
+
void tst_qquickapplication::layoutDirection()
{