Merge lp:~mterry/unity8/no-touch-no-lifecycle into lp:unity8
- no-touch-no-lifecycle
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Gerry Boland |
Approved revision: | 2001 |
Merged at revision: | 2031 |
Proposed branch: | lp:~mterry/unity8/no-touch-no-lifecycle |
Merge into: | lp:unity8 |
Prerequisite: | lp:~unity-team/unity8/new_fix_upsidedown |
Diff against target: |
651 lines (+218/-86) 15 files modified
CMakeLists.txt (+1/-1) debian/control (+2/-2) qml/Stages/AbstractStage.qml (+63/-0) qml/Stages/DesktopStage.qml (+4/-20) qml/Stages/PhoneStage.qml (+18/-29) qml/Stages/ShimStage.qml (+1/-1) qml/Stages/TabletStage.qml (+14/-32) tests/mocks/GSettings.1.0/fake_gsettings.cpp (+31/-0) tests/mocks/GSettings.1.0/fake_gsettings.h (+10/-0) tests/mocks/Unity/Application/ApplicationInfo.cpp (+12/-0) tests/mocks/Unity/Application/ApplicationInfo.h (+4/-0) tests/mocks/Unity/Application/ApplicationManager.cpp (+9/-0) tests/mocks/Unity/Application/ApplicationManager.h (+1/-1) tests/plugins/Unity/Launcher/launchermodeltest.cpp (+1/-0) tests/qmltests/tst_Shell.qml (+47/-0) |
To merge this branch: | bzr merge lp:~mterry/unity8/no-touch-no-lifecycle |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Gerry Boland (community) | Approve | ||
PS Jenkins bot (community) | continuous-integration | Needs Fixing | |
Daniel d'Andrada (community) | Abstain | ||
Andrea Cimitan | Pending | ||
Review via email: mp+275919@code.launchpad.net |
This proposal supersedes a proposal from 2015-09-29.
Commit message
Handle lifecycle policy exceptions ourselves, instead of letting qtmir do it for us and allow non-Touch apps to opt-out of the Touch lifecycle.
This requires using the new isTouchApp unity-api property to ApplicationInfo
Now that qtmir won't decide policy for suspending exemptions anymore, we take over the interpretation of the lifecycleException GSettings key. Since the GSettings key for that was registered under the qtmir namespace (and there's no technical reason to migrate settings), I left the schema in qtmir itself. We merely consume it.
Description of the change
== Checklist ==
* Are there any related MPs required for this MP to build/function as expected? Please list.
- https:/
- https:/
* Did you perform an exploratory manual test run of your code change and any related functionality?
Yes
* Did you make sure that your branch does not contain spurious tags?
Yes
* If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
I'm a member of that team.
* If you changed the UI, has there been a design review?
NA
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1990
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1991
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Andrea Cimitan (cimi) : Posted in a previous version of this proposal | # |
Michael Terry (mterry) wrote : Posted in a previous version of this proposal | # |
> 1.2 for now
Done.
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1992
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Gerry Boland (gerboland) wrote : Posted in a previous version of this proposal | # |
=== added file 'qml/graphics/
Binary files qml/graphics/
Why did that change?
Gerry Boland (gerboland) wrote : Posted in a previous version of this proposal | # |
=== added file 'qml/Stages/
Instead of destroying and re-creating the GSettings instance when Stage changes, could this file be a Singleton shared by all Stages?
+Rectangle {
This looks like a useless rectangle, no color is set. It could be a QtObject, if you weren't inheriting from it.
Oh, I see why the LibreOffice icon. Please ignore above comment
Gerry Boland (gerboland) wrote : Posted in a previous version of this proposal | # |
+ !model.isTouchApp
+ || isExemptFromLif
I think it would improve readability to make a quick boolean property :
canSuspend: model.isTouchApp && !isExemptFromLi
Michael Terry (mterry) wrote : Posted in a previous version of this proposal | # |
> === added file 'qml/Stages/
> Instead of destroying and re-creating the GSettings instance when
> Stage changes, could this file be a Singleton shared by all Stages?
It could be, sure, but I wasn't in the mindset of optimizing for Stage changes. What about the hundred other objects that get destroyed & created in that case? Are GSettings instances particularly expensive (honest question)?
> +Rectangle {
> This looks like a useless rectangle, no color is set. It could be
> a QtObject, if you weren't inheriting from it.
Fair point. I was trying to avoid unrelated changes by not merging common Stage code. I've done that now, and consolidated the color: settings as well as the public API for stages (which various of the Stage implementations didn't fully implement!).
> + !model.isTouchApp
> + || isExemptFromLif
> I think it would improve readability to make a quick boolean property :
> canSuspend: model.isTouchApp && !isExemptFromLi
Good point. Done.
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1993
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 1994. By Michael Terry
-
Go back to using 1.3
- 1995. By Michael Terry
-
Merge new_fix_upsidedown branch
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1994
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1995
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Daniel d'Andrada (dandrader) wrote : | # |
"Set lifecycle policy ourselves, instead of letting qtmir do it for us and allow non-Touch apps to opt-out of the Touch lifecycle."
This commit message is not correct. Unity 8 is *already* controlling the lifecycle policy.
The only thing missing in trunk is the "allow non-Touch apps to opt-out of the Touch lifecycle" part.
Daniel d'Andrada (dandrader) wrote : | # |
test_lifecycleP
It's too comprehensive. You can't and should not expect a single test to cover all angles and aspects of lifecycle policy as that catch-all name (test_lifecycle
Michael Terry (mterry) wrote : | # |
> This commit message is not correct. Unity 8 is *already* controlling the lifecycle policy.
Sort of. Qtmir was overriding unity8's requests based on its own handling of the exception list. This branch moves that handling into unity8, so that unity8 is wholly responsible for policy. I've made the commit message clearer.
> test_lifecycleP
Sure, OK. I'll split the test in two (exception list and isTouchApp) and remove the sanity checks that duplicate checks in those tests. New commit coming.
Michael Terry (mterry) wrote : | # |
Alright. I made the requested test change. I still like having "control group" checks, but I understand the argument that those other test methods are the control group.
- 1996. By Michael Terry
-
Break test apart
Daniel d'Andrada (dandrader) wrote : | # |
Thanks for splitting it into smaller tests.
For the sake of clarity it's worth checking that libreoffice and webbrowser-app are not focused before the final compare() calls. Afterall, the only reason you launched a second app after them was to get them unfocused. A check (and/or comment) would make your intent clear.
- 1997. By Michael Terry
-
Also confirm that app no longer has focus
Michael Terry (mterry) wrote : | # |
> For the sake of clarity it's worth checking that libreoffice
> and webbrowser-app are not focused before the final compare() calls.
Done.
- 1998. By Michael Terry
-
Add quick clarifying comment
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1996
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1998
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 1999. By Michael Terry
-
Bump shell application version
- 2000. By Michael Terry
-
Bump shell application version harder
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2000
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 2001. By Michael Terry
-
Whoops, remove testing changes
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2001
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Gerry Boland (gerboland) wrote : | # |
Tested on device, unable to detect any regression, looks good!
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2015-10-21 11:51:38 +0000 |
3 | +++ CMakeLists.txt 2015-11-03 20:18:21 +0000 |
4 | @@ -57,7 +57,7 @@ |
5 | find_package(Qt5Concurrent 5.2 REQUIRED) |
6 | find_package(Qt5Sql 5.2 REQUIRED) |
7 | |
8 | -pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=9) |
9 | +pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=10) |
10 | |
11 | # Standard install paths |
12 | include(GNUInstallDirs) |
13 | |
14 | === modified file 'debian/control' |
15 | --- debian/control 2015-10-21 11:51:11 +0000 |
16 | +++ debian/control 2015-11-03 20:18:21 +0000 |
17 | @@ -127,7 +127,7 @@ |
18 | qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.3.1627) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.3.1627), |
19 | qtdeclarative5-unity-notifications-plugin (>= 0.1.2) | unity-notifications-impl, |
20 | ubuntu-thumbnailer-impl-0, |
21 | - unity-application-impl-9, |
22 | + unity-application-impl-10, |
23 | unity-notifications-impl-3, |
24 | unity-plugin-scopes | unity-scopes-impl, |
25 | unity-scopes-impl-7, |
26 | @@ -173,7 +173,7 @@ |
27 | Depends: ${misc:Depends}, |
28 | ${shlibs:Depends}, |
29 | Provides: unity-application-impl, |
30 | - unity-application-impl-9, |
31 | + unity-application-impl-10, |
32 | Replaces: unity8-autopilot (<< 8.02+15.04.20150422-0ubuntu1) |
33 | Description: Fake environment for running Unity 8 shell |
34 | Provides fake implementations of some QML modules used by Unity 8 shell |
35 | |
36 | === added file 'qml/Stages/AbstractStage.qml' |
37 | --- qml/Stages/AbstractStage.qml 1970-01-01 00:00:00 +0000 |
38 | +++ qml/Stages/AbstractStage.qml 2015-11-03 20:18:21 +0000 |
39 | @@ -0,0 +1,63 @@ |
40 | +/* |
41 | + * Copyright (C) 2015 Canonical, Ltd. |
42 | + * |
43 | + * This program is free software; you can redistribute it and/or modify |
44 | + * it under the terms of the GNU General Public License as published by |
45 | + * the Free Software Foundation; version 3. |
46 | + * |
47 | + * This program is distributed in the hope that it will be useful, |
48 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
49 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
50 | + * GNU General Public License for more details. |
51 | + * |
52 | + * You should have received a copy of the GNU General Public License |
53 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
54 | + */ |
55 | + |
56 | +import QtQuick 2.4 |
57 | +import Ubuntu.Components 1.3 |
58 | +import GSettings 1.0 |
59 | + |
60 | +Rectangle { |
61 | + id: root |
62 | + |
63 | + color: "#111111" |
64 | + |
65 | + // Controls to be set from outside |
66 | + property bool altTabPressed |
67 | + property url background |
68 | + property bool beingResized |
69 | + property int dragAreaWidth |
70 | + property bool interactive |
71 | + property real inverseProgress // This is the progress for left edge drags, in pixels. |
72 | + property bool keepDashRunning: true |
73 | + property real maximizedAppTopMargin |
74 | + property real nativeHeight |
75 | + property real nativeWidth |
76 | + property QtObject orientations |
77 | + property int shellOrientation |
78 | + property int shellOrientationAngle |
79 | + property bool spreadEnabled: true // If false, animations and right edge will be disabled |
80 | + property bool suspended |
81 | + |
82 | + // To be read from outside |
83 | + property var mainApp: null |
84 | + property int mainAppWindowOrientationAngle |
85 | + property bool orientationChangesEnabled |
86 | + |
87 | + // Shared code for use in stage implementations |
88 | + GSettings { |
89 | + id: lifecycleExceptions |
90 | + schema.id: "com.canonical.qtmir" |
91 | + } |
92 | + |
93 | + function isExemptFromLifecycle(appId) { |
94 | + var shortAppId = appId.split('_')[0]; |
95 | + for (var i = 0; i < lifecycleExceptions.lifecycleExemptAppids.length; i++) { |
96 | + if (shortAppId === lifecycleExceptions.lifecycleExemptAppids[i]) { |
97 | + return true; |
98 | + } |
99 | + } |
100 | + return false; |
101 | + } |
102 | +} |
103 | |
104 | === modified file 'qml/Stages/DesktopStage.qml' |
105 | --- qml/Stages/DesktopStage.qml 2015-11-03 20:18:21 +0000 |
106 | +++ qml/Stages/DesktopStage.qml 2015-11-03 20:18:21 +0000 |
107 | @@ -26,35 +26,17 @@ |
108 | import Utils 0.1 |
109 | import Ubuntu.Gestures 0.1 |
110 | |
111 | -Rectangle { |
112 | +AbstractStage { |
113 | id: root |
114 | anchors.fill: parent |
115 | |
116 | - // Controls to be set from outside |
117 | - property int dragAreaWidth // just to comply with the interface shared between stages |
118 | - property real maximizedAppTopMargin |
119 | - property bool interactive |
120 | - property bool spreadEnabled // just to comply with the interface shared between stages |
121 | - property real inverseProgress: 0 // just to comply with the interface shared between stages |
122 | - property int shellOrientationAngle: 0 |
123 | - property int shellOrientation |
124 | - property QtObject orientations |
125 | - property bool beingResized: false |
126 | - property bool keepDashRunning: true |
127 | - property bool suspended: false |
128 | - property alias background: wallpaper.source |
129 | - property alias altTabPressed: spread.altTabPressed |
130 | - |
131 | // functions to be called from outside |
132 | function updateFocusedAppOrientation() { /* TODO */ } |
133 | function updateFocusedAppOrientationAnimated() { /* TODO */} |
134 | |
135 | - // To be read from outside |
136 | - readonly property var mainApp: ApplicationManager.focusedApplicationId |
137 | + mainApp: ApplicationManager.focusedApplicationId |
138 | ? ApplicationManager.findApplication(ApplicationManager.focusedApplicationId) |
139 | : null |
140 | - property int mainAppWindowOrientationAngle: 0 |
141 | - readonly property bool orientationChangesEnabled: false |
142 | |
143 | Connections { |
144 | target: ApplicationManager |
145 | @@ -122,6 +104,7 @@ |
146 | CrossFadeImage { |
147 | id: wallpaper |
148 | anchors.fill: parent |
149 | + source: root.background |
150 | sourceSize { height: root.height; width: root.width } |
151 | fillMode: Image.PreserveAspectCrop |
152 | } |
153 | @@ -275,5 +258,6 @@ |
154 | anchors.fill: parent |
155 | workspace: appContainer |
156 | focus: state == "altTab" |
157 | + altTabPressed: root.altTabPressed |
158 | } |
159 | } |
160 | |
161 | === modified file 'qml/Stages/PhoneStage.qml' |
162 | --- qml/Stages/PhoneStage.qml 2015-11-03 20:18:21 +0000 |
163 | +++ qml/Stages/PhoneStage.qml 2015-11-03 20:18:21 +0000 |
164 | @@ -22,29 +22,15 @@ |
165 | import Utils 0.1 |
166 | import "../Components" |
167 | |
168 | -Rectangle { |
169 | +AbstractStage { |
170 | id: root |
171 | |
172 | - // Controls to be set from outside |
173 | - property int dragAreaWidth |
174 | - property real maximizedAppTopMargin |
175 | - property bool interactive |
176 | - property bool spreadEnabled: true // If false, animations and right edge will be disabled |
177 | - property real inverseProgress: 0 // This is the progress for left edge drags, in pixels. |
178 | property QtObject applicationManager: ApplicationManager |
179 | property bool focusFirstApp: true // If false, focused app will appear on right edge like other apps |
180 | property bool altTabEnabled: true |
181 | property real startScale: 1.1 |
182 | property real endScale: 0.7 |
183 | - property bool keepDashRunning: true |
184 | - property bool suspended: false |
185 | - property int shellOrientationAngle: 0 |
186 | |
187 | - property int shellOrientation |
188 | - property QtObject orientations |
189 | - property real nativeWidth |
190 | - property real nativeHeight |
191 | - property bool beingResized: false |
192 | onBeingResizedChanged: { |
193 | if (beingResized) { |
194 | // Brace yourselves for impact! |
195 | @@ -56,6 +42,8 @@ |
196 | priv.reset(); |
197 | } |
198 | } |
199 | + |
200 | + // Functions to be called from outside |
201 | function updateFocusedAppOrientation() { |
202 | if (spreadRepeater.count > 0) { |
203 | spreadRepeater.itemAt(0).matchShellOrientation(); |
204 | @@ -85,16 +73,14 @@ |
205 | } |
206 | } |
207 | |
208 | - // To be read from outside |
209 | - readonly property var mainApp: applicationManager.focusedApplicationId |
210 | + mainApp: applicationManager.focusedApplicationId |
211 | ? applicationManager.findApplication(applicationManager.focusedApplicationId) |
212 | : null |
213 | |
214 | - property int mainAppWindowOrientationAngle: 0 |
215 | - readonly property bool orientationChangesEnabled: priv.focusedAppOrientationChangesEnabled |
216 | - && !priv.focusedAppDelegateIsDislocated |
217 | - && !(priv.focusedAppDelegate && priv.focusedAppDelegate.xBehavior.running) |
218 | - && spreadView.phase === 0 |
219 | + orientationChangesEnabled: priv.focusedAppOrientationChangesEnabled |
220 | + && !priv.focusedAppDelegateIsDislocated |
221 | + && !(priv.focusedAppDelegate && priv.focusedAppDelegate.xBehavior.running) |
222 | + && spreadView.phase === 0 |
223 | |
224 | // How far left the stage has been dragged |
225 | readonly property real dragProgress: spreadRepeater.count > 0 ? -spreadRepeater.itemAt(0).xTranslate : 0 |
226 | @@ -106,8 +92,6 @@ |
227 | |
228 | signal opened() |
229 | |
230 | - color: "#111111" |
231 | - |
232 | function select(appId) { |
233 | spreadView.snapTo(priv.indexOf(appId)); |
234 | } |
235 | @@ -438,16 +422,21 @@ |
236 | dropShadow: spreadView.active || priv.focusedAppDelegateIsDislocated |
237 | focusFirstApp: root.focusFirstApp |
238 | |
239 | + readonly property bool isDash: model.appId == "unity8-dash" |
240 | + |
241 | + readonly property bool canSuspend: model.isTouchApp |
242 | + && !isExemptFromLifecycle(model.appId) |
243 | + |
244 | Binding { |
245 | target: appDelegate.application |
246 | property: "requestedState" |
247 | - value: (isDash && root.keepDashRunning) || (!root.suspended && appDelegate.focus) |
248 | - ? ApplicationInfoInterface.RequestedRunning |
249 | - : ApplicationInfoInterface.RequestedSuspended |
250 | + value: !canSuspend |
251 | + || (isDash && root.keepDashRunning) |
252 | + || (!root.suspended && appDelegate.focus) |
253 | + ? ApplicationInfoInterface.RequestedRunning |
254 | + : ApplicationInfoInterface.RequestedSuspended |
255 | } |
256 | |
257 | - readonly property bool isDash: model.appId == "unity8-dash" |
258 | - |
259 | z: isDash && !spreadView.active ? -1 : behavioredIndex |
260 | |
261 | x: { |
262 | |
263 | === modified file 'qml/Stages/ShimStage.qml' |
264 | --- qml/Stages/ShimStage.qml 2015-04-21 19:43:25 +0000 |
265 | +++ qml/Stages/ShimStage.qml 2015-11-03 20:18:21 +0000 |
266 | @@ -17,7 +17,7 @@ |
267 | import QtQuick 2.3 |
268 | import Ubuntu.Components 0.1 |
269 | |
270 | -Rectangle { |
271 | +AbstractStage { |
272 | id: shimStage |
273 | |
274 | anchors.fill: parent |
275 | |
276 | === modified file 'qml/Stages/TabletStage.qml' |
277 | --- qml/Stages/TabletStage.qml 2015-11-03 20:18:21 +0000 |
278 | +++ qml/Stages/TabletStage.qml 2015-11-03 20:18:21 +0000 |
279 | @@ -21,30 +21,12 @@ |
280 | import Utils 0.1 |
281 | import "../Components" |
282 | |
283 | -Rectangle { |
284 | +AbstractStage { |
285 | id: root |
286 | objectName: "stages" |
287 | anchors.fill: parent |
288 | - color: "#111111" |
289 | - |
290 | - // Controls to be set from outside |
291 | - property int dragAreaWidth |
292 | - property real maximizedAppTopMargin |
293 | - property bool interactive |
294 | - property alias beingResized: spreadView.beingResized |
295 | - |
296 | - property bool spreadEnabled: true // If false, animations and right edge will be disabled |
297 | - |
298 | - property real inverseProgress: 0 // This is the progress for left edge drags, in pixels. |
299 | - property bool keepDashRunning: true |
300 | - property bool suspended: false |
301 | - property int shellOrientationAngle: 0 |
302 | - |
303 | - property int shellOrientation |
304 | - property QtObject orientations |
305 | - property real nativeWidth |
306 | - property real nativeHeight |
307 | - |
308 | + |
309 | + // Functions to be called from outside |
310 | function updateFocusedAppOrientation() { |
311 | var mainStageAppIndex = priv.indexOf(priv.mainStageAppId); |
312 | if (mainStageAppIndex >= 0 && mainStageAppIndex < spreadRepeater.count) { |
313 | @@ -87,10 +69,7 @@ |
314 | } |
315 | } |
316 | |
317 | - // To be read from outside |
318 | - property var mainApp: null |
319 | - property int mainAppWindowOrientationAngle: 0 |
320 | - readonly property bool orientationChangesEnabled: priv.mainAppOrientationChangesEnabled |
321 | + orientationChangesEnabled: priv.mainAppOrientationChangesEnabled |
322 | |
323 | onWidthChanged: { |
324 | spreadView.selectedIndex = -1; |
325 | @@ -303,7 +282,7 @@ |
326 | } |
327 | |
328 | property bool animateX: true |
329 | - property bool beingResized: false |
330 | + property bool beingResized: root.beingResized |
331 | onBeingResizedChanged: { |
332 | if (beingResized) { |
333 | // Brace yourselves for impact! |
334 | @@ -630,15 +609,18 @@ |
335 | |
336 | readonly property bool isDash: model.appId == "unity8-dash" |
337 | |
338 | + readonly property bool canSuspend: model.isTouchApp |
339 | + && !isExemptFromLifecycle(model.appId) |
340 | + |
341 | Binding { |
342 | target: spreadTile.application |
343 | property: "requestedState" |
344 | - value: (spreadTile.isDash && root.keepDashRunning) |
345 | - || |
346 | - (!root.suspended && (model.appId == priv.mainStageAppId |
347 | - || model.appId == priv.sideStageAppId)) |
348 | - ? ApplicationInfoInterface.RequestedRunning |
349 | - : ApplicationInfoInterface.RequestedSuspended |
350 | + value: !canSuspend |
351 | + || (isDash && root.keepDashRunning) |
352 | + || (!root.suspended && (model.appId == priv.mainStageAppId |
353 | + || model.appId == priv.sideStageAppId)) |
354 | + ? ApplicationInfoInterface.RequestedRunning |
355 | + : ApplicationInfoInterface.RequestedSuspended |
356 | } |
357 | |
358 | // FIXME: A regular binding doesn't update any more after closing an app. |
359 | |
360 | === added file 'qml/graphics/applicationIcons/libreoffice@18.png' |
361 | Binary files qml/graphics/applicationIcons/libreoffice@18.png 1970-01-01 00:00:00 +0000 and qml/graphics/applicationIcons/libreoffice@18.png 2015-11-03 20:18:21 +0000 differ |
362 | === modified file 'tests/mocks/GSettings.1.0/fake_gsettings.cpp' |
363 | --- tests/mocks/GSettings.1.0/fake_gsettings.cpp 2015-09-02 13:06:56 +0000 |
364 | +++ tests/mocks/GSettings.1.0/fake_gsettings.cpp 2015-11-03 20:18:21 +0000 |
365 | @@ -75,6 +75,19 @@ |
366 | } |
367 | } |
368 | |
369 | +QStringList GSettingsControllerQml::lifecycleExemptAppids() const |
370 | +{ |
371 | + return m_lifecycleExemptAppids; |
372 | +} |
373 | + |
374 | +void GSettingsControllerQml::setLifecycleExemptAppids(const QStringList &appIds) |
375 | +{ |
376 | + if (m_lifecycleExemptAppids != appIds) { |
377 | + m_lifecycleExemptAppids = appIds; |
378 | + Q_EMIT lifecycleExemptAppidsChanged(m_lifecycleExemptAppids); |
379 | + } |
380 | +} |
381 | + |
382 | GSettingsSchemaQml::GSettingsSchemaQml(QObject *parent): QObject(parent) { |
383 | } |
384 | |
385 | @@ -114,6 +127,8 @@ |
386 | this, &GSettingsQml::usageModeChanged); |
387 | connect(GSettingsControllerQml::instance(), &GSettingsControllerQml::lockedOutTimeChanged, |
388 | this, &GSettingsQml::lockedOutTimeChanged); |
389 | + connect(GSettingsControllerQml::instance(), &GSettingsControllerQml::lifecycleExemptAppidsChanged, |
390 | + this, &GSettingsQml::lifecycleExemptAppidsChanged); |
391 | } |
392 | |
393 | GSettingsSchemaQml * GSettingsQml::schema() const { |
394 | @@ -167,3 +182,19 @@ |
395 | GSettingsControllerQml::instance()->setLockedOutTime(timestamp); |
396 | } |
397 | } |
398 | + |
399 | +QStringList GSettingsQml::lifecycleExemptAppids() const |
400 | +{ |
401 | + if (m_schema->id() == "com.canonical.qtmir") { |
402 | + return GSettingsControllerQml::instance()->lifecycleExemptAppids(); |
403 | + } else { |
404 | + return QStringList(); |
405 | + } |
406 | +} |
407 | + |
408 | +void GSettingsQml::setLifecycleExemptAppids(const QStringList &appIds) |
409 | +{ |
410 | + if (m_schema->id() == "com.canonical.qtmir") { |
411 | + GSettingsControllerQml::instance()->setLifecycleExemptAppids(appIds); |
412 | + } |
413 | +} |
414 | |
415 | === modified file 'tests/mocks/GSettings.1.0/fake_gsettings.h' |
416 | --- tests/mocks/GSettings.1.0/fake_gsettings.h 2015-08-19 23:41:18 +0000 |
417 | +++ tests/mocks/GSettings.1.0/fake_gsettings.h 2015-11-03 20:18:21 +0000 |
418 | @@ -19,6 +19,7 @@ |
419 | |
420 | #include <QList> |
421 | #include <QObject> |
422 | +#include <QStringList> |
423 | |
424 | class GSettingsSchemaQml: public QObject |
425 | { |
426 | @@ -48,6 +49,7 @@ |
427 | Q_PROPERTY(QString pictureUri READ pictureUri WRITE setPictureUri NOTIFY pictureUriChanged) |
428 | Q_PROPERTY(QString usageMode READ usageMode WRITE setUsageMode NOTIFY usageModeChanged) |
429 | Q_PROPERTY(qint64 lockedOutTime READ lockedOutTime WRITE setLockedOutTime NOTIFY lockedOutTimeChanged) |
430 | + Q_PROPERTY(QStringList lifecycleExemptAppids READ lifecycleExemptAppids WRITE setLifecycleExemptAppids NOTIFY lifecycleExemptAppidsChanged) |
431 | |
432 | public: |
433 | GSettingsQml(QObject *parent = nullptr); |
434 | @@ -56,16 +58,19 @@ |
435 | QString pictureUri() const; |
436 | QString usageMode() const; |
437 | qint64 lockedOutTime() const; |
438 | + QStringList lifecycleExemptAppids() const; |
439 | |
440 | void setPictureUri(const QString &str); |
441 | void setUsageMode(const QString &usageMode); |
442 | void setLockedOutTime(qint64 timestamp); |
443 | + void setLifecycleExemptAppids(const QStringList &appIds); |
444 | |
445 | Q_SIGNALS: |
446 | void schemaChanged(); |
447 | void pictureUriChanged(const QString&); |
448 | void usageModeChanged(const QString&); |
449 | void lockedOutTimeChanged(qint64); |
450 | + void lifecycleExemptAppidsChanged(const QStringList &); |
451 | |
452 | private: |
453 | GSettingsSchemaQml* m_schema; |
454 | @@ -90,10 +95,14 @@ |
455 | qint64 lockedOutTime() const; |
456 | Q_INVOKABLE void setLockedOutTime(qint64 timestamp); |
457 | |
458 | + QStringList lifecycleExemptAppids() const; |
459 | + Q_INVOKABLE void setLifecycleExemptAppids(const QStringList &appIds); |
460 | + |
461 | Q_SIGNALS: |
462 | void pictureUriChanged(const QString&); |
463 | void usageModeChanged(const QString&); |
464 | void lockedOutTimeChanged(qint64 timestamp); |
465 | + void lifecycleExemptAppidsChanged(const QStringList&); |
466 | |
467 | private: |
468 | GSettingsControllerQml(); |
469 | @@ -101,6 +110,7 @@ |
470 | QString m_pictureUri; |
471 | QString m_usageMode; |
472 | qint64 m_lockedOutTime; |
473 | + QStringList m_lifecycleExemptAppids; |
474 | |
475 | static GSettingsControllerQml* s_controllerInstance; |
476 | QList<GSettingsQml *> m_registeredGSettings; |
477 | |
478 | === modified file 'tests/mocks/Unity/Application/ApplicationInfo.cpp' |
479 | --- tests/mocks/Unity/Application/ApplicationInfo.cpp 2015-08-31 10:25:07 +0000 |
480 | +++ tests/mocks/Unity/Application/ApplicationInfo.cpp 2015-11-03 20:18:21 +0000 |
481 | @@ -41,6 +41,7 @@ |
482 | Qt::InvertedLandscapeOrientation) |
483 | , m_rotatesWindowContents(false) |
484 | , m_requestedState(RequestedRunning) |
485 | + , m_isTouchApp(true) |
486 | , m_manualSurfaceCreation(false) |
487 | { |
488 | } |
489 | @@ -58,6 +59,7 @@ |
490 | Qt::InvertedLandscapeOrientation) |
491 | , m_rotatesWindowContents(false) |
492 | , m_requestedState(RequestedRunning) |
493 | + , m_isTouchApp(true) |
494 | , m_manualSurfaceCreation(false) |
495 | { |
496 | } |
497 | @@ -245,6 +247,16 @@ |
498 | } |
499 | } |
500 | |
501 | +bool ApplicationInfo::isTouchApp() const |
502 | +{ |
503 | + return m_isTouchApp; |
504 | +} |
505 | + |
506 | +void ApplicationInfo::setIsTouchApp(bool isTouchApp) |
507 | +{ |
508 | + m_isTouchApp = isTouchApp; |
509 | +} |
510 | + |
511 | void ApplicationInfo::onSessionSurfaceChanged(MirSurface* surface) |
512 | { |
513 | if (surface != nullptr && m_state == Starting) { |
514 | |
515 | === modified file 'tests/mocks/Unity/Application/ApplicationInfo.h' |
516 | --- tests/mocks/Unity/Application/ApplicationInfo.h 2015-08-03 15:00:47 +0000 |
517 | +++ tests/mocks/Unity/Application/ApplicationInfo.h 2015-11-03 20:18:21 +0000 |
518 | @@ -89,6 +89,9 @@ |
519 | bool manualSurfaceCreation() const { return m_manualSurfaceCreation; } |
520 | void setManualSurfaceCreation(bool value); |
521 | |
522 | + bool isTouchApp() const override; |
523 | + void setIsTouchApp(bool isTouchApp); // only in mock |
524 | + |
525 | public: |
526 | void setSession(Session* session); |
527 | Session* session() const { return m_session; } |
528 | @@ -121,6 +124,7 @@ |
529 | Qt::ScreenOrientations m_supportedOrientations; |
530 | bool m_rotatesWindowContents; |
531 | RequestedState m_requestedState; |
532 | + bool m_isTouchApp; |
533 | |
534 | bool m_manualSurfaceCreation; |
535 | }; |
536 | |
537 | === modified file 'tests/mocks/Unity/Application/ApplicationManager.cpp' |
538 | --- tests/mocks/Unity/Application/ApplicationManager.cpp 2015-08-03 13:47:44 +0000 |
539 | +++ tests/mocks/Unity/Application/ApplicationManager.cpp 2015-11-03 20:18:21 +0000 |
540 | @@ -105,6 +105,8 @@ |
541 | return app->state(); |
542 | case RoleFocused: |
543 | return app->focused(); |
544 | + case RoleIsTouchApp: |
545 | + return app->isTouchApp(); |
546 | case RoleSession: |
547 | return QVariant::fromValue(app->session()); |
548 | case RoleFullscreen: |
549 | @@ -458,6 +460,13 @@ |
550 | application->setName("YouTube"); |
551 | application->setIconId("youtube"); |
552 | m_availableApplications.append(application); |
553 | + |
554 | + application = new ApplicationInfo(this); |
555 | + application->setAppId("libreoffice"); |
556 | + application->setName("LibreOffice"); |
557 | + application->setIconId("libreoffice"); |
558 | + application->setIsTouchApp(false); |
559 | + m_availableApplications.append(application); |
560 | } |
561 | |
562 | |
563 | |
564 | === modified file 'tests/mocks/Unity/Application/ApplicationManager.h' |
565 | --- tests/mocks/Unity/Application/ApplicationManager.h 2015-06-19 18:19:33 +0000 |
566 | +++ tests/mocks/Unity/Application/ApplicationManager.h 2015-11-03 20:18:21 +0000 |
567 | @@ -43,7 +43,7 @@ |
568 | static ApplicationManager *singleton(); |
569 | |
570 | enum MoreRoles { |
571 | - RoleSession = RoleFocused+1, |
572 | + RoleSession = RoleIsTouchApp+1, |
573 | RoleFullscreen, |
574 | }; |
575 | enum Flag { |
576 | |
577 | === modified file 'tests/plugins/Unity/Launcher/launchermodeltest.cpp' |
578 | --- tests/plugins/Unity/Launcher/launchermodeltest.cpp 2015-08-19 14:24:07 +0000 |
579 | +++ tests/plugins/Unity/Launcher/launchermodeltest.cpp 2015-11-03 20:18:21 +0000 |
580 | @@ -57,6 +57,7 @@ |
581 | QColor splashColorFooter() const override { return QColor(0,0,0,0); } |
582 | Qt::ScreenOrientations supportedOrientations() const override { return Qt::PortraitOrientation; } |
583 | bool rotatesWindowContents() const override { return false; } |
584 | + bool isTouchApp() const override { return true; } |
585 | |
586 | // Methods used for mocking (not in the interface) |
587 | void setFocused(bool focused) { m_focused = focused; Q_EMIT focusedChanged(focused); } |
588 | |
589 | === modified file 'tests/qmltests/tst_Shell.qml' |
590 | --- tests/qmltests/tst_Shell.qml 2015-11-03 20:18:21 +0000 |
591 | +++ tests/qmltests/tst_Shell.qml 2015-11-03 20:18:21 +0000 |
592 | @@ -380,6 +380,8 @@ |
593 | LightDM.Greeter.authenticate(""); // reset greeter |
594 | |
595 | sessionSpy.clear(); |
596 | + |
597 | + GSettingsController.setLifecycleExemptAppids([]); |
598 | } |
599 | |
600 | function killApps() { |
601 | @@ -1780,5 +1782,50 @@ |
602 | waitForRendering(shell); |
603 | tryCompare(panelButtons, "visible", true); |
604 | } |
605 | + |
606 | + function test_lifecyclePolicyForNonTouchApp_data() { |
607 | + return [ |
608 | + {tag: "phone", formFactor: "phone", usageScenario: "phone"}, |
609 | + {tag: "tablet", formFactor: "tablet", usageScenario: "tablet"} |
610 | + ] |
611 | + } |
612 | + |
613 | + function test_lifecyclePolicyForNonTouchApp(data) { |
614 | + loadShell(data.formFactor); |
615 | + shell.usageScenario = data.usageScenario; |
616 | + |
617 | + var app1 = ApplicationManager.startApplication("libreoffice"); |
618 | + waitUntilAppWindowIsFullyLoaded(app1); |
619 | + var app2 = ApplicationManager.startApplication("dialer-app"); |
620 | + waitUntilAppWindowIsFullyLoaded(app2); |
621 | + |
622 | + // Make sure app1 is unfocused but still running |
623 | + compare(app1.session.surface.activeFocus, false); |
624 | + compare(app1.isTouchApp, false); // sanity check our mock, which sets this for us |
625 | + compare(app1.requestedState, ApplicationInfoInterface.RequestedRunning); |
626 | + } |
627 | + |
628 | + function test_lifecyclePolicyExemption_data() { |
629 | + return [ |
630 | + {tag: "phone", formFactor: "phone", usageScenario: "phone", suspendsApps: true}, |
631 | + {tag: "tablet", formFactor: "tablet", usageScenario: "tablet", suspendsApps: true} |
632 | + ] |
633 | + } |
634 | + |
635 | + function test_lifecyclePolicyExemption(data) { |
636 | + loadShell(data.formFactor); |
637 | + shell.usageScenario = data.usageScenario; |
638 | + |
639 | + GSettingsController.setLifecycleExemptAppids(["webbrowser-app"]); |
640 | + |
641 | + var app1 = ApplicationManager.startApplication("webbrowser-app"); |
642 | + waitUntilAppWindowIsFullyLoaded(app1); |
643 | + var app2 = ApplicationManager.startApplication("dialer-app"); |
644 | + waitUntilAppWindowIsFullyLoaded(app2); |
645 | + |
646 | + // Make sure app1 is unfocused but still running |
647 | + compare(app1.session.surface.activeFocus, false); |
648 | + compare(app1.requestedState, ApplicationInfoInterface.RequestedRunning); |
649 | + } |
650 | } |
651 | } |
FAILED: Continuous integration, rev:1989 jenkins. qa.ubuntu. com/job/ unity8- ci/6394/ jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- vivid-touch/ 4443/console jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- wily-touch/ 772/console jenkins. qa.ubuntu. com/job/ unity-phablet- qmluitests- vivid/1106/ console jenkins. qa.ubuntu. com/job/ unity-phablet- qmluitests- wily/424/ console jenkins. qa.ubuntu. com/job/ unity8- vivid-amd64- ci/1001/ console jenkins. qa.ubuntu. com/job/ unity8- vivid-i386- ci/1002/ console jenkins. qa.ubuntu. com/job/ unity8- wily-amd64- ci/633/ console jenkins. qa.ubuntu. com/job/ unity8- wily-i386- ci/634/ console jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- vivid-armhf/ 4440/console jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- wily-armhf/ 772/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity8- ci/6394/ rebuild
http://