@@ -47,6 +47,7 @@ Rectangle {
50 anchors.left: root.left
51 anchors.left: root.left
51 anchors.right: controls.left
52 anchors.right: controls.left
52 anchors.top: root.top
53 anchors.top: root.top
@@ -74,6 +75,18 @@ Rectangle {
74 width: units.gu(100)
75 width: units.gu(100)
75 height: units.gu(71)
76 height: units.gu(71)
83+ width: shellContainer.width
84+ height: shellContainer.height
87+ target: mouseEmulation
@@ -81,6 +94,7 @@ Rectangle {
81 property bool itemDestroyed: false
94 property bool itemDestroyed: false
82 sourceComponent: Component {
95 sourceComponent: Component {
84 usageScenario: usageScenarioSelector.model[usageScenarioSelector.selectedIndex]
98 usageScenario: usageScenarioSelector.model[usageScenarioSelector.selectedIndex]
85 orientation: Qt.PortraitOrientation
99 orientation: Qt.PortraitOrientation
86 primaryOrientation: Qt.PortraitOrientation
100 primaryOrientation: Qt.PortraitOrientation
@@ -88,6 +102,10 @@ Rectangle {
88 Component.onDestruction: {
102 Component.onDestruction: {
89 shellLoader.itemDestroyed = true;
103 shellLoader.itemDestroyed = true;
105+ Component.onCompleted: {
106+ var keyMapper = testCase.findChild(__shell, "physicalKeysMapper");
107+ keyMapper.controlInsteadOfAlt = true;
@@ -112,16 +130,32 @@ Rectangle {
112 anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
130 anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
113 spacing: units.gu(1)
131 spacing: units.gu(1)
134+ spacing: units.gu(1)
115− Button {
135+ Button {
116− text: "Show Greeter"
136+ text: "Show Greeter"
117− activeFocusOnPress: false
137+ activeFocusOnPress: false
118− onClicked: {
138+ onClicked: {
119− if (shellLoader.status !== Loader.Ready)
139+ if (shellLoader.status !== Loader.Ready)
122− var greeter = testCase.findChild(shellLoader.item, "greeter");
142+ var greeter = testCase.findChild(shellLoader.item, "greeter");
123− if (!greeter.shown) {
143+ if (!greeter.shown) {
124− LightDM.Greeter.showGreeter();
144+ LightDM.Greeter.showGreeter();
149+ text: "Hide Greeter"
150+ activeFocusOnPress: false
152+ if (shellLoader.status !== Loader.Ready)
155+ var greeter = testCase.findChild(shellLoader.item, "greeter");
156+ if (greeter.shown) {
@@ -141,7 +175,7 @@ Rectangle {
141 anchors { left: parent.left; right: parent.right }
175 anchors { left: parent.left; right: parent.right }
142 activeFocusOnPress: false
176 activeFocusOnPress: false
143 text: "Size"
177 text: "Size"
144− model: ["phone", "tablet"]
178+ model: ["phone", "tablet", "desktop"]
145 onSelectedIndexChanged: {
179 onSelectedIndexChanged: {
146 shellLoader.active = false;
180 shellLoader.active = false;
147 shellLoader.state = model[selectedIndex];
181 shellLoader.state = model[selectedIndex];
@@ -163,6 +197,17 @@ Rectangle {
164 Label { text: "Applications"; font.bold: true }
198 Label { text: "Applications"; font.bold: true }
201+ text: "Start all apps"
204+ for (var i = 0; i < ApplicationManager.availableApplications.length; i++) {
205+ var appId = ApplicationManager.availableApplications[i];
206+ ApplicationManager.startApplication(appId)
166 Repeater {
211 Repeater {
167 id: appRepeater
212 id: appRepeater
168 model: ApplicationManager.availableApplications
213 model: ApplicationManager.availableApplications
@@ -226,6 +271,12 @@ Rectangle {
226 signalName: "actionInvoked"
271 signalName: "actionInvoked"
276+ target: ApplicationManager
277+ signalName: "applicationRemoved"
229 Telephony.CallEntry {
280 Telephony.CallEntry {
230 id: phoneCall
281 id: phoneCall
231 phoneNumber: "+447812221111"
282 phoneNumber: "+447812221111"
@@ -248,9 +299,9 @@ Rectangle {
250 function cleanup() {
301 function cleanup() {
302+ mouseEmulation.checked = true;
251 tryCompare(shell, "enabled", true); // make sure greeter didn't leave us in disabled state
303 tryCompare(shell, "enabled", true); // make sure greeter didn't leave us in disabled state
252 tearDown();
304 tearDown();
253− GSettingsController.setUsageMode("Staged");
256 function loadShell(formFactor) {
307 function loadShell(formFactor) {
@@ -269,6 +320,20 @@ Rectangle {
269 waitForGreeterToStabilize();
320 waitForGreeterToStabilize();
323+ function loadDesktopShellWithApps() {
324+ loadShell("desktop");
325+ shell.usageScenario = "desktop"
326+ waitForRendering(root)
327+ var app1 = ApplicationManager.startApplication("dialer-app")
328+ var app2 = ApplicationManager.startApplication("webbrowser-app")
329+ var app3 = ApplicationManager.startApplication("camera-app")
330+ var app4 = ApplicationManager.startApplication("facebook-webapp")
331+ var app5 = ApplicationManager.startApplication("calendar-app")
332+ var app6 = ApplicationManager.startApplication("gallery-app")
333+ var app7 = ApplicationManager.startApplication("camera-app")
334+ waitUntilAppWindowIsFullyLoaded(app7);
272 function waitForGreeterToStabilize() {
337 function waitForGreeterToStabilize() {
273 var greeter = findChild(shell, "greeter");
338 var greeter = findChild(shell, "greeter");
274 verify(greeter);
339 verify(greeter);
@@ -472,6 +537,41 @@ Rectangle {
472 confirmLoggedIn(data.loggedIn)
537 confirmLoggedIn(data.loggedIn)
540+ function test_longLeftEdgeSwipeTakesToAppsAndResetSearchString() {
543+ dragLauncherIntoView();
544+ dashCommunicatorSpy.clear();
546+ tapOnAppIconInLauncher();
547+ waitUntilApplicationWindowIsFullyVisible();
549+ verify(ApplicationManager.focusedApplicationId !== "unity8-dash")
552+ swipeFromLeftEdge(units.gu(30));
554+ tryCompare(ApplicationManager, "focusedApplicationId", "unity8-dash");
556+ compare(dashCommunicatorSpy.count, 1);
559+ function test_ClickUbuntuIconInLauncherTakesToAppsAndResetSearchString() {
562+ dragLauncherIntoView();
563+ dashCommunicatorSpy.clear();
565+ var launcher = findChild(shell, "launcher");
566+ var dashIcon = findChild(launcher, "dashItem");
567+ verify(dashIcon != undefined);
568+ mouseClick(dashIcon);
570+ tryCompare(ApplicationManager, "focusedApplicationId", "unity8-dash");
572+ compare(dashCommunicatorSpy.count, 1);
475 function test_suspend() {
575 function test_suspend() {
476 loadShell("phone");
576 loadShell("phone");
477 swipeAwayGreeter();
577 swipeAwayGreeter();
@@ -486,9 +586,9 @@ Rectangle {
486 verify(mainAppId != "");
586 verify(mainAppId != "");
487 var mainApp = ApplicationManager.findApplication(mainAppId);
587 var mainApp = ApplicationManager.findApplication(mainAppId);
488 verify(mainApp);
588 verify(mainApp);
489− tryCompare(mainApp, "state", ApplicationInfoInterface.Running);
589+ tryCompare(mainApp, "requestedState", ApplicationInfoInterface.RequestedRunning);
491− // Suspend while call is active...
591+ // Display off while call is active...
492 callManager.foregroundCall = phoneCall;
592 callManager.foregroundCall = phoneCall;
493 Powerd.status = Powerd.Off;
593 Powerd.status = Powerd.Off;
494 tryCompare(greeter, "shown", false);
594 tryCompare(greeter, "shown", false);
@@ -499,8 +599,7 @@ Rectangle {
499 Powerd.status = Powerd.Off;
599 Powerd.status = Powerd.Off;
500 tryCompare(greeter, "fullyShown", true);
600 tryCompare(greeter, "fullyShown", true);
502− tryCompare(ApplicationManager, "suspended", true);
503− compare(mainApp.state, ApplicationInfoInterface.Suspended);
602+ compare(mainApp.requestedState, ApplicationInfoInterface.RequestedSuspended);
505 // And wake up
604 // And wake up
506 Powerd.status = Powerd.On;
605 Powerd.status = Powerd.On;
@@ -516,8 +615,7 @@ Rectangle {
516 removeTimeConstraintsFromDirectionalDragAreas(greeter);
615 removeTimeConstraintsFromDirectionalDragAreas(greeter);
517 swipeAwayGreeter();
616 swipeAwayGreeter();
519− tryCompare(ApplicationManager, "suspended", false);
520− compare(mainApp.state, ApplicationInfoInterface.Running);
618+ compare(mainApp.requestedState, ApplicationInfoInterface.RequestedRunning);
521 tryCompare(ApplicationManager, "focusedApplicationId", mainAppId);
619 tryCompare(ApplicationManager, "focusedApplicationId", mainAppId);
@@ -688,15 +786,15 @@ Rectangle {
689 function test_launchedAppHasActiveFocus_data() {
787 function test_launchedAppHasActiveFocus_data() {
691− {tag: "phone", formFactor: "phone", usageMode: "Staged"},
789+ {tag: "phone", formFactor: "phone", usageScenario: "phone"},
692− {tag: "tablet", formFactor: "tablet", usageMode: "Staged"},
790+ {tag: "tablet", formFactor: "tablet", usageScenario: "tablet"},
693− {tag: "desktop", formFactor: "tablet", usageMode: "Windowed"}
791+ {tag: "desktop", formFactor: "tablet", usageScenario: "desktop"}
697 function test_launchedAppHasActiveFocus(data) {
795 function test_launchedAppHasActiveFocus(data) {
698− GSettingsController.setUsageMode(data.usageMode);
699 loadShell(data.formFactor);
796 loadShell(data.formFactor);
797+ shell.usageScenario = data.usageScenario;
700 swipeAwayGreeter();
798 swipeAwayGreeter();
702 var webApp = ApplicationManager.startApplication("webbrowser-app");
800 var webApp = ApplicationManager.startApplication("webbrowser-app");
@@ -724,7 +822,7 @@ Rectangle {
725 // check that the desktop stage and window have been loaded
823 // check that the desktop stage and window have been loaded
727− var desktopWindow = findChild(shell, "decoratedWindow_webbrowser-app");
825+ var desktopWindow = findChild(shell, "appWindow_webbrowser-app");
728 verify(desktopWindow);
826 verify(desktopWindow);
@@ -1082,6 +1180,8 @@ Rectangle {
1084 function test_tapUbuntuIconInLauncherOverAppSpread() {
1182 function test_tapUbuntuIconInLauncherOverAppSpread() {
1183+ launcherShowDashHomeSpy.clear();
1085 loadShell("phone");
1185 loadShell("phone");
1086 swipeAwayGreeter();
1186 swipeAwayGreeter();
@@ -1228,5 +1328,272 @@ Rectangle {
1228 var launcher = findChild(shell, "launcher");
1328 var launcher = findChild(shell, "launcher");
1229 compare(launcher.inverted, data.launcherInverted);
1329 compare(launcher.inverted, data.launcherInverted);
1332+ function test_unfocusedAppsGetSuspendedAfterEnteringStagedMode() {
1333+ loadShell("tablet");
1334+ shell.usageScenario = "desktop";
1336+ var webBrowserApp = ApplicationManager.startApplication("webbrowser-app");
1337+ waitUntilAppWindowIsFullyLoaded(webBrowserApp);
1339+ var galleryApp = ApplicationManager.startApplication("gallery-app");
1340+ waitUntilAppWindowIsFullyLoaded(galleryApp);
1342+ ApplicationManager.requestFocusApplication("unity8-dash");
1343+ tryCompare(ApplicationManager, "focusedApplicationId", "unity8-dash");
1345+ compare(webBrowserApp.requestedState, ApplicationInfoInterface.RequestedRunning);
1346+ compare(galleryApp.requestedState, ApplicationInfoInterface.RequestedRunning);
1348+ shell.usageScenario = "tablet";
1350+ tryCompare(webBrowserApp, "requestedState", ApplicationInfoInterface.RequestedSuspended);
1351+ tryCompare(galleryApp, "requestedState", ApplicationInfoInterface.RequestedSuspended);
1354+ function test_unfocusedAppsAreResumedWhenEnteringWindowedMode() {
1355+ loadShell("tablet");
1356+ shell.usageScenario = "tablet";
1358+ var webBrowserApp = ApplicationManager.startApplication("webbrowser-app");
1359+ waitUntilAppWindowIsFullyLoaded(webBrowserApp);
1361+ var galleryApp = ApplicationManager.startApplication("gallery-app");
1362+ waitUntilAppWindowIsFullyLoaded(galleryApp);
1364+ ApplicationManager.requestFocusApplication("unity8-dash");
1365+ tryCompare(ApplicationManager, "focusedApplicationId", "unity8-dash");
1367+ compare(webBrowserApp.requestedState, ApplicationInfoInterface.RequestedSuspended);
1368+ compare(galleryApp.requestedState, ApplicationInfoInterface.RequestedSuspended);
1370+ shell.usageScenario = "desktop";
1372+ tryCompare(webBrowserApp, "requestedState", ApplicationInfoInterface.RequestedRunning);
1373+ tryCompare(galleryApp, "requestedState", ApplicationInfoInterface.RequestedRunning);
1376+ function test_altTabSwitchesFocus() {
1377+ loadShell("desktop");
1378+ shell.usageScenario = "desktop"
1379+ waitForRendering(root)
1381+ var desktopStage = findChild(shell, "stage");
1382+ verify(desktopStage != null)
1384+ var app1 = ApplicationManager.startApplication("dialer-app")
1385+ waitUntilAppWindowIsFullyLoaded(app1);
1386+ var app2 = ApplicationManager.startApplication("webbrowser-app")
1387+ waitUntilAppWindowIsFullyLoaded(app2);
1388+ var app3 = ApplicationManager.startApplication("camera-app")
1389+ waitUntilAppWindowIsFullyLoaded(app3);
1391+ // Do a quick alt-tab and see if focus changes
1392+ tryCompare(app3.session.surface, "activeFocus", true)
1393+ keyClick(Qt.Key_Tab, Qt.ControlModifier)
1394+ tryCompare(app2.session.surface, "activeFocus", true)
1397+ tryCompare(desktopStage, "state", "")
1399+ // Just press Alt, make sure the spread comes up
1400+ keyPress(Qt.Key_Control);
1401+ keyClick(Qt.Key_Tab);
1402+ tryCompare(desktopStage, "state", "altTab")
1404+ // Release control, check if spread disappears
1405+ keyRelease(Qt.Key_Control)
1406+ tryCompare(desktopStage, "state", "")
1408+ // Focus should have switched back now
1409+ tryCompare(app3.session.surface, "activeFocus", true)
1412+ function test_altTabWrapAround() {
1413+ loadDesktopShellWithApps();
1415+ var desktopStage = findChild(shell, "stage");
1416+ verify(desktopStage !== null)
1418+ var appContainer = findInvisibleChild(shell, "appContainer")
1419+ verify(appContainer !== null)
1421+ var appRepeater = findInvisibleChild(shell, "appRepeater")
1422+ verify(appRepeater !== null)
1424+ // remember the focused appId
1425+ var focused = ApplicationManager.get(ApplicationManager.findApplication(ApplicationManager.focusedApplicationId));
1427+ tryCompare(desktopStage, "state", "")
1429+ // Just press Alt, make sure the spread comes up
1430+ keyPress(Qt.Key_Control);
1431+ keyClick(Qt.Key_Tab);
1432+ tryCompare(desktopStage, "state", "altTab")
1433+ tryCompare(appRepeater, "highlightedIndex", 1)
1434+ waitForRendering(shell)
1436+ // Now press and hold Tab, make sure the highlight moves all the way but stops at the last one
1437+ // We can't simulate a pressed key with keyPress() currently, so let's inject the events
1438+ // at API level. Jump for 10 times, verify that it's still at the last one and didn't wrap around.
1439+ for (var i = 0; i < 10; i++) {
1440+ appContainer.selectNext(true); // true == isAutoRepeat
1441+ wait(0); // Trigger the event loop to make sure all the things happen
1443+ tryCompare(appRepeater, "highlightedIndex", 6)
1445+ // Now release it once, and verify that it does wrap around with an additional Tab press
1446+ keyRelease(Qt.Key_Tab);
1447+ keyClick(Qt.Key_Tab);
1448+ tryCompare(appRepeater, "highlightedIndex", 0)
1450+ // Release control, check if spread disappears
1451+ keyRelease(Qt.Key_Control)
1452+ tryCompare(desktopStage, "state", "")
1454+ // Make sure that after wrapping around once, we have the same one focused as at the beginning
1455+ tryCompare(focused.session.surface, "activeFocus", true)
1458+ function test_altBackTabNavigation() {
1459+ loadDesktopShellWithApps();
1461+ var appRepeater = findInvisibleChild(shell, "appRepeater");
1462+ verify(appRepeater !== null);
1464+ keyPress(Qt.Key_Control)
1465+ keyClick(Qt.Key_Tab);
1466+ tryCompare(appRepeater, "highlightedIndex", 1);
1468+ keyClick(Qt.Key_Tab);
1469+ tryCompare(appRepeater, "highlightedIndex", 2);
1471+ keyClick(Qt.Key_Tab);
1472+ tryCompare(appRepeater, "highlightedIndex", 3);
1474+ keyClick(Qt.Key_Tab);
1475+ tryCompare(appRepeater, "highlightedIndex", 4);
1477+ keyClick(Qt.Key_Backtab);
1478+ tryCompare(appRepeater, "highlightedIndex", 3);
1480+ keyClick(Qt.Key_Backtab);
1481+ tryCompare(appRepeater, "highlightedIndex", 2);
1483+ keyClick(Qt.Key_Backtab);
1484+ tryCompare(appRepeater, "highlightedIndex", 1);
1486+ keyRelease(Qt.Key_Control);
1489+ function test_highlightFollowsMouse() {
1490+ loadDesktopShellWithApps()
1492+ var appRepeater = findInvisibleChild(shell, "appRepeater");
1493+ verify(appRepeater !== null);
1495+ keyPress(Qt.Key_Control)
1496+ keyClick(Qt.Key_Tab);
1498+ tryCompare(appRepeater, "highlightedIndex", 1);
1501+ var y = shell.height * .75;
1502+ mouseMove(shell, x, y)
1504+ for (var i = 0; i < 7; i++) {
1505+ while (appRepeater.highlightedIndex != i && x <= 4000) {
1507+ mouseMove(shell, x, y)
1508+ wait(0); // spin the loop so bindings get evaluated
1514+ keyRelease(Qt.Key_Control);
1517+ function test_closeFromSpread() {
1518+ loadDesktopShellWithApps()
1520+ var appRepeater = findInvisibleChild(shell, "appRepeater");
1521+ verify(appRepeater !== null);
1523+ keyPress(Qt.Key_Control)
1524+ keyClick(Qt.Key_Tab);
1526+ appRemovedSpy.clear();
1528+ var closedAppId = ApplicationManager.get(2).appId;
1529+ var appDelegate2 = appRepeater.itemAt(2);
1530+ var closeMouseArea = findChild(appDelegate2, "closeMouseArea");
1532+ // Move the mosue over tile 2 and verify the close button becomes visible
1534+ var y = shell.height * .5;
1535+ mouseMove(shell, x, y)
1536+ while (appRepeater.highlightedIndex !== 2 && x <= 4000) {
1538+ mouseMove(shell, x, y)
1539+ wait(0); // spin the loop so bindings get evaluated
1541+ tryCompare(closeMouseArea, "enabled", true)
1543+ // Close the app using the close button
1544+ mouseClick(closeMouseArea, closeMouseArea.width / 2, closeMouseArea.height / 2)
1546+ // Verify applicationRemoved has been emitted correctly
1547+ tryCompare(appRemovedSpy, "count", 1)
1548+ compare(appRemovedSpy.signalArguments[0][0], closedAppId);
1550+ keyRelease(Qt.Key_Control);
1553+ function test_selectFromSpreadWithMouse_data() {
1555+ {tag: "click on tileInfo", tileInfo: true },
1556+ {tag: "click on surface", tileInfo: false },
1560+ function test_selectFromSpreadWithMouse(data) {
1561+ loadDesktopShellWithApps()
1563+ var appRepeater = findInvisibleChild(shell, "appRepeater");
1564+ verify(appRepeater !== null);
1566+ keyPress(Qt.Key_Control)
1567+ keyClick(Qt.Key_Tab);
1569+ appRemovedSpy.clear();
1571+ var focusAppId = ApplicationManager.get(2).appId;
1572+ var appDelegate2 = appRepeater.itemAt(2);
1573+ var decoratedWindow = findChild(appDelegate2, "decoratedWindow");
1574+ var stage = findChild(shell, "stage");
1576+ tryCompare(stage, "state", "altTab");
1578+ // Move the mouse over tile 2 and verify the highlight becomes visible
1580+ var y = shell.height * (data.tileInfo ? .5 : 0.95)
1581+ mouseMove(shell, x, y)
1582+ while (appRepeater.highlightedIndex !== 2 && x <= 4000) {
1584+ mouseMove(shell, x, y)
1585+ wait(0); // spin the loop so bindings get evaluated
1587+ tryCompare(decoratedWindow, "highlightShown", true);
1590+ mouseClick(decoratedWindow, decoratedWindow.width / 2, decoratedWindow.height / 2)
1592+ // Verify that we left the spread and app2 is the focused one now
1593+ tryCompare(stage, "state", "");
1594+ tryCompare(ApplicationManager, "focusedApplicationId", focusAppId);
1596+ keyRelease(Qt.Key_Control);