Merge lp:~nick-dedekind/unity8/lp1475678.surface-occlude into lp:unity8

Proposed by Nick Dedekind on 2015-10-05
Status: Superseded
Proposed branch: lp:~nick-dedekind/unity8/lp1475678.surface-occlude
Merge into: lp:unity8
Diff against target: 510 lines (+233/-35)
9 files modified
debian/control (+1/-1)
qml/Stages/DesktopStage.qml (+71/-3)
qml/Stages/PhoneStage.qml (+10/-3)
qml/Stages/TabletStage.qml (+8/-0)
tests/mocks/Unity/Application/MirSurface.cpp (+44/-17)
tests/mocks/Unity/Application/MirSurface.h (+14/-4)
tests/mocks/Unity/Application/MirSurfaceItem.cpp (+12/-2)
tests/mocks/Unity/Application/MirSurfaceItem.h (+1/-0)
tests/qmltests/Stages/tst_DesktopStage.qml (+72/-5)
To merge this branch: bzr merge lp:~nick-dedekind/unity8/lp1475678.surface-occlude
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing on 2015-10-27
Michał Sawicz Needs Fixing on 2015-10-26
Michael Zanetti (community) Abstain on 2015-10-21
Daniel d'Andrada (community) 2015-10-05 Needs Fixing on 2015-10-13
Review via email: mp+273427@code.launchpad.net

This proposal has been superseded by a proposal from 2015-10-27.

Commit message

