on xenial help sign in
Update unity8 to handle lifecycle policy for apps
commit1df29c160abd8547138310726891cf64de65d3fe authorMichael Terry <michael.terry@canonical.com> dateTue 29 Sep 2015, 16:19 (11 years ago) parentd1c74de
10 files changed+128−1
debian/control+1−1 qml/Shell.qml+25 qml/graphics/applicationIcons/libreoffice@16.png tests/mocks/GSettings.1.0/fake_gsettings.cpp+31 tests/mocks/GSettings.1.0/fake_gsettings.h+10 tests/mocks/Unity/Application/ApplicationInfo.cpp+25 tests/mocks/Unity/Application/ApplicationInfo.h+8 tests/mocks/Unity/Application/ApplicationManager.cpp+7 tests/plugins/Unity/Launcher/launchermodeltest.cpp+3 tests/qmltests/tst_Shell.qml+18
debian/control+1−1
@@ -28,7 +28,7 @@ Build-Depends: cmake,
2828 libqt5xmlpatterns5-dev,
2929 libsystemsettings-dev,
3030 libudev-dev,
31− libunity-api-dev (>= 7.100),
31+ libunity-api-dev (>= 7.101),
3232 libusermetricsoutput1-dev,
3333 libxcb1-dev,
3434 pkg-config,
qml/Shell.qml+25
@@ -214,6 +214,20 @@ Item {
214214 width: parent.width
215215 height: parent.height
216216
217+ GSettings {
218+ id: lifecycleExceptions
219+ schema.id: "com.canonical.qtmir"
220+ }
221+
222+ function isExemptFromLifecycle(appId) {
223+ for (var i = 0; i < lifecycleExceptions.lifecycleExemptAppids.length; i++) {
224+ if (appId === lifecycleExceptions.lifecycleExemptAppids[i]) {
225+ return true;
226+ }
227+ }
228+ return false;
229+ }
230+
217231 Connections {
218232 target: ApplicationManager
219233
@@ -243,6 +257,17 @@ Item {
243257
244258 onApplicationAdded: {
245259 launcher.hide();
260+
261+ // Apply lifecycle policy when an app is opened
262+ var app = ApplicationManager.findApplication(appId);
263+ if (app) {
264+ // We don't bother with a Qt.binding because isTouchApp is
265+ // marked as CONSTANT by unity-api, and we neither expect
266+ // the gsettings to change on us during the life of the app,
267+ // nor does it make a whole lot of sense to adjust the
268+ // lifecycle policy while the app is running.
269+ app.canSuspend = app.isTouchApp && !stages.isExemptFromLifecycle(appId);
270+ }
246271 }
247272 }
248273
qml/graphics/applicationIcons/libreoffice@16.pngnew file

Binary file not shown.

tests/mocks/GSettings.1.0/fake_gsettings.cpp+31
@@ -75,6 +75,19 @@ void GSettingsControllerQml::setLockedOutTime(qint64 timestamp)
7575 }
7676}
7777
78+QStringList GSettingsControllerQml::lifecycleExemptAppids() const
79+{
80+ return m_lifecycleExemptAppids;
81+}
82+
83+void GSettingsControllerQml::setLifecycleExemptAppids(const QStringList &appIds)
84+{
85+ if (m_lifecycleExemptAppids != appIds) {
86+ m_lifecycleExemptAppids = appIds;
87+ Q_EMIT lifecycleExemptAppidsChanged(m_lifecycleExemptAppids);
88+ }
89+}
90+
7891GSettingsSchemaQml::GSettingsSchemaQml(QObject *parent): QObject(parent) {
7992}
8093
@@ -114,6 +127,8 @@ GSettingsQml::GSettingsQml(QObject *parent)
114127 this, &GSettingsQml::usageModeChanged);
115128 connect(GSettingsControllerQml::instance(), &GSettingsControllerQml::lockedOutTimeChanged,
116129 this, &GSettingsQml::lockedOutTimeChanged);
130+ connect(GSettingsControllerQml::instance(), &GSettingsControllerQml::lifecycleExemptAppidsChanged,
131+ this, &GSettingsQml::lifecycleExemptAppidsChanged);
117132}
118133
119134GSettingsSchemaQml * GSettingsQml::schema() const {
@@ -167,3 +182,19 @@ void GSettingsQml::setLockedOutTime(qint64 timestamp)
167182 GSettingsControllerQml::instance()->setLockedOutTime(timestamp);
168183 }
169184}
185+
186+QStringList GSettingsQml::lifecycleExemptAppids() const
187+{
188+ if (m_schema->id() == "com.canonical.qtmir") {
189+ return GSettingsControllerQml::instance()->lifecycleExemptAppids();
190+ } else {
191+ return QStringList();
192+ }
193+}
194+
195+void GSettingsQml::setLifecycleExemptAppids(const QStringList &appIds)
196+{
197+ if (m_schema->id() == "com.canonical.qtmir") {
198+ GSettingsControllerQml::instance()->setLifecycleExemptAppids(appIds);
199+ }
200+}
tests/mocks/GSettings.1.0/fake_gsettings.h+10
@@ -19,6 +19,7 @@
1919
2020#include <QList>
2121#include <QObject>
22+#include <QStringList>
2223
2324class GSettingsSchemaQml: public QObject
2425{
@@ -48,6 +49,7 @@ class GSettingsQml: public QObject
4849 Q_PROPERTY(QString pictureUri READ pictureUri WRITE setPictureUri NOTIFY pictureUriChanged)
4950 Q_PROPERTY(QString usageMode READ usageMode WRITE setUsageMode NOTIFY usageModeChanged)
5051 Q_PROPERTY(qint64 lockedOutTime READ lockedOutTime WRITE setLockedOutTime NOTIFY lockedOutTimeChanged)
52+ Q_PROPERTY(QStringList lifecycleExemptAppids READ lifecycleExemptAppids WRITE setLifecycleExemptAppids NOTIFY lifecycleExemptAppidsChanged)
5153
5254public:
5355 GSettingsQml(QObject *parent = nullptr);
@@ -56,16 +58,19 @@ public:
5658 QString pictureUri() const;
5759 QString usageMode() const;
5860 qint64 lockedOutTime() const;
61+ QStringList lifecycleExemptAppids() const;
5962
6063 void setPictureUri(const QString &str);
6164 void setUsageMode(const QString &usageMode);
6265 void setLockedOutTime(qint64 timestamp);
66+ void setLifecycleExemptAppids(const QStringList &appIds);
6367
6468Q_SIGNALS:
6569 void schemaChanged();
6670 void pictureUriChanged(const QString&);
6771 void usageModeChanged(const QString&);
6872 void lockedOutTimeChanged(qint64);
73+ void lifecycleExemptAppidsChanged(const QStringList &);
6974
7075private:
7176 GSettingsSchemaQml* m_schema;
@@ -90,10 +95,14 @@ public:
9095 qint64 lockedOutTime() const;
9196 Q_INVOKABLE void setLockedOutTime(qint64 timestamp);
9297
98+ QStringList lifecycleExemptAppids() const;
99+ Q_INVOKABLE void setLifecycleExemptAppids(const QStringList &appIds);
100+
93101Q_SIGNALS:
94102 void pictureUriChanged(const QString&);
95103 void usageModeChanged(const QString&);
96104 void lockedOutTimeChanged(qint64 timestamp);
105+ void lifecycleExemptAppidsChanged(const QStringList&);
97106
98107private:
99108 GSettingsControllerQml();
@@ -101,6 +110,7 @@ private:
101110 QString m_pictureUri;
102111 QString m_usageMode;
103112 qint64 m_lockedOutTime;
113+ QStringList m_lifecycleExemptAppids;
104114
105115 static GSettingsControllerQml* s_controllerInstance;
106116 QList<GSettingsQml *> m_registeredGSettings;
tests/mocks/Unity/Application/ApplicationInfo.cpp+25
@@ -41,6 +41,8 @@ ApplicationInfo::ApplicationInfo(const QString &appId, QObject *parent)
4141 Qt::InvertedLandscapeOrientation)
4242 , m_rotatesWindowContents(false)
4343 , m_requestedState(RequestedRunning)
44+ , m_isTouchApp(true)
45+ , m_canSuspend(true)
4446 , m_manualSurfaceCreation(false)
4547{
4648}
@@ -58,6 +60,8 @@ ApplicationInfo::ApplicationInfo(QObject *parent)
5860 Qt::InvertedLandscapeOrientation)
5961 , m_rotatesWindowContents(false)
6062 , m_requestedState(RequestedRunning)
63+ , m_isTouchApp(true)
64+ , m_canSuspend(true)
6165 , m_manualSurfaceCreation(false)
6266{
6367}
@@ -245,6 +249,27 @@ void ApplicationInfo::setRequestedState(RequestedState value)
245249 }
246250}
247251
252+bool ApplicationInfo::isTouchApp() const
253+{
254+ return m_isTouchApp;
255+}
256+
257+void ApplicationInfo::setIsTouchApp(bool isTouchApp)
258+{
259+ m_isTouchApp = isTouchApp;
260+}
261+
262+bool ApplicationInfo::canSuspend() const
263+{
264+ return m_canSuspend;
265+}
266+
267+void ApplicationInfo::setCanSuspend(bool canSuspend)
268+{
269+ m_canSuspend = canSuspend;
270+ Q_EMIT canSuspendChanged(canSuspend);
271+}
272+
248273void ApplicationInfo::onSessionSurfaceChanged(MirSurface* surface)
249274{
250275 if (surface != nullptr && m_state == Starting) {
tests/mocks/Unity/Application/ApplicationInfo.h+8
@@ -89,6 +89,12 @@ public:
8989 bool manualSurfaceCreation() const { return m_manualSurfaceCreation; }
9090 void setManualSurfaceCreation(bool value);
9191
92+ bool isTouchApp() const override;
93+ void setIsTouchApp(bool isTouchApp); // only in mock
94+
95+ bool canSuspend() const override;
96+ void setCanSuspend(bool canSuspend) override;
97+
9298public:
9399 void setSession(Session* session);
94100 Session* session() const { return m_session; }
@@ -121,6 +127,8 @@ private:
121127 Qt::ScreenOrientations m_supportedOrientations;
122128 bool m_rotatesWindowContents;
123129 RequestedState m_requestedState;
130+ bool m_isTouchApp;
131+ bool m_canSuspend;
124132
125133 bool m_manualSurfaceCreation;
126134};
tests/mocks/Unity/Application/ApplicationManager.cpp+7
@@ -458,6 +458,13 @@ void ApplicationManager::buildListOfAvailableApplications()
458458 application->setName("YouTube");
459459 application->setIconId("youtube");
460460 m_availableApplications.append(application);
461+
462+ application = new ApplicationInfo(this);
463+ application->setAppId("libreoffice");
464+ application->setName("LibreOffice");
465+ application->setIconId("libreoffice");
466+ application->setIsTouchApp(false);
467+ m_availableApplications.append(application);
461468}
462469
463470
tests/plugins/Unity/Launcher/launchermodeltest.cpp+3
@@ -57,6 +57,9 @@ public:
5757 QColor splashColorFooter() const override { return QColor(0,0,0,0); }
5858 Qt::ScreenOrientations supportedOrientations() const override { return Qt::PortraitOrientation; }
5959 bool rotatesWindowContents() const override { return false; }
60+ bool isTouchApp() const override { return true; }
61+ bool canSuspend() const override { return true; }
62+ void setCanSuspend(bool) override {}
6063
6164 // Methods used for mocking (not in the interface)
6265 void setFocused(bool focused) { m_focused = focused; Q_EMIT focusedChanged(focused); }
tests/qmltests/tst_Shell.qml+18
@@ -377,6 +377,8 @@ Rectangle {
377377 LightDM.Greeter.authenticate(""); // reset greeter
378378
379379 sessionSpy.clear();
380+
381+ GSettingsController.setLifecycleExemptAppids([]);
380382 }
381383
382384 function killApps() {
@@ -1731,5 +1733,21 @@ Rectangle {
17311733
17321734 keyRelease(Qt.Key_Control);
17331735 }
1736+
1737+ function test_lifecyclePolicy() {
1738+ loadShell("desktop");
1739+
1740+ GSettingsController.setLifecycleExemptAppids(["webbrowser-app"]);
1741+
1742+ var app1 = ApplicationManager.startApplication("camera-app");
1743+ tryCompare(app1, "canSuspend", true);
1744+
1745+ var app2 = ApplicationManager.startApplication("webbrowser-app");
1746+ tryCompare(app2, "canSuspend", false);
1747+
1748+ var app3 = ApplicationManager.startApplication("libreoffice");
1749+ compare(app3.isTouchApp, false); // sanity check our mock, which sets this for us
1750+ tryCompare(app3, "canSuspend", false);
1751+ }
17341752 }
17351753}