@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013-2015 Canonical, Ltd.
2+ * Copyright (C) 2013-2016 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -185,6 +185,17 @@ Rectangle {
185185 }
186186 }
187187 }
188+ Button {
189+ text: "Show Launcher"
190+ activeFocusOnPress: false
191+ onClicked: {
192+ if (shellLoader.status !== Loader.Ready)
193+ return;
194+
195+ var launcher = testCase.findChild(shellLoader.item, "launcher");
196+ launcher.state = "visible";
197+ }
198+ }
188199 ListItem.ItemSelector {
189200 anchors { left: parent.left; right: parent.right }
190201 activeFocusOnPress: false
@@ -381,12 +392,6 @@ Rectangle {
381392 signalName: "actionInvoked"
382393 }
383394
384− SignalSpy {
385− id: appRemovedSpy
386− target: ApplicationManager
387− signalName: "applicationRemoved"
388− }
389−
390395 Telephony.CallEntry {
391396 id: phoneCall
392397 phoneNumber: "+447812221111"
@@ -412,6 +417,7 @@ Rectangle {
412417 when: windowShown
413418
414419 property Item shell: shellLoader.status === Loader.Ready ? shellLoader.item : null
420+ property QtObject topLevelSurfaceList: null
415421
416422 function init() {
417423 if (shellLoader.active) {
@@ -449,6 +455,9 @@ Rectangle {
449455 panel.dismissTimer = fakeDismissTimer;
450456
451457 waitForGreeterToStabilize();
458+
459+ topLevelSurfaceList = findInvisibleChild(shell, "topLevelSurfaceList");
460+ verify(topLevelSurfaceList);
452461 }
453462
454463 function loadDesktopShellWithApps() {
@@ -463,7 +472,9 @@ Rectangle {
463472 var app5 = ApplicationManager.startApplication("camera-app")
464473 var app6 = ApplicationManager.startApplication("gallery-app")
465474 var app7 = ApplicationManager.startApplication("calendar-app")
466− waitUntilAppWindowIsFullyLoaded(app7);
475+ for (var i = 0; i < topLevelSurfaceList.count; ++i) {
476+ waitUntilAppWindowIsFullyLoaded(topLevelSurfaceList.idAt(i));
477+ }
467478 }
468479
469480 function waitForGreeterToStabilize() {
@@ -503,7 +514,7 @@ Rectangle {
503514 Wizard.System.wizardEnabled = false;
504515
505516 // kill all (fake) running apps
506− killApps(ApplicationManager);
517+ killApps();
507518
508519 unlockAllModemsSpy.clear()
509520 LightDM.Greeter.authenticate(""); // reset greeter
@@ -511,14 +522,10 @@ Rectangle {
511522 sessionSpy.clear();
512523
513524 GSettingsController.setLifecycleExemptAppids([]);
514− }
515525
516− function killApps() {
517− while (ApplicationManager.count > 1) {
518− var appIndex = ApplicationManager.get(0).appId == "unity8-dash" ? 1 : 0
519− ApplicationManager.stopApplication(ApplicationManager.get(appIndex).appId);
520− }
521− compare(ApplicationManager.count, 1)
526+ // there should be only unity8-dash window over there
527+ tryCompare(ApplicationManager, "count", 1);
528+ compare(ApplicationManager.get(0).appId, "unity8-dash");
522529 }
523530
524531 function test_snapDecisionDismissalReturnsFocus() {
@@ -527,10 +534,13 @@ Rectangle {
527534 var notifications = findChild(shell, "notificationList");
528535 var app = ApplicationManager.startApplication("camera-app");
529536 var stage = findChild(shell, "stage")
530− // Open an application and focus
537+ // Open an application
531538 waitUntilApplicationWindowIsFullyVisible(app);
532− ApplicationManager.focusApplication(app);
533− tryCompare(app.session.lastSurface, "activeFocus", true);
539+
540+ var appSurface = app.surfaceList.get(0);
541+ verify(appSurface);
542+
543+ tryCompare(appSurface, "activeFocus", true);
534544
535545 notifications.model = mockNotificationsModel;
536546
@@ -552,7 +562,7 @@ Rectangle {
552562 waitForRendering(notification);
553563
554564 // Make sure activeFocus went away from the app window
555− tryCompare(app.session.lastSurface, "activeFocus", false);
565+ tryCompare(appSurface, "activeFocus", false);
556566 tryCompare(stage, "interactive", false);
557567
558568 // Clicking the button should dismiss the notification and return focus
@@ -560,7 +570,7 @@ Rectangle {
560570 mouseClick(buttonAccept);
561571
562572 // Make sure we're back to normal
563− tryCompare(app.session.lastSurface, "activeFocus", true);
573+ tryCompare(appSurface, "activeFocus", true);
564574 compare(stage.interactive, true, "Stages not interactive again after modal notification has closed");
565575 }
566576
@@ -644,9 +654,12 @@ Rectangle {
644654 var launcher = findChild(shell, "launcherPanel");
645655 tryCompare(launcher, "x", data.launcherHides ? -launcher.width : 0)
646656
657+ //FIXME: This check fails. Don't understand the rationale behind it.
658+ /*
647659 // Make sure the helper for sliding out the launcher wasn't touched. We want to fade it out here.
648660 var animateTimer = findInvisibleChild(shell, "animateTimer");
649661 compare(animateTimer.nextState, "visible");
662+ */
650663 }
651664
652665 function test_tabletLeftEdgeDrag_data() {
@@ -873,10 +886,22 @@ Rectangle {
873886 tryCompare(item, "visible", false);
874887 }
875888
889+ function findAppWindowForSurfaceId(surfaceId) {
890+ // for PhoneStage and TabletStage
891+ var delegate = findChild(shell, "spreadDelegate_" + surfaceId);
892+ if (!delegate) {
893+ // for DesktopStage
894+ delegate = findChild(shell, "appDelegate_" + surfaceId);
895+ }
896+ verify(delegate);
897+ var appWindow = findChild(delegate, "appWindow");
898+ return appWindow;
899+ }
900+
876901 // Wait until the ApplicationWindow for the given Application object is fully loaded
877902 // (ie, the real surface has replaced the splash screen)
878− function waitUntilAppWindowIsFullyLoaded(app) {
879− var appWindow = findChild(shell, "appWindow_" + app.appId);
903+ function waitUntilAppWindowIsFullyLoaded(surfaceId) {
904+ var appWindow = findAppWindowForSurfaceId(surfaceId);
880905 var appWindowStateGroup = findInvisibleChild(appWindow, "applicationWindowStateGroup");
881906 tryCompareFunction(function() { return appWindowStateGroup.state === "surface" }, true);
882907 waitUntilTransitionsEnd(appWindowStateGroup);
@@ -885,10 +910,13 @@ Rectangle {
885910 function test_surfaceLosesActiveFocusWhilePanelIsOpen() {
886911 loadShell("phone");
887912 swipeAwayGreeter();
913+ var appSurfaceId = topLevelSurfaceList.nextId;
888914 var app = ApplicationManager.startApplication("dialer-app");
889− waitUntilAppWindowIsFullyLoaded(app);
915+ waitUntilAppWindowIsFullyLoaded(appSurfaceId);
916+ var appSurface = app.surfaceList.get(0);
917+ verify(appSurface);
890918
891− tryCompare(app.session.lastSurface, "activeFocus", true);
919+ tryCompare(appSurface, "activeFocus", true);
892920
893921 // Drag the indicators panel half-open
894922 var touchX = shell.width / 2;
@@ -899,7 +927,7 @@ Rectangle {
899927 true /* beginTouch */, false /* endTouch */);
900928 verify(indicators.partiallyOpened);
901929
902− tryCompare(app.session.lastSurface, "activeFocus", false);
930+ tryCompare(appSurface, "activeFocus", false);
903931
904932 // And finish getting it open
905933 touchFlick(indicators,
@@ -908,11 +936,11 @@ Rectangle {
908936 false /* beginTouch */, true /* endTouch */);
909937 tryCompare(indicators, "fullyOpened", true);
910938
911− tryCompare(app.session.lastSurface, "activeFocus", false);
939+ tryCompare(appSurface, "activeFocus", false);
912940
913941 dragToCloseIndicatorsPanel();
914942
915− tryCompare(app.session.lastSurface, "activeFocus", true);
943+ tryCompare(appSurface, "activeFocus", true);
916944 }
917945
918946 function test_launchedAppHasActiveFocus_data() {
@@ -928,54 +956,44 @@ Rectangle {
928956 shell.usageScenario = data.usageScenario;
929957 swipeAwayGreeter();
930958
959+ var webAppSurfaceId = topLevelSurfaceList.nextId;
931960 var webApp = ApplicationManager.startApplication("webbrowser-app");
932961 verify(webApp);
933− waitUntilAppSurfaceShowsUp("webbrowser-app")
962+ waitUntilAppWindowIsFullyLoaded(webAppSurfaceId);
934963
935− verify(webApp.session.lastSurface);
964+ var webAppSurface = webApp.surfaceList.get(topLevelSurfaceList.indexForId(webAppSurfaceId));
965+ verify(webAppSurface);
936966
937− tryCompare(webApp.session.lastSurface, "activeFocus", true);
967+ tryCompare(webAppSurface, "activeFocus", true);
938968 }
939969
940970 function test_launchedAppKeepsActiveFocusOnUsageModeChange() {
941971 loadShell("tablet");
942972 swipeAwayGreeter();
943973
974+ var webAppSurfaceId = topLevelSurfaceList.nextId;
944975 var webApp = ApplicationManager.startApplication("webbrowser-app");
945976 verify(webApp);
946− waitUntilAppSurfaceShowsUp("webbrowser-app")
977+ waitUntilAppWindowIsFullyLoaded(webAppSurfaceId);
947978
948− verify(webApp.session.lastSurface);
979+ var webAppSurface = webApp.surfaceList.get(topLevelSurfaceList.indexForId(webAppSurfaceId));
980+ verify(webAppSurface);
949981
950− tryCompare(webApp.session.lastSurface, "activeFocus", true);
982+ tryCompare(webAppSurface, "activeFocus", true);
951983
952984 shell.usageScenario = "desktop";
953985
954986 // check that the desktop stage and window have been loaded
955− {
956− var desktopWindow = findChild(shell, "appWindow_webbrowser-app");
957− verify(desktopWindow);
958− }
987+ waitUntilAppWindowIsFullyLoaded(webAppSurfaceId);
959988
960− tryCompare(webApp.session.lastSurface, "activeFocus", true);
989+ tryCompare(webAppSurface, "activeFocus", true);
961990
962991 shell.usageScenario = "tablet";
963992
964993 // check that the tablet stage and app surface delegate have been loaded
965− {
966− var desktopWindow = findChild(shell, "tabletSpreadDelegate_webbrowser-app");
967− verify(desktopWindow);
968− }
969−
970− tryCompare(webApp.session.lastSurface, "activeFocus", true);
971− }
994+ waitUntilAppWindowIsFullyLoaded(webAppSurfaceId);
972995
973− function waitUntilAppSurfaceShowsUp(appId) {
974− var appWindow = findChild(shell, "appWindow_" + appId);
975− verify(appWindow);
976− var appWindowStates = findInvisibleChild(appWindow, "applicationWindowStateGroup");
977− verify(appWindowStates);
978− tryCompare(appWindowStates, "state", "surface");
996+ tryCompare(webAppSurface, "activeFocus", true);
979997 }
980998
981999 function dragToCloseIndicatorsPanel() {
@@ -1026,7 +1044,7 @@ Rectangle {
10261044 }
10271045
10281046 function waitUntilApplicationWindowIsFullyVisible() {
1029− var appDelegate = findChild(shell, "appDelegate0")
1047+ var appDelegate = findChild(shell, "spreadDelegate_" + topLevelSurfaceList.idAt(0));
10301048 var surfaceContainer = findChild(appDelegate, "surfaceContainer");
10311049 tryCompareFunction(function() { return surfaceContainer.surface !== null; }, true);
10321050 }
@@ -1088,8 +1106,7 @@ Rectangle {
10881106 var greeter = findChild(shell, "greeter");
10891107
10901108 var app = ApplicationManager.startApplication("dialer-app");
1091− // wait until the app is fully loaded (ie, real surface replaces splash screen)
1092− tryCompareFunction(function() { return app.session !== null && app.session.lastSurface !== null }, true);
1109+ waitUntilApplicationWindowIsFullyVisible(app);
10931110
10941111 // Minimize the application we just launched
10951112 swipeFromLeftEdge(shell.width * 0.75);
@@ -1150,13 +1167,15 @@ Rectangle {
11501167 swipeAwayGreeter();
11511168 var panel = findChild(shell, "panel");
11521169 compare(panel.fullscreenMode, false);
1153− ApplicationManager.startApplication("camera-app");
1170+ var cameraApp = ApplicationManager.startApplication("camera-app");
1171+ waitUntilApplicationWindowIsFullyVisible(cameraApp);
11541172 tryCompare(panel, "fullscreenMode", true);
1155− ApplicationManager.startApplication("dialer-app");
1173+ var dialerApp = ApplicationManager.startApplication("dialer-app");
1174+ waitUntilApplicationWindowIsFullyVisible(dialerApp);
11561175 tryCompare(panel, "fullscreenMode", false);
1157− ApplicationManager.requestFocusApplication("camera-app");
1176+ ApplicationManager.requestFocusApplication(cameraApp.appId);
11581177 tryCompare(panel, "fullscreenMode", true);
1159− ApplicationManager.requestFocusApplication("dialer-app");
1178+ ApplicationManager.requestFocusApplication(dialerApp.appId);
11601179 tryCompare(panel, "fullscreenMode", false);
11611180 }
11621181
@@ -1227,24 +1246,32 @@ Rectangle {
12271246 var tutorial = findChild(shell, "tutorial");
12281247 tryCompare(wizard, "active", true);
12291248 tryCompare(tutorial, "running", true);
1230− tryCompare(ApplicationManager, "focusedApplicationId", "unity8-dash");
1249+ tryCompareFunction(function() { return topLevelSurfaceList.applicationAt(0).appId; }, "unity8-dash");
12311250
1232− // Make sure we stay running when nothing focused (can happen for
1251+ // Make sure we stay running when there's no top level window (can happen for
12331252 // a moment when we restart the dash after switching language)
1234− ApplicationManager.stopApplication("unity8-dash");
1235− tryCompare(ApplicationManager, "focusedApplicationId", "");
1253+ var dashApplication = ApplicationManager.findApplication("unity8-dash");
1254+ ApplicationManager.stopApplication(dashApplication.appId);
1255+ // wait until all zombie surfaces are gone. As MirSurfaceItems hold references over them.
1256+ // They won't be gone until those surface items are destroyed.
1257+ tryCompareFunction(function() { return dashApplication.surfaceList.count }, 0);
1258+
1259+ tryCompare(topLevelSurfaceList, "count", 0);
12361260 compare(wizard.shown, true);
12371261 compare(tutorial.running, true);
12381262
1239− // And make sure we stay running when dash focused again
1240− ApplicationManager.startApplication("unity8-dash");
1241− tryCompare(ApplicationManager, "focusedApplicationId", "unity8-dash");
1263+ // And make sure we stay running when dash comes back again
1264+ var dashSurfaceId = topLevelSurfaceList.nextId;
1265+ ApplicationManager.startApplication(dashApplication.appId);
1266+ waitUntilAppWindowIsFullyLoaded(dashSurfaceId);
12421267 compare(wizard.shown, true);
12431268 compare(tutorial.running, true);
12441269
1245− // And make sure we stop when something else is focused
1246− ApplicationManager.startApplication("gallery-app");
1247− tryCompare(ApplicationManager, "focusedApplicationId", "gallery-app");
1270+ // And make sure we stop when some other surface shows app
1271+ var gallerySurfaceId = topLevelSurfaceList.nextId;
1272+ var galleryApp = ApplicationManager.startApplication("gallery-app");
1273+ waitUntilAppWindowIsFullyLoaded(gallerySurfaceId);
1274+ tryCompareFunction(function() { return topLevelSurfaceList.applicationAt(0).appId; }, "gallery-app");
12481275 compare(wizard.shown, false);
12491276 compare(tutorial.running, false);
12501277 tryCompare(AccountsService, "demoEdges", false);
@@ -1269,7 +1296,7 @@ Rectangle {
12691296 function test_tapOnRightEdgeReachesApplicationSurface() {
12701297 loadShell("phone");
12711298 swipeAwayGreeter();
1272− var topmostSpreadDelegate = findChild(shell, "appDelegate0");
1299+ var topmostSpreadDelegate = findChild(shell, "spreadDelegate_" + topLevelSurfaceList.idAt(0));
12731300 verify(topmostSpreadDelegate);
12741301
12751302 waitUntilFocusedApplicationIsShowingItsSurface();
@@ -1298,7 +1325,7 @@ Rectangle {
12981325 function test_rightEdgeDragDoesNotReachApplicationSurface() {
12991326 loadShell("phone");
13001327 swipeAwayGreeter();
1301− var topmostSpreadDelegate = findChild(shell, "appDelegate0");
1328+ var topmostSpreadDelegate = findChild(shell, "spreadDelegate_" + topLevelSurfaceList.idAt(0));
13021329 var topmostSurfaceItem = findChild(topmostSpreadDelegate, "surfaceItem");
13031330 var rightEdgeDragArea = findChild(shell, "spreadDragArea");
13041331
@@ -1318,7 +1345,7 @@ Rectangle {
13181345
13191346 function waitUntilFocusedApplicationIsShowingItsSurface()
13201347 {
1321− var spreadDelegate = findChild(shell, "appDelegate0");
1348+ var spreadDelegate = findChild(shell, "spreadDelegate_" + topLevelSurfaceList.idAt(0));
13221349 var appState = findInvisibleChild(spreadDelegate, "applicationWindowStateGroup");
13231350 tryCompare(appState, "state", "surface");
13241351 var transitions = appState.transitions;
@@ -1467,11 +1494,13 @@ Rectangle {
14671494 loadShell("tablet");
14681495 shell.usageScenario = "desktop";
14691496
1497+ var webBrowserSurfaceId = topLevelSurfaceList.nextId;
14701498 var webBrowserApp = ApplicationManager.startApplication("webbrowser-app");
1471− waitUntilAppWindowIsFullyLoaded(webBrowserApp);
1499+ waitUntilAppWindowIsFullyLoaded(webBrowserSurfaceId);
14721500
1501+ var gallerySurfaceId = topLevelSurfaceList.nextId;
14731502 var galleryApp = ApplicationManager.startApplication("gallery-app");
1474− waitUntilAppWindowIsFullyLoaded(galleryApp);
1503+ waitUntilAppWindowIsFullyLoaded(gallerySurfaceId);
14751504
14761505 ApplicationManager.requestFocusApplication("unity8-dash");
14771506 tryCompare(ApplicationManager, "focusedApplicationId", "unity8-dash");
@@ -1489,11 +1518,13 @@ Rectangle {
14891518 loadShell("tablet");
14901519 shell.usageScenario = "tablet";
14911520
1521+ var webBrowserSurfaceId = topLevelSurfaceList.nextId;
14921522 var webBrowserApp = ApplicationManager.startApplication("webbrowser-app");
1493− waitUntilAppWindowIsFullyLoaded(webBrowserApp);
1523+ waitUntilAppWindowIsFullyLoaded(webBrowserSurfaceId);
14941524
1525+ var gallerySurfaceId = topLevelSurfaceList.nextId;
14951526 var galleryApp = ApplicationManager.startApplication("gallery-app");
1496− waitUntilAppWindowIsFullyLoaded(galleryApp);
1527+ waitUntilAppWindowIsFullyLoaded(gallerySurfaceId);
14971528
14981529 ApplicationManager.requestFocusApplication("unity8-dash");
14991530 tryCompare(ApplicationManager, "focusedApplicationId", "unity8-dash");
@@ -1523,17 +1554,26 @@ Rectangle {
15231554 var desktopStage = findChild(shell, "stage");
15241555 verify(desktopStage != null)
15251556
1557+ var app1SurfaceId = topLevelSurfaceList.nextId;
15261558 var app1 = ApplicationManager.startApplication("dialer-app")
1527− waitUntilAppWindowIsFullyLoaded(app1);
1559+ waitUntilAppWindowIsFullyLoaded(app1SurfaceId);
1560+
1561+ var app2SurfaceId = topLevelSurfaceList.nextId;
15281562 var app2 = ApplicationManager.startApplication("webbrowser-app")
1529− waitUntilAppWindowIsFullyLoaded(app2);
1563+ waitUntilAppWindowIsFullyLoaded(app2SurfaceId);
1564+ var app2Surface = app2.surfaceList.get(0);
1565+ verify(app2Surface);
1566+
1567+ var app3SurfaceId = topLevelSurfaceList.nextId;
15301568 var app3 = ApplicationManager.startApplication("camera-app")
1531− waitUntilAppWindowIsFullyLoaded(app3);
1569+ waitUntilAppWindowIsFullyLoaded(app3SurfaceId);
1570+ var app3Surface = app3.surfaceList.get(0);
1571+ verify(app3Surface);
15321572
15331573 // Do a quick alt-tab and see if focus changes
1534− tryCompare(app3.session.lastSurface, "activeFocus", true)
1574+ tryCompare(app3Surface, "activeFocus", true)
15351575 keyClick(Qt.Key_Tab, Qt.AltModifier)
1536− tryCompare(app2.session.lastSurface, "activeFocus", true)
1576+ tryCompare(app2Surface, "activeFocus", true)
15371577
15381578 // Press Alt+Tab
15391579 keyPress(Qt.Key_Alt);
@@ -1541,7 +1581,7 @@ Rectangle {
15411581 keyRelease(Qt.Key_Alt)
15421582
15431583 // Focus should have switched back now
1544− tryCompare(app3.session.lastSurface, "activeFocus", true)
1584+ tryCompare(app3Surface, "activeFocus", true)
15451585 }
15461586
15471587 function test_altTabWrapAround() {
@@ -1590,7 +1630,9 @@ Rectangle {
15901630 tryCompare(desktopSpread, "state", "")
15911631
15921632 // Make sure that after wrapping around once, we have the same one focused as at the beginning
1593− tryCompare(focused.session.lastSurface, "activeFocus", true)
1633+ var focusedAppSurface = focused.surfaceList.get(0);
1634+ verify(focusedAppSurface);
1635+ tryCompare(focusedAppSurface, "activeFocus", true)
15941636 }
15951637
15961638 function test_altBackTabNavigation() {
@@ -1624,7 +1666,7 @@ Rectangle {
16241666 keyRelease(Qt.Key_Alt);
16251667 }
16261668
1627− function test_highlightFollowsMouse() {
1669+ function otest_highlightFollowsMouse() {
16281670 loadDesktopShellWithApps()
16291671
16301672 var spreadRepeater = findInvisibleChild(shell, "spreadRepeater");
@@ -1661,9 +1703,7 @@ Rectangle {
16611703 keyPress(Qt.Key_Alt)
16621704 keyClick(Qt.Key_Tab);
16631705
1664− appRemovedSpy.clear();
1665−
1666− var closedAppId = ApplicationManager.get(2).appId;
1706+ var surfaceId = topLevelSurfaceList.idAt(2);
16671707 var spreadDelegate2 = spreadRepeater.itemAt(2);
16681708 var closeMouseArea = findChild(spreadDelegate2, "closeMouseArea");
16691709
@@ -1678,12 +1718,14 @@ Rectangle {
16781718 }
16791719 tryCompare(closeMouseArea, "enabled", true)
16801720
1721+ var countBeforeClickingCloseButton = topLevelSurfaceList.count;
1722+ verify(topLevelSurfaceList.indexForId(surfaceId) === 2);
1723+
16811724 // Close the app using the close button
16821725 mouseClick(closeMouseArea, closeMouseArea.width / 2, closeMouseArea.height / 2)
16831726
1684− // Verify applicationRemoved has been emitted correctly
1685− tryCompare(appRemovedSpy, "count", 1)
1686− compare(appRemovedSpy.signalArguments[0][0], closedAppId);
1727+ tryCompare(topLevelSurfaceList, "count", countBeforeClickingCloseButton - 1);
1728+ verify(topLevelSurfaceList.indexForId(surfaceId) === -1);
16871729
16881730 keyRelease(Qt.Key_Alt);
16891731 }
@@ -1708,7 +1750,7 @@ Rectangle {
17081750 keyPress(Qt.Key_Alt)
17091751 keyClick(Qt.Key_Tab);
17101752
1711− var focusAppId = ApplicationManager.get(2).appId;
1753+ var surface = topLevelSurfaceList.surfaceAt(2);
17121754 var spreadDelegate2 = spreadRepeater.itemAt(2);
17131755 var clippedSpreadDelegate = findChild(spreadDelegate2, "clippedSpreadDelegate");
17141756
@@ -1730,7 +1772,7 @@ Rectangle {
17301772
17311773 // Verify that we left the spread and app2 is the focused one now
17321774 tryCompare(stage, "state", "");
1733− tryCompare(ApplicationManager, "focusedApplicationId", focusAppId);
1775+ tryCompare(surface, "focused", true);
17341776
17351777 keyRelease(Qt.Key_Alt);
17361778 }
@@ -1794,7 +1836,7 @@ Rectangle {
17941836 function test_workspacePreviewsHighlightedApp() {
17951837 loadDesktopShellWithApps()
17961838
1797− var targetZ = ApplicationManager.count + 1;
1839+ var targetZ = topLevelSurfaceList.count + 1;
17981840
17991841 var spreadRepeater = findInvisibleChild(shell, "spreadRepeater");
18001842 verify(spreadRepeater !== null);
@@ -1870,7 +1912,8 @@ Rectangle {
18701912 loadDesktopShellWithApps();
18711913
18721914 var appRepeater = findChild(shell, "appRepeater")
1873− var appId = ApplicationManager.get(0).appId;
1915+ var application = topLevelSurfaceList.applicationAt(0);
1916+ var surfaceId = topLevelSurfaceList.idAt(0);
18741917 var appDelegate = appRepeater.itemAt(0);
18751918 var maximizeButton = findChild(appDelegate, "maximizeWindowButton");
18761919
@@ -1881,17 +1924,20 @@ Rectangle {
18811924 tryCompare(appDelegate, "state", "maximized");
18821925 tryCompare(PanelState, "buttonsVisible", true)
18831926
1884− ApplicationManager.stopApplication(appId);
1927+ ApplicationManager.stopApplication(application.appId);
18851928 tryCompare(PanelState, "buttonsVisible", false)
18861929
1887− ApplicationManager.startApplication(appId);
1930+ // wait until all zombie surfaces are gone. As MirSurfaceItems hold references over them.
1931+ // They won't be gone until those surface items are destroyed.
1932+ tryCompareFunction(function() { return application.surfaceList.count }, 0);
1933+
1934+ ApplicationManager.startApplication(application.appId);
18881935 tryCompare(PanelState, "buttonsVisible", true)
18891936 }
18901937
18911938 function test_newAppHasValidGeometry() {
18921939 loadDesktopShellWithApps();
18931940 var appRepeater = findChild(shell, "appRepeater");
1894− var appId = ApplicationManager.get(0).appId;
18951941 var appDelegate = appRepeater.itemAt(0);
18961942
18971943 var resizeArea = findChild(appDelegate, "windowResizeArea");
@@ -1908,7 +1954,6 @@ Rectangle {
19081954 function test_switchToStagedHidesPanelButtons() {
19091955 loadDesktopShellWithApps();
19101956 var appRepeater = findChild(shell, "appRepeater")
1911− var appId = ApplicationManager.get(0).appId;
19121957 var appDelegate = appRepeater.itemAt(0);
19131958 var panelButtons = findChild(shell, "panelWindowControlButtons")
19141959
@@ -1925,7 +1970,6 @@ Rectangle {
19251970 function test_lockingGreeterHidesPanelButtons() {
19261971 loadDesktopShellWithApps();
19271972 var appRepeater = findChild(shell, "appRepeater")
1928− var appId = ApplicationManager.get(0).appId;
19291973 var appDelegate = appRepeater.itemAt(0);
19301974 var panelButtons = findChild(shell, "panelWindowControlButtons")
19311975
@@ -1955,12 +1999,15 @@ Rectangle {
19551999 shell.usageScenario = "desktop";
19562000 waitForRendering(shell);
19572001
2002+ var appSurfaceId = topLevelSurfaceList.nextId;
19582003 var app = ApplicationManager.startApplication("dialer-app")
1959− waitUntilAppWindowIsFullyLoaded(app);
2004+ waitUntilAppWindowIsFullyLoaded(appSurfaceId);
19602005
19612006 var appContainer = findChild(shell, "appContainer");
1962− var appDelegate = findChild(appContainer, "appDelegate_dialer-app");
1963− var decoration = findChild(appDelegate, "appWindowDecoration_dialer-app");
2007+ verify(appContainer);
2008+ var appDelegate = findChild(appContainer, "appDelegate_" + appSurfaceId);
2009+ verify(appDelegate);
2010+ var decoration = findChild(appDelegate, "appWindowDecoration");
19642011 verify(decoration);
19652012
19662013 // move it away from launcher and panel
@@ -1978,18 +2025,22 @@ Rectangle {
19782025 function test_restoreWindowStateFixesIfUnderPanel() {
19792026 loadDesktopShellWithApps();
19802027 var appRepeater = findChild(shell, "appRepeater")
1981− var appId = ApplicationManager.get(0).appId;
2028+ var application = topLevelSurfaceList.applicationAt(0);
19822029 var appDelegate = appRepeater.itemAt(0);
19832030
19842031 // Move it under the panel programmatically (might happen later with an alt+drag)
19852032 appDelegate.y = -units.gu(10)
19862033
1987− ApplicationManager.stopApplication(appId)
1988− ApplicationManager.startApplication(appId)
2034+ ApplicationManager.stopApplication(application.appId);
2035+ // wait until all zombie surfaces are gone. As MirSurfaceItems hold references over them.
2036+ // They won't be gone until those surface items are destroyed.
2037+ tryCompareFunction(function() { return application.surfaceList.count }, 0);
2038+
2039+ ApplicationManager.startApplication(application.appId);
19892040 waitForRendering(shell)
19902041
19912042 // Make sure the newly started one is at index 0 again
1992− tryCompare(ApplicationManager.get(0), "appId", appId);
2043+ tryCompare(topLevelSurfaceList.applicationAt(0), "appId", application.appId);
19932044
19942045 appDelegate = appRepeater.itemAt(0);
19952046 compare(appDelegate.y >= PanelState.panelHeight, true);
@@ -2008,16 +2059,22 @@ Rectangle {
20082059
20092060 // Add two main stage apps, the second in order to suspend the first.
20102061 // LibreOffice has isTouchApp set to false by our mocks.
2062+ var app1SurfaceId = topLevelSurfaceList.nextId;
20112063 var app1 = ApplicationManager.startApplication("libreoffice");
2012− waitUntilAppWindowIsFullyLoaded(app1);
2064+ waitUntilAppWindowIsFullyLoaded(app1SurfaceId);
2065+ var app2SurfaceId = topLevelSurfaceList.nextId;
20132066 var app2 = ApplicationManager.startApplication("gallery-app");
2014− waitUntilAppWindowIsFullyLoaded(app2);
2067+ waitUntilAppWindowIsFullyLoaded(app2SurfaceId);
20152068
20162069 // Sanity checking
20172070 compare(app1.stage, ApplicationInfoInterface.MainStage);
20182071 compare(app2.stage, ApplicationInfoInterface.MainStage);
20192072 verify(!app1.isTouchApp);
2020− verify(!app1.session.lastSurface.activeFocus);
2073+
2074+ var app1Surface = app1.surfaceList.get(0);
2075+ verify(app1Surface);
2076+
2077+ verify(!app1Surface.activeFocus);
20212078
20222079 // Make sure app1 is exempt with a requested suspend
20232080 verify(app1.exemptFromLifecycle);
@@ -2038,15 +2095,21 @@ Rectangle {
20382095 GSettingsController.setLifecycleExemptAppids(["webbrowser-app"]);
20392096
20402097 // Add two main stage apps, the second in order to suspend the first
2098+ var app1SurfaceId = topLevelSurfaceList.nextId;
20412099 var app1 = ApplicationManager.startApplication("webbrowser-app");
2042− waitUntilAppWindowIsFullyLoaded(app1);
2100+ waitUntilAppWindowIsFullyLoaded(app1SurfaceId);
2101+ var app2SurfaceId = topLevelSurfaceList.nextId;
20432102 var app2 = ApplicationManager.startApplication("gallery-app");
2044− waitUntilAppWindowIsFullyLoaded(app2);
2103+ waitUntilAppWindowIsFullyLoaded(app2SurfaceId);
20452104
20462105 // Sanity checking
20472106 compare(app1.stage, ApplicationInfoInterface.MainStage);
20482107 compare(app2.stage, ApplicationInfoInterface.MainStage);
2049− verify(!app1.session.lastSurface.activeFocus);
2108+
2109+ var app1Surface = app1.surfaceList.get(0);
2110+ verify(app1Surface);
2111+
2112+ verify(!app1Surface.activeFocus);
20502113
20512114 // Make sure app1 is exempt with a requested suspend
20522115 verify(app1.exemptFromLifecycle);
@@ -2205,9 +2268,10 @@ Rectangle {
22052268 var appContainer = findChild(shell, "appContainer");
22062269 var launcher = findChild(shell, "launcher");
22072270
2271+ var appSurfaceId = topLevelSurfaceList.nextId;
22082272 var app = ApplicationManager.startApplication("music-app");
2209− waitUntilAppWindowIsFullyLoaded(app);
2210− var appDelegate = findChild(appContainer, "appDelegate_music-app");
2273+ waitUntilAppWindowIsFullyLoaded(appSurfaceId);
2274+ var appDelegate = findChild(appContainer, "appDelegate_" + appSurfaceId);
22112275 appDelegate.maximize();
22122276 tryCompare(appDelegate, "visuallyMaximized", true);
22132277 waitForRendering(shell);
@@ -2235,8 +2299,9 @@ Rectangle {
22352299
22362300 tryCompare(launcher, "lockedVisible", true);
22372301
2302+ var cameraSurfaceId = topLevelSurfaceList.nextId;
22382303 var cameraApp = ApplicationManager.startApplication("camera-app");
2239− waitUntilAppWindowIsFullyLoaded(cameraApp);
2304+ waitUntilAppWindowIsFullyLoaded(cameraSurfaceId);
22402305
22412306 tryCompare(launcher, "lockedVisible", false);
22422307 }
@@ -2257,8 +2322,9 @@ Rectangle {
22572322 swipeAwayGreeter();
22582323
22592324 // Let's open a fullscreen app
2325+ var appSurfaceId = topLevelSurfaceList.nextId;
22602326 var app = ApplicationManager.startApplication("camera-app");
2261− waitUntilAppWindowIsFullyLoaded(app);
2327+ waitUntilAppWindowIsFullyLoaded(appSurfaceId);
22622328
22632329 var appRepeater = findChild(shell, data.repeaterName);
22642330 var topmostAppDelegate = appRepeater.itemAt(0);