Support server->client visibility change to stop rendering (lp:#1475678)

Description of the change

Support server->client visibility change to stop rendering (lp:#1475678)

 * Are there any related MPs required for this MP to build/function as expected? Please list.
https://code.launchpad.net/~nick-dedekind/qtmir/lp1475678.surface-occlude/+merge/273426
https://code.launchpad.net/~nick-dedekind/unity-api/lp1475678.surface-occlude/+merge/273425
https://code.launchpad.net/~nick-dedekind/qtubuntu/lp1475678.surface-occlude/+merge/273424

 * Did you perform an exploratory manual test run of your code change and any related functionality?
 * Did you make sure that your branch does not contain spurious tags?
 * If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
 * If you changed the UI, has there been a design review?

To post a comment you must log in.
1974. By Nick Dedekind on 2015-10-06

occlude on screen power

Daniel d'Andrada (dandrader) wrote :

In qml/Stages/TabletStage.qml:

"""
+ // Hiding tiles when their progress is negative or reached the maximum
"""

A TODO item?

review: Needs Information
1975. By Nick Dedekind on 2015-10-12

update hide comment

Nick Dedekind (nick-dedekind) wrote :

> In qml/Stages/TabletStage.qml:
>
> """
> + // Hiding tiles when their progress is negative or reached the maximum
> """
>
> A TODO item?

Yes. Fixed.

Daniel d'Andrada (dandrader) wrote :

Shouldn't we do something for DesktopStage.qml as well? I quickly checked its code and it seems it doesn't set windows visibility at all.

Things to check:
 - Minimized windows should have their MirSurfaces invisible/occluded.
 - When a window is focused (on foreground, index 0) and maximized, the MirSurfaces of all others should be invisible/occluded

review: Needs Fixing
Michał Sawicz (saviq) wrote :

W dniu 13.10.2015 o 14:41, Daniel d'Andrada pisze:
> Things to check:
> - Minimized windows should have their MirSurfaces invisible/occluded.
> - When a window is focused (on foreground, index 0) and maximized, the MirSurfaces of all others should be invisible/occluded

And (maybe later) we should actually try and determine real visibility -
if a window is completely covered by others (we should probably exclude
windows with alpha from this), it should be made invisible/occluded, too.

Lukáš Tinkl (lukas-kde) wrote :

Left some inline comments; also:

> When a window is focused (on foreground, index 0) and maximized, the MirSurfaces of all others
> should be invisible/occluded

Just wondering what happens in multi monitor situations, should all the other windows/surfaces get occluded too in this case?

Daniel d'Andrada (dandrader) wrote :

On 13/10/2015 10:32, Lukáš Tinkl wrote:
>> When a window is focused (on foreground, index 0) and maximized, the MirSurfaces of all others
>> >should be invisible/occluded
> Just wondering what happens in multi monitor situations, should all the other windows/surfaces get occluded too in this case?

Since multimonitor hasn't landed and this branch does not build on top
of it, it can't really address multimonitor issues here. Furthermore, on
the first iteration, windows will be shown all in a single screen (be it
the built-in display or an external monitor), so multimonitor doesn't
really affect occlusion scenarios right now.

1976. By Nick Dedekind on 2015-10-13

dekstop stage item visibility

Nick Dedekind (nick-dedekind) wrote :

> Shouldn't we do something for DesktopStage.qml as well? I quickly checked its
> code and it seems it doesn't set windows visibility at all.
>
> Things to check:
> - Minimized windows should have their MirSurfaces invisible/occluded.
> - When a window is focused (on foreground, index 0) and maximized, the
> MirSurfaces of all others should be invisible/occluded

Added.

Daniel d'Andrada (dandrader) wrote :

Could you please add a qml test to tst_DesktopStage to cover the "hide windows behind the maximized one" feature? Logic looks involved enough to warrant a test.

Michael Zanetti (mzanetti) wrote :

* Open 2 windows so that both are visible. Maximize one, the other will disappear before it's occluded.

* It breaks the alt+tab preview.

review: Needs Fixing
1977. By Nick Dedekind on 2015-10-20

fixed surface visibility

Michael Zanetti (mzanetti) wrote :

> * Open 2 windows so that both are visible. Maximize one, the other will
> disappear before it's occluded.
>
> * It breaks the alt+tab preview.

Both seem to be fixed now.

review: Abstain
1978. By Nick Dedekind on 2015-10-22

Only visible if in front of maximized application

Michał Sawicz (saviq) :
review: Needs Fixing
1979. By Nick Dedekind on 2015-10-26

merged with trunk

1980. By Nick Dedekind on 2015-10-26

bump libunity-api version

Unmerged revisions

1980. By Nick Dedekind on 2015-10-26

bump libunity-api version

1979. By Nick Dedekind on 2015-10-26

merged with trunk

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/control'
2--- debian/control 2015-10-21 11:51:11 +0000
3+++ debian/control 2015-10-26 18:36:26 +0000
4@@ -29,7 +29,7 @@
5 libqt5xmlpatterns5-dev,
6 libsystemsettings-dev,
7 libudev-dev,
8- libunity-api-dev (>= 7.101),
9+ libunity-api-dev (>= 7.102),
10 libusermetricsoutput1-dev,
11 libxcb1-dev,
12 pkg-config,
13
14=== modified file 'qml/Stages/DesktopStage.qml'
15--- qml/Stages/DesktopStage.qml 2015-10-19 14:27:57 +0000
16+++ qml/Stages/DesktopStage.qml 2015-10-26 18:36:26 +0000
17@@ -65,6 +65,11 @@
18
19 ApplicationManager.requestFocusApplication(appId)
20 }
21+ onApplicationRemoved: {
22+ if (priv.foregroundMaximizedAppId === appId) {
23+ priv.foregroundMaximizedAppIdIndex = -1;
24+ }
25+ }
26
27 onFocusRequested: {
28 var appIndex = priv.indexOf(appId);
29@@ -86,6 +91,17 @@
30 var index = indexOf(focusedAppId);
31 return index >= 0 && index < appRepeater.count ? appRepeater.itemAt(index) : null
32 }
33+ readonly property string foregroundMaximizedAppId: {
34+ if (foregroundMaximizedAppIdIndex == -1) {
35+ return "";
36+ }
37+ var app = ApplicationManager.get(foregroundMaximizedAppIdIndex);
38+ if (app) {
39+ return app.appId;
40+ }
41+ return "";
42+ }
43+ property int foregroundMaximizedAppIdIndex: -1
44
45 function indexOf(appId) {
46 for (var i = 0; i < ApplicationManager.count; i++) {
47@@ -132,6 +148,7 @@
48
49 delegate: FocusScope {
50 id: appDelegate
51+ objectName: "stageDelegate_" + model.appId
52 z: ApplicationManager.count - index
53 y: units.gu(3)
54 width: units.gu(60)
55@@ -141,12 +158,47 @@
56 property bool maximized: false
57 property bool minimized: false
58
59+ property bool visuallyMaximized: false
60+ property bool visuallyMinimized: false
61+
62 onFocusChanged: {
63 if (focus && ApplicationManager.focusedApplicationId !== model.appId) {
64 ApplicationManager.focusApplication(model.appId);
65 }
66 }
67
68+ onZChanged: updateMaximized()
69+ onVisuallyMaximizedChanged: updateMaximized()
70+ Connections {
71+ target: priv
72+ onForegroundMaximizedAppIdIndexChanged: updateMaximized()
73+ }
74+
75+ property bool connectMaxEnabled: true
76+ function updateMaximized() {
77+ if (!connectMaxEnabled) return;
78+ connectMaxEnabled = false;
79+
80+ // work out if this is the top maximized app.
81+ if (visuallyMaximized) {
82+ if (priv.foregroundMaximizedAppId === model.appId) {
83+ priv.foregroundMaximizedAppIdIndex = index;
84+ }
85+ else if (priv.foregroundMaximizedAppIdIndex == -1 ||
86+ (index >= 0 && index <= priv.foregroundMaximizedAppIdIndex)) {
87+ priv.foregroundMaximizedAppIdIndex = index;
88+ }
89+ } else if (priv.foregroundMaximizedAppId === model.appId) {
90+ priv.foregroundMaximizedAppIdIndex = -1;
91+ }
92+
93+ connectMaxEnabled = true;
94+ }
95+
96+ visible: !visuallyMinimized &&
97+ (priv.foregroundMaximizedAppIdIndex === -1 || priv.foregroundMaximizedAppIdIndex >= index) ||
98+ (spread.focus && index === spread.highlightedIndex)
99+
100 Binding {
101 target: ApplicationManager.get(index)
102 property: "requestedState"
103@@ -186,9 +238,25 @@
104 ]
105 transitions: [
106 Transition {
107- from: "maximized,minimized,normal,"
108- to: "maximized,minimized,normal,"
109- PropertyAnimation { target: appDelegate; properties: "x,y,opacity,width,height,scale" }
110+ to: "normal"
111+ PropertyAction { target: appDelegate; properties: "visuallyMinimized,visuallyMaximized"; value: false }
112+ PropertyAnimation { target: appDelegate; properties: "x,y,opacity,width,height,scale," }
113+ },
114+ Transition {
115+ to: "maximized"
116+ SequentialAnimation {
117+ PropertyAction { target: appDelegate; property: "visuallyMinimized"; value: false }
118+ PropertyAnimation { target: appDelegate; properties: "x,y,opacity,width,height,scale" }
119+ PropertyAction { target: appDelegate; property: "visuallyMaximized"; value: true }
120+ }
121+ },
122+ Transition {
123+ to: "minimized"
124+ SequentialAnimation {
125+ PropertyAction { target: appDelegate; property: "visuallyMaximized"; value: false }
126+ PropertyAnimation { target: appDelegate; properties: "x,y,opacity,width,height,scale" }
127+ PropertyAction { target: appDelegate; property: "visuallyMinimized"; value: true }
128+ }
129 },
130 Transition {
131 from: ""
132
133=== modified file 'qml/Stages/PhoneStage.qml'
134--- qml/Stages/PhoneStage.qml 2015-09-21 13:37:47 +0000
135+++ qml/Stages/PhoneStage.qml 2015-10-26 18:36:26 +0000
136@@ -20,6 +20,7 @@
137 import Unity.Application 0.1
138 import Unity.Session 0.1
139 import Utils 0.1
140+import Powerd 0.1
141 import "../Components"
142
143 Rectangle {
144@@ -531,9 +532,15 @@
145 return progress;
146 }
147
148- // Hiding tiles when their progress is negative or reached the maximum
149- visible: (progress >= 0 && progress < 1.7)
150- || (isDash && priv.focusedAppDelegateIsDislocated)
151+ // Hide tile when progress is such that it will be off screen.
152+ property bool occluded: {
153+ if (spreadView.active && (progress >= 0 && progress < 1.7)) return false;
154+ if (!spreadView.active && isFocused) return false;
155+ return true;
156+ }
157+
158+ visible: Powerd.status == Powerd.On &&
159+ (!occluded || (isDash && priv.focusedAppDelegateIsDislocated))
160
161
162 shellOrientationAngle: root.shellOrientationAngle
163
164=== modified file 'qml/Stages/TabletStage.qml'
165--- qml/Stages/TabletStage.qml 2015-08-03 13:47:44 +0000
166+++ qml/Stages/TabletStage.qml 2015-10-26 18:36:26 +0000
167@@ -676,6 +676,14 @@
168 return tileProgress;
169 }
170
171+ // TODO: Hiding tile when progress is such that it will be off screen.
172+ property bool occluded: {
173+ if (spreadView.active) return false;
174+ else if (isFocused) return false;
175+ return true;
176+ }
177+ visible: !occluded
178+
179 animatedProgress: {
180 if (spreadView.phase == 0 && (spreadTile.active || spreadView.nextInStack == index)) {
181 if (progress < spreadView.positionMarker1) {
182
183=== modified file 'tests/mocks/Unity/Application/MirSurface.cpp'
184--- tests/mocks/Unity/Application/MirSurface.cpp 2015-09-25 12:13:13 +0000
185+++ tests/mocks/Unity/Application/MirSurface.cpp 2015-10-26 18:36:26 +0000
186@@ -31,7 +31,7 @@
187 , m_screenshotUrl(screenshot)
188 , m_qmlFilePath(qmlFilePath)
189 , m_live(true)
190- , m_viewCount(0)
191+ , m_visible(true)
192 , m_activeFocus(false)
193 , m_width(-1)
194 , m_height(-1)
195@@ -73,6 +73,11 @@
196 return m_live;
197 }
198
199+bool MirSurface::visible() const
200+{
201+ return m_visible;
202+}
203+
204 void MirSurface::setLive(bool live)
205 {
206 // qDebug().nospace() << "MirSurface::setLive("<<live<<") " << name();
207@@ -82,7 +87,7 @@
208 m_live = live;
209 Q_EMIT liveChanged(live);
210
211- if (!m_live && m_viewCount == 0) {
212+ if (!m_live && m_views.count() == 0) {
213 deleteLater();
214 }
215 }
216@@ -120,27 +125,49 @@
217 Q_EMIT orientationAngleChanged(angle);
218 }
219
220-void MirSurface::incrementViewCount()
221+
222+
223+void MirSurface::registerView(qintptr viewId)
224 {
225- ++m_viewCount;
226-// qDebug().nospace() << "MirSurface::incrementViewCount() viewCount(after)=" << m_viewCount << " " << name();
227+ m_views.insert(viewId, MirSurface::View{false});
228+// qDebug().nospace() << "MirSurface[" << name() << "]::registerView(" << viewId << ")"
229+// << " after=" << m_views.count();
230 }
231
232-void MirSurface::decrementViewCount()
233+void MirSurface::unregisterView(qintptr viewId)
234 {
235- --m_viewCount;
236-// qDebug().nospace() << "MirSurface::decrementViewCount() viewCount(after)=" << m_viewCount << " " << name();
237-
238- Q_ASSERT(m_viewCount >= 0);
239-
240- if (!m_live && m_viewCount == 0) {
241+// qDebug().nospace() << "MirSurface[" << name() << "]::unregisterView(" << viewId << ")"
242+// << " after=" << m_views.count() << " live=" << m_live;
243+ m_views.remove(viewId);
244+ if (!m_live && m_views.count() == 0) {
245 deleteLater();
246 }
247-}
248-
249-int MirSurface::viewCount() const
250-{
251- return m_viewCount;
252+ updateVisibility();
253+}
254+
255+void MirSurface::setViewVisibility(qintptr viewId, bool visible)
256+{
257+ if (!m_views.contains(viewId)) return;
258+
259+ m_views[viewId].visible = visible;
260+ updateVisibility();
261+}
262+
263+void MirSurface::updateVisibility()
264+{
265+ bool newVisible = false;
266+ QHashIterator<qintptr, View> i(m_views);
267+ while (i.hasNext()) {
268+ i.next();
269+ newVisible |= i.value().visible;
270+ }
271+
272+ if (newVisible != visible()) {
273+// qDebug().nospace() << "MirSurface[" << name() << "]::updateVisibility(" << newVisible << ")";
274+
275+ m_visible = newVisible;
276+ Q_EMIT visibleChanged(m_visible);
277+ }
278 }
279
280 bool MirSurface::activeFocus() const
281
282=== modified file 'tests/mocks/Unity/Application/MirSurface.h'
283--- tests/mocks/Unity/Application/MirSurface.h 2015-09-02 10:35:16 +0000
284+++ tests/mocks/Unity/Application/MirSurface.h 2015-10-26 18:36:26 +0000
285@@ -19,6 +19,7 @@
286
287 #include <QObject>
288 #include <QUrl>
289+#include <QHash>
290
291 // unity-api
292 #include <unity/shell/application/MirSurfaceInterface.h>
293@@ -58,6 +59,8 @@
294
295 bool live() const override;
296
297+ bool visible() const override;
298+
299 Mir::OrientationAngle orientationAngle() const override;
300 void setOrientationAngle(Mir::OrientationAngle) override;
301
302@@ -66,9 +69,10 @@
303
304 Q_INVOKABLE void setLive(bool live);
305
306- void incrementViewCount();
307- void decrementViewCount();
308- int viewCount() const;
309+ void registerView(qintptr viewId);
310+ void unregisterView(qintptr viewId);
311+ void setViewVisibility(qintptr viewId, bool visible);
312+ int viewCount() const { return m_views.count(); }
313
314 int width() const;
315 int height() const;
316@@ -97,6 +101,8 @@
317 void activeFocusChanged(bool);
318
319 private:
320+ void updateVisibility();
321+
322 const QString m_name;
323 const Mir::Type m_type;
324 Mir::State m_state;
325@@ -104,10 +110,14 @@
326 QUrl m_screenshotUrl;
327 QUrl m_qmlFilePath;
328 bool m_live;
329- int m_viewCount;
330+ bool m_visible;
331 bool m_activeFocus;
332 int m_width;
333 int m_height;
334+ struct View {
335+ bool visible;
336+ };
337+ QHash<qintptr, View> m_views;
338 };
339
340 #endif // MOCK_MIR_SURFACE_H
341
342=== modified file 'tests/mocks/Unity/Application/MirSurfaceItem.cpp'
343--- tests/mocks/Unity/Application/MirSurfaceItem.cpp 2015-09-25 12:13:13 +0000
344+++ tests/mocks/Unity/Application/MirSurfaceItem.cpp 2015-10-26 18:36:26 +0000
345@@ -44,6 +44,8 @@
346 Qt::ExtraButton5 | Qt::ExtraButton6 | Qt::ExtraButton7 | Qt::ExtraButton8 |
347 Qt::ExtraButton9 | Qt::ExtraButton10 | Qt::ExtraButton11 |
348 Qt::ExtraButton12 | Qt::ExtraButton13);
349+
350+ connect(this, &QQuickItem::visibleChanged, this, &MirSurfaceItem::updateMirSurfaceVisibility);
351 }
352
353 MirSurfaceItem::~MirSurfaceItem()
354@@ -194,17 +196,18 @@
355 m_qmlContentComponent = nullptr;
356
357 disconnect(m_qmlSurface, nullptr, this, nullptr);
358- m_qmlSurface->decrementViewCount();
359+ m_qmlSurface->unregisterView((qintptr)this);
360 }
361
362 m_qmlSurface = static_cast<MirSurface*>(surface);
363
364 if (m_qmlSurface) {
365- m_qmlSurface->incrementViewCount();
366+ m_qmlSurface->registerView((qintptr)this);
367
368 m_qmlSurface->setActiveFocus(hasActiveFocus());
369
370 updateSurfaceSize();
371+ updateMirSurfaceVisibility();
372
373 connect(m_qmlSurface, &MirSurface::orientationAngleChanged, this, &MirSurfaceItem::orientationAngleChanged);
374 connect(m_qmlSurface, &MirSurface::screenshotUrlChanged, this, &MirSurfaceItem::updateScreenshot);
375@@ -253,6 +256,13 @@
376 }
377 }
378
379+void MirSurfaceItem::updateMirSurfaceVisibility()
380+{
381+ if (!m_qmlSurface) return;
382+
383+ m_qmlSurface->setViewVisibility((qintptr)this, isVisible());
384+}
385+
386 void MirSurfaceItem::setConsumesInput(bool value)
387 {
388 if (m_consumesInput != value) {
389
390=== modified file 'tests/mocks/Unity/Application/MirSurfaceItem.h'
391--- tests/mocks/Unity/Application/MirSurfaceItem.h 2015-09-19 07:37:52 +0000
392+++ tests/mocks/Unity/Application/MirSurfaceItem.h 2015-10-26 18:36:26 +0000
393@@ -87,6 +87,7 @@
394 private Q_SLOTS:
395 void onComponentStatusChanged(QQmlComponent::Status status);
396 void updateScreenshot(QUrl screenshot);
397+ void updateMirSurfaceVisibility();
398
399 private:
400 void createQmlContentItem();
401
402=== modified file 'tests/qmltests/Stages/tst_DesktopStage.qml'
403--- tests/qmltests/Stages/tst_DesktopStage.qml 2015-09-17 12:25:29 +0000
404+++ tests/qmltests/Stages/tst_DesktopStage.qml 2015-10-26 18:36:26 +0000
405@@ -35,12 +35,15 @@
406 value: false
407 }
408
409- Component.onCompleted: {
410+ Component.onCompleted: resetGeometry()
411+
412+ function resetGeometry() {
413 // ensures apps which are tested decorations are in view.
414 WindowStateStorage.geometry = {
415 'unity8-dash': Qt.rect(0, units.gu(3), units.gu(50), units.gu(40)),
416 'dialer-app': Qt.rect(units.gu(51), units.gu(3), units.gu(50), units.gu(40)),
417 'camera-app': Qt.rect(0, units.gu(44), units.gu(50), units.gu(40)),
418+ 'gallery-app': Qt.rect(units.gu(51), units.gu(44), units.gu(50), units.gu(40))
419 }
420 }
421
422@@ -110,14 +113,14 @@
423
424 desktopStageLoader.active = true;
425 tryCompare(desktopStageLoader, "status", Loader.Ready);
426+ root.resetGeometry();
427 }
428
429 function killAllRunningApps() {
430- while (ApplicationManager.count > 1) {
431- var appIndex = ApplicationManager.get(0).appId == "unity8-dash" ? 1 : 0
432- ApplicationManager.stopApplication(ApplicationManager.get(appIndex).appId);
433+ while (ApplicationManager.count > 0) {
434+ ApplicationManager.stopApplication(ApplicationManager.get(0).appId);
435 }
436- compare(ApplicationManager.count, 1)
437+ compare(ApplicationManager.count, 0)
438 }
439
440 function waitUntilAppSurfaceShowsUp(appId) {
441@@ -210,5 +213,69 @@
442 tap(toAppDecoration);
443 tryCompare(ApplicationManager.findApplication(data.apps[data.focusTo]).session.surface, "activeFocus", true);
444 }
445+
446+ function test_minimizeApplicationHidesSurface(data) {
447+ var dashApp = startApplication("unity8-dash");
448+
449+ var dashDelegate = findChild(desktopStage, "stageDelegate_unity8-dash");
450+ verify(dashDelegate);
451+
452+ dashDelegate.minimize();
453+ tryCompare(dashApp.session.surface, "visible", false);
454+ }
455+
456+ function test_maximizeApplicationHidesSurfacesBehindIt(data) {
457+ var dashApp = startApplication("unity8-dash");
458+ var dialerApp = startApplication("dialer-app");
459+ var cameraApp = startApplication("camera-app");
460+
461+ var dashDelegate = findChild(desktopStage, "stageDelegate_unity8-dash");
462+ verify(dashDelegate);
463+ var dialerDelegate = findChild(desktopStage, "stageDelegate_dialer-app");
464+ verify(dialerDelegate);
465+ var cameraDelegate = findChild(desktopStage, "stageDelegate_camera-app");
466+ verify(cameraDelegate);
467+
468+ dialerDelegate.maximize();
469+ tryCompare(dialerDelegate, "visuallyMaximized", true);
470+
471+ tryCompare(dashApp.session.surface, "visible", false);
472+ compare(cameraApp.session.surface.visible, true);
473+
474+ dialerDelegate.unmaximize();
475+ compare(dashApp.session.surface.visible, true);
476+ compare(cameraApp.session.surface.visible, true);
477+ }
478+
479+ function test_applicationsBecomeVisibleWhenOccludingAppRemoved(data) {
480+ var dashApp = startApplication("unity8-dash");
481+ var dialerApp = startApplication("dialer-app");
482+ var cameraApp = startApplication("camera-app");
483+ var galleryApp = startApplication("gallery-app");
484+
485+ var dashDelegate = findChild(desktopStage, "stageDelegate_unity8-dash");
486+ verify(dashDelegate);
487+ var dialerDelegate = findChild(desktopStage, "stageDelegate_dialer-app");
488+ verify(dialerDelegate);
489+ var cameraDelegate = findChild(desktopStage, "stageDelegate_camera-app");
490+ verify(cameraDelegate);
491+ var galleryDelegate = findChild(desktopStage, "stageDelegate_gallery-app");
492+ verify(galleryDelegate);
493+
494+ dialerDelegate.maximize();
495+ galleryDelegate.maximize();
496+ tryCompare(dialerDelegate, "visuallyMaximized", true);
497+ tryCompare(galleryDelegate, "visuallyMaximized", true);
498+
499+ tryCompare(dashApp.session.surface, "visible", false);
500+ tryCompare(dialerApp.session.surface, "visible", false);
501+ tryCompare(cameraApp.session.surface, "visible", false);
502+
503+ ApplicationManager.stopApplication("gallery-app");
504+
505+ compare(cameraApp.session.surface.visible, true);
506+ tryCompare(dialerApp.session.surface, "visible", true);
507+ tryCompare(dashApp.session.surface, "visible", false); // still occluded by maximised dialer
508+ }
509 }
510 }

Subscribers

People subscribed via source and target branches