on xenial help sign in
Let qtmir know which apps are exempt from the lifecycle management.
cb4c07bMichael Terry
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}
@@ -263,3 +265,17 @@ void ApplicationInfo::onSessionSurfaceAdded(MirSurface* surface)
263 }
265 }
264 }
266 }
265}
267}
268+
269+bool ApplicationInfo::exemptFromLifecycle() const
270+{
271+ return m_exemptFromLifecycle;
272+}
273+
274+void ApplicationInfo::setExemptFromLifecycle(bool exemptFromLifecycle)
275+{
276+ if (m_exemptFromLifecycle != exemptFromLifecycle)
277+ {
278+ m_exemptFromLifecycle = exemptFromLifecycle;
279+ Q_EMIT exemptFromLifecycleChanged(m_exemptFromLifecycle);
280+ }
281+}
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+24−11
@@ -1857,21 +1857,28 @@ Rectangle {
1857 loadShell(data.formFactor);
1857 loadShell(data.formFactor);
1858 shell.usageScenario = data.usageScenario;
1858 shell.usageScenario = data.usageScenario;
1859
1859
1860+ // Add two main stage apps, the second in order to suspend the first.
1861+ // LibreOffice has isTouchApp set to false by our mocks.
1860 var app1 = ApplicationManager.startApplication("libreoffice");
1862 var app1 = ApplicationManager.startApplication("libreoffice");
1861 waitUntilAppWindowIsFullyLoaded(app1);
1863 waitUntilAppWindowIsFullyLoaded(app1);
1862− var app2 = ApplicationManager.startApplication("dialer-app");
1864+ var app2 = ApplicationManager.startApplication("gallery-app");
1863 waitUntilAppWindowIsFullyLoaded(app2);
1865 waitUntilAppWindowIsFullyLoaded(app2);
1864
1866
1865− // Make sure app1 is unfocused but still running
1867+ // Sanity checking
1868+ compare(app1.stage, ApplicationInfoInterface.MainStage);
1869+ compare(app2.stage, ApplicationInfoInterface.MainStage);
1870+ verify(!app1.isTouchApp);
1866− compare(app1.session.lastSurface.activeFocus, false);
1871+ verify(!app1.session.lastSurface.activeFocus);
1867− compare(app1.isTouchApp, false); // sanity check our mock, which sets this for us
1872+
1873+ // Make sure app1 is exempt with a requested suspend
1874+ verify(app1.exemptFromLifecycle);
1868− compare(app1.requestedState, ApplicationInfoInterface.RequestedRunning);
1875+ compare(app1.requestedState, ApplicationInfoInterface.RequestedSuspended);
1869 }
1876 }
1870
1877
1871 function test_lifecyclePolicyExemption_data() {
1878 function test_lifecyclePolicyExemption_data() {
1872 return [
1879 return [
1873− {tag: "phone", formFactor: "phone", usageScenario: "phone", suspendsApps: true},
1880+ {tag: "phone", formFactor: "phone", usageScenario: "phone"},
1874− {tag: "tablet", formFactor: "tablet", usageScenario: "tablet", suspendsApps: true}
1881+ {tag: "tablet", formFactor: "tablet", usageScenario: "tablet"}
1875 ]
1882 ]
1876 }
1883 }
1877
1884
@@ -1881,14 +1888,20 @@ Rectangle {
1881
1888
1882 GSettingsController.setLifecycleExemptAppids(["webbrowser-app"]);
1889 GSettingsController.setLifecycleExemptAppids(["webbrowser-app"]);
1883
1890
1891+ // Add two main stage apps, the second in order to suspend the first
1884 var app1 = ApplicationManager.startApplication("webbrowser-app");
1892 var app1 = ApplicationManager.startApplication("webbrowser-app");
1885 waitUntilAppWindowIsFullyLoaded(app1);
1893 waitUntilAppWindowIsFullyLoaded(app1);
1886− var app2 = ApplicationManager.startApplication("dialer-app");
1894+ var app2 = ApplicationManager.startApplication("gallery-app");
1887 waitUntilAppWindowIsFullyLoaded(app2);
1895 waitUntilAppWindowIsFullyLoaded(app2);
1888
1896
1889− // Make sure app1 is unfocused but still running
1897+ // Sanity checking
1898+ compare(app1.stage, ApplicationInfoInterface.MainStage);
1899+ compare(app2.stage, ApplicationInfoInterface.MainStage);
1890− compare(app1.session.lastSurface.activeFocus, false);
1900+ verify(!app1.session.lastSurface.activeFocus);
1901+
1902+ // Make sure app1 is exempt with a requested suspend
1903+ verify(app1.exemptFromLifecycle);
1891− compare(app1.requestedState, ApplicationInfoInterface.RequestedRunning);
1904+ compare(app1.requestedState, ApplicationInfoInterface.RequestedSuspended);
1892 }
1905 }
1893
1906
1894 function test_switchToStagedForcesLegacyAppClosing_data() {
1907 function test_switchToStagedForcesLegacyAppClosing_data() {