on xenial help sign in
Pass qtmir whether an app is exempt from the lifecycle or not
c6ccdb7Michael Terry
CMakeLists.txt+1−1
@@ -57,7 +57,7 @@ find_package(Qt5DBus 5.4 REQUIRED)
57find_package(Qt5Concurrent 5.4 REQUIRED)
57find_package(Qt5Concurrent 5.4 REQUIRED)
58find_package(Qt5Sql 5.4 REQUIRED)
58find_package(Qt5Sql 5.4 REQUIRED)
59
59
60−pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=11)
60+pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=12)
61
61
62# Standard install paths
62# Standard install paths
63include(GNUInstallDirs)
63include(GNUInstallDirs)
debian/control+3−3
@@ -29,7 +29,7 @@ Build-Depends: cmake,
29 libqt5xmlpatterns5-dev,
29 libqt5xmlpatterns5-dev,
30 libsystemsettings-dev,
30 libsystemsettings-dev,
31 libudev-dev,
31 libudev-dev,
32− libunity-api-dev (>= 7.103),
32+ libunity-api-dev (>= 7.104),
33 libusermetricsoutput1-dev,
33 libusermetricsoutput1-dev,
34 libxcb1-dev,
34 libxcb1-dev,
35 pkg-config,
35 pkg-config,
@@ -128,7 +128,7 @@ Depends: qml-module-qtquick-layouts,
128 qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.3.1627) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.3.1627),
128 qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.3.1627) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.3.1627),
129 qtdeclarative5-unity-notifications-plugin (>= 0.1.2) | unity-notifications-impl,
129 qtdeclarative5-unity-notifications-plugin (>= 0.1.2) | unity-notifications-impl,
130 ubuntu-thumbnailer-impl-0,
130 ubuntu-thumbnailer-impl-0,
131− unity-application-impl-11,
131+ unity-application-impl-12,
132 unity-notifications-impl-3,
132 unity-notifications-impl-3,
133 unity-plugin-scopes | unity-scopes-impl,
133 unity-plugin-scopes | unity-scopes-impl,
134 unity-scopes-impl-7,
134 unity-scopes-impl-7,
@@ -174,7 +174,7 @@ Pre-Depends: ${misc:Pre-Depends},
174Depends: ${misc:Depends},
174Depends: ${misc:Depends},
175 ${shlibs:Depends},
175 ${shlibs:Depends},
176Provides: unity-application-impl,
176Provides: unity-application-impl,
177− unity-application-impl-11,
177+ unity-application-impl-12,
178Replaces: unity8-autopilot (<< 8.02+15.04.20150422-0ubuntu1)
178Replaces: unity8-autopilot (<< 8.02+15.04.20150422-0ubuntu1)
179Description: Fake environment for running Unity 8 shell
179Description: Fake environment for running Unity 8 shell
180 Provides fake implementations of some QML modules used by Unity 8 shell
180 Provides fake implementations of some QML modules used by Unity 8 shell
qml/Stages/PhoneStage.qml+6−4
@@ -426,14 +426,16 @@ AbstractStage {
426
426
427 readonly property bool isDash: model.appId == "unity8-dash"
427 readonly property bool isDash: model.appId == "unity8-dash"
428
428
429− readonly property bool canSuspend: model.isTouchApp
429+ Binding {
430+ target: appDelegate.application
431+ property: "exemptFromLifecycle"
430− && !isExemptFromLifecycle(model.appId)
432+ value: !model.isTouchApp || isExemptFromLifecycle(model.appId)
433+ }
431
434
432 Binding {
435 Binding {
433 target: appDelegate.application
436 target: appDelegate.application
434 property: "requestedState"
437 property: "requestedState"
435− value: !canSuspend
436− || (isDash && root.keepDashRunning)
438+ value: (isDash && root.keepDashRunning)
437 || (!root.suspended && appDelegate.focus)
439 || (!root.suspended && appDelegate.focus)
438 ? ApplicationInfoInterface.RequestedRunning
440 ? ApplicationInfoInterface.RequestedRunning
439 : ApplicationInfoInterface.RequestedSuspended
441 : ApplicationInfoInterface.RequestedSuspended
qml/Stages/TabletStage.qml+6−4
@@ -612,14 +612,16 @@ AbstractStage {
612
612
613 readonly property bool isDash: model.appId == "unity8-dash"
613 readonly property bool isDash: model.appId == "unity8-dash"
614
614
615− readonly property bool canSuspend: model.isTouchApp
615+ Binding {
616+ target: spreadTile.application
617+ property: "exemptFromLifecycle"
616− && !isExemptFromLifecycle(model.appId)
618+ value: !model.isTouchApp || isExemptFromLifecycle(model.appId)
619+ }
617
620
618 Binding {
621 Binding {
619 target: spreadTile.application
622 target: spreadTile.application
620 property: "requestedState"
623 property: "requestedState"
621− value: !canSuspend
622− || (isDash && root.keepDashRunning)
624+ value: (isDash && root.keepDashRunning)
623 || (!root.suspended && (model.appId == priv.mainStageAppId
625 || (!root.suspended && (model.appId == priv.mainStageAppId
624 || model.appId == priv.sideStageAppId))
626 || model.appId == priv.sideStageAppId))
625 ? ApplicationInfoInterface.RequestedRunning
627 ? ApplicationInfoInterface.RequestedRunning
tests/mocks/Unity/Application/ApplicationInfo.cpp+16
@@ -42,6 +42,7 @@ ApplicationInfo::ApplicationInfo(const QString &appId, QObject *parent)
42 , m_rotatesWindowContents(false)
42 , m_rotatesWindowContents(false)
43 , m_requestedState(RequestedRunning)
43 , m_requestedState(RequestedRunning)
44 , m_isTouchApp(true)
44 , m_isTouchApp(true)
45+ , m_exemptFromLifecycle(false)
45 , m_manualSurfaceCreation(false)
46 , m_manualSurfaceCreation(false)
46{
47{
47}
48}
@@ -60,6 +61,7 @@ ApplicationInfo::ApplicationInfo(QObject *parent)
60 , m_rotatesWindowContents(false)
61 , m_rotatesWindowContents(false)
61 , m_requestedState(RequestedRunning)
62 , m_requestedState(RequestedRunning)
62 , m_isTouchApp(true)
63 , m_isTouchApp(true)
64+ , m_exemptFromLifecycle(false)
63 , m_manualSurfaceCreation(false)
65 , m_manualSurfaceCreation(false)
64{
66{
65}
67}
@@ -253,6 +255,20 @@ void ApplicationInfo::setIsTouchApp(bool isTouchApp)
253 m_isTouchApp = isTouchApp;
255 m_isTouchApp = isTouchApp;
254}
256}
255
257
258+bool ApplicationInfo::exemptFromLifecycle() const
259+{
260+ return m_exemptFromLifecycle;
261+}
262+
263+void ApplicationInfo::setExemptFromLifecycle(bool exemptFromLifecycle)
264+{
265+ if (m_exemptFromLifecycle != exemptFromLifecycle)
266+ {
267+ m_exemptFromLifecycle = exemptFromLifecycle;
268+ Q_EMIT exemptFromLifecycleChanged(m_exemptFromLifecycle);
269+ }
270+}
271+
256void ApplicationInfo::onSessionSurfaceChanged(MirSurface* surface)
272void ApplicationInfo::onSessionSurfaceChanged(MirSurface* surface)
257{
273{
258 if (surface != nullptr && m_state == Starting) {
274 if (surface != nullptr && m_state == Starting) {
tests/mocks/Unity/Application/ApplicationInfo.h+4
@@ -92,6 +92,9 @@ public:
92 bool isTouchApp() const override;
92 bool isTouchApp() const override;
93 void setIsTouchApp(bool isTouchApp); // only in mock
93 void setIsTouchApp(bool isTouchApp); // only in mock
94
94
95+ bool exemptFromLifecycle() const override;
96+ void setExemptFromLifecycle(bool) override;
97+
95public:
98public:
96 void setSession(Session* session);
99 void setSession(Session* session);
97 Session* session() const { return m_session; }
100 Session* session() const { return m_session; }
@@ -125,6 +128,7 @@ private:
125 bool m_rotatesWindowContents;
128 bool m_rotatesWindowContents;
126 RequestedState m_requestedState;
129 RequestedState m_requestedState;
127 bool m_isTouchApp;
130 bool m_isTouchApp;
131+ bool m_exemptFromLifecycle;
128
132
129 bool m_manualSurfaceCreation;
133 bool m_manualSurfaceCreation;
130};
134};
tests/mocks/Unity/Application/ApplicationManager.cpp+2
@@ -107,6 +107,8 @@ QVariant ApplicationManager::data(const QModelIndex& index, int role) const {
107 return app->focused();
107 return app->focused();
108 case RoleIsTouchApp:
108 case RoleIsTouchApp:
109 return app->isTouchApp();
109 return app->isTouchApp();
110+ case RoleExemptFromLifecycle:
111+ return app->exemptFromLifecycle();
110 case RoleSession:
112 case RoleSession:
111 return QVariant::fromValue(app->session());
113 return QVariant::fromValue(app->session());
112 case RoleFullscreen:
114 case RoleFullscreen:
tests/mocks/Unity/Application/ApplicationManager.h+1−1
@@ -43,7 +43,7 @@ class ApplicationManager : public ApplicationManagerInterface {
43 static ApplicationManager *singleton();
43 static ApplicationManager *singleton();
44
44
45 enum MoreRoles {
45 enum MoreRoles {
46− RoleSession = RoleIsTouchApp+1,
46+ RoleSession = RoleExemptFromLifecycle+1,
47 RoleFullscreen,
47 RoleFullscreen,
48 };
48 };
49 enum Flag {
49 enum Flag {
tests/plugins/Unity/Launcher/launchermodeltest.cpp+2
@@ -59,6 +59,8 @@ public:
59 Qt::ScreenOrientations supportedOrientations() const override { return Qt::PortraitOrientation; }
59 Qt::ScreenOrientations supportedOrientations() const override { return Qt::PortraitOrientation; }
60 bool rotatesWindowContents() const override { return false; }
60 bool rotatesWindowContents() const override { return false; }
61 bool isTouchApp() const override { return true; }
61 bool isTouchApp() const override { return true; }
62+ bool exemptFromLifecycle() const override { return false; }
63+ void setExemptFromLifecycle(bool) override {}
62
64
63 // Methods used for mocking (not in the interface)
65 // Methods used for mocking (not in the interface)
64 void setFocused(bool focused) { m_focused = focused; Q_EMIT focusedChanged(focused); }
66 void setFocused(bool focused) { m_focused = focused; Q_EMIT focusedChanged(focused); }
tests/qmltests/tst_Shell.qml+13−11
@@ -1859,19 +1859,20 @@ Rectangle {
1859
1859
1860 var app1 = ApplicationManager.startApplication("libreoffice");
1860 var app1 = ApplicationManager.startApplication("libreoffice");
1861 waitUntilAppWindowIsFullyLoaded(app1);
1861 waitUntilAppWindowIsFullyLoaded(app1);
1862− var app2 = ApplicationManager.startApplication("dialer-app");
1862+ var app2 = ApplicationManager.startApplication("gallery-app");
1863 waitUntilAppWindowIsFullyLoaded(app2);
1863 waitUntilAppWindowIsFullyLoaded(app2);
1864
1864
1865− // Make sure app1 is unfocused but still running
1865+ // Make sure app1 is exempt with a requested suspend
1866− compare(app1.session.surface.activeFocus, false);
1866+ verify(app1.exemptFromLifecycle);
1867− compare(app1.isTouchApp, false); // sanity check our mock, which sets this for us
1867+ verify(!app1.isTouchApp); // sanity check our mock, which sets this for us
1868+ verify(!app1.session.surface.activeFocus);
1868− compare(app1.requestedState, ApplicationInfoInterface.RequestedRunning);
1869+ compare(app1.requestedState, ApplicationInfoInterface.RequestedSuspended);
1869 }
1870 }
1870
1871
1871 function test_lifecyclePolicyExemption_data() {
1872 function test_lifecyclePolicyExemption_data() {
1872 return [
1873 return [
1873− {tag: "phone", formFactor: "phone", usageScenario: "phone", suspendsApps: true},
1874+ {tag: "phone", formFactor: "phone", usageScenario: "phone"},
1874− {tag: "tablet", formFactor: "tablet", usageScenario: "tablet", suspendsApps: true}
1875+ {tag: "tablet", formFactor: "tablet", usageScenario: "tablet"}
1875 ]
1876 ]
1876 }
1877 }
1877
1878
@@ -1883,12 +1884,13 @@ Rectangle {
1883
1884
1884 var app1 = ApplicationManager.startApplication("webbrowser-app");
1885 var app1 = ApplicationManager.startApplication("webbrowser-app");
1885 waitUntilAppWindowIsFullyLoaded(app1);
1886 waitUntilAppWindowIsFullyLoaded(app1);
1886− var app2 = ApplicationManager.startApplication("dialer-app");
1887+ var app2 = ApplicationManager.startApplication("gallery-app");
1887 waitUntilAppWindowIsFullyLoaded(app2);
1888 waitUntilAppWindowIsFullyLoaded(app2);
1888
1889
1889− // Make sure app1 is unfocused but still running
1890+ // Make sure app1 is exempt with a requested suspend
1891+ verify(app1.exemptFromLifecycle);
1890− compare(app1.session.surface.activeFocus, false);
1892+ verify(!app1.session.surface.activeFocus);
1891− compare(app1.requestedState, ApplicationInfoInterface.RequestedRunning);
1893+ compare(app1.requestedState, ApplicationInfoInterface.RequestedSuspended);
1892 }
1894 }
1893
1895
1894 function test_switchToStagedForcesLegacyAppClosing_data() {
1896 function test_switchToStagedForcesLegacyAppClosing_data() {