@@ -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
@@ -66,6 +67,11 @@ Rectangle {
66 width: units.gu(40)
67 width: units.gu(40)
67 height: units.gu(71)
68 height: units.gu(71)
72+ GSettingsController.setUsageMode("Staged")
71 name: "tablet"
77 name: "tablet"
@@ -74,6 +80,28 @@ Rectangle {
74 width: units.gu(100)
80 width: units.gu(100)
75 height: units.gu(71)
81 height: units.gu(71)
85+ GSettingsController.setUsageMode("Staged")
93+ width: shellContainer.width
94+ height: shellContainer.height
97+ target: mouseEmulation
102+ GSettingsController.setUsageMode("Windowed")
@@ -81,6 +109,7 @@ Rectangle {
81 property bool itemDestroyed: false
109 property bool itemDestroyed: false
82 sourceComponent: Component {
110 sourceComponent: Component {
84 usageScenario: usageScenarioSelector.model[usageScenarioSelector.selectedIndex]
113 usageScenario: usageScenarioSelector.model[usageScenarioSelector.selectedIndex]
85 orientation: Qt.PortraitOrientation
114 orientation: Qt.PortraitOrientation
86 primaryOrientation: Qt.PortraitOrientation
115 primaryOrientation: Qt.PortraitOrientation
@@ -88,6 +117,10 @@ Rectangle {
88 Component.onDestruction: {
117 Component.onDestruction: {
89 shellLoader.itemDestroyed = true;
118 shellLoader.itemDestroyed = true;
120+ Component.onCompleted: {
121+ var keyMapper = testCase.findChild(__shell, "physicalKeysMapper");
122+ keyMapper.controlInsteadOfAlt = true;
@@ -112,16 +145,32 @@ Rectangle {
112 anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
145 anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
113 spacing: units.gu(1)
146 spacing: units.gu(1)
149+ spacing: units.gu(1)
115− Button {
150+ Button {
116− text: "Show Greeter"
151+ text: "Show Greeter"
117− activeFocusOnPress: false
152+ activeFocusOnPress: false
118− onClicked: {
153+ onClicked: {
119− if (shellLoader.status !== Loader.Ready)
154+ if (shellLoader.status !== Loader.Ready)
122− var greeter = testCase.findChild(shellLoader.item, "greeter");
157+ var greeter = testCase.findChild(shellLoader.item, "greeter");
123− if (!greeter.shown) {
158+ if (!greeter.shown) {
124− LightDM.Greeter.showGreeter();
159+ LightDM.Greeter.showGreeter();
164+ text: "Hide Greeter"
165+ activeFocusOnPress: false
167+ if (shellLoader.status !== Loader.Ready)
170+ var greeter = testCase.findChild(shellLoader.item, "greeter");
171+ if (greeter.shown) {
@@ -141,7 +190,7 @@ Rectangle {
141 anchors { left: parent.left; right: parent.right }
190 anchors { left: parent.left; right: parent.right }
142 activeFocusOnPress: false
191 activeFocusOnPress: false
143 text: "Size"
192 text: "Size"
144− model: ["phone", "tablet"]
193+ model: ["phone", "tablet", "desktop"]
145 onSelectedIndexChanged: {
194 onSelectedIndexChanged: {
146 shellLoader.active = false;
195 shellLoader.active = false;
147 shellLoader.state = model[selectedIndex];
196 shellLoader.state = model[selectedIndex];
@@ -163,6 +212,17 @@ Rectangle {
164 Label { text: "Applications"; font.bold: true }
213 Label { text: "Applications"; font.bold: true }
216+ text: "Start all apps"
219+ for (var i = 0; i < ApplicationManager.availableApplications.length; i++) {
220+ var appId = ApplicationManager.availableApplications[i];
221+ ApplicationManager.startApplication(appId)
166 Repeater {
226 Repeater {
167 id: appRepeater
227 id: appRepeater
168 model: ApplicationManager.availableApplications
228 model: ApplicationManager.availableApplications
@@ -226,6 +286,12 @@ Rectangle {
226 signalName: "actionInvoked"
286 signalName: "actionInvoked"
291+ target: ApplicationManager
292+ signalName: "applicationRemoved"
229 Telephony.CallEntry {
295 Telephony.CallEntry {
230 id: phoneCall
296 id: phoneCall
231 phoneNumber: "+447812221111"
297 phoneNumber: "+447812221111"
@@ -248,6 +314,7 @@ Rectangle {
250 function cleanup() {
316 function cleanup() {
317+ mouseEmulation.checked = true;
251 tryCompare(shell, "enabled", true); // make sure greeter didn't leave us in disabled state
318 tryCompare(shell, "enabled", true); // make sure greeter didn't leave us in disabled state
252 tearDown();
319 tearDown();
253 GSettingsController.setUsageMode("Staged");
320 GSettingsController.setUsageMode("Staged");
@@ -269,6 +336,20 @@ Rectangle {
269 waitForGreeterToStabilize();
336 waitForGreeterToStabilize();
339+ function loadDesktopShellWithApps() {
340+ loadShell("desktop");
341+ shell.usageScenario = "desktop"
342+ waitForRendering(root)
343+ var app1 = ApplicationManager.startApplication("dialer-app")
344+ var app2 = ApplicationManager.startApplication("webbrowser-app")
345+ var app3 = ApplicationManager.startApplication("camera-app")
346+ var app4 = ApplicationManager.startApplication("facebook-webapp")
347+ var app5 = ApplicationManager.startApplication("calendar-app")
348+ var app6 = ApplicationManager.startApplication("gallery-app")
349+ var app7 = ApplicationManager.startApplication("camera-app")
350+ waitUntilAppWindowIsFullyLoaded(app7);
272 function waitForGreeterToStabilize() {
353 function waitForGreeterToStabilize() {
273 var greeter = findChild(shell, "greeter");
354 var greeter = findChild(shell, "greeter");
274 verify(greeter);
355 verify(greeter);
@@ -759,7 +840,7 @@ Rectangle {
760 // check that the desktop stage and window have been loaded
841 // check that the desktop stage and window have been loaded
762− var desktopWindow = findChild(shell, "decoratedWindow_webbrowser-app");
843+ var desktopWindow = findChild(shell, "appWindow_webbrowser-app");
763 verify(desktopWindow);
844 verify(desktopWindow);
@@ -1265,5 +1346,228 @@ Rectangle {
1265 var launcher = findChild(shell, "launcher");
1346 var launcher = findChild(shell, "launcher");
1266 compare(launcher.inverted, data.launcherInverted);
1347 compare(launcher.inverted, data.launcherInverted);
1350+ function test_altTabSwitchesFocus() {
1351+ loadShell("desktop");
1352+ shell.usageScenario = "desktop"
1353+ waitForRendering(root)
1355+ var desktopStage = findChild(shell, "stage");
1356+ verify(desktopStage != null)
1358+ var app1 = ApplicationManager.startApplication("dialer-app")
1359+ waitUntilAppWindowIsFullyLoaded(app1);
1360+ var app2 = ApplicationManager.startApplication("webbrowser-app")
1361+ waitUntilAppWindowIsFullyLoaded(app2);
1362+ var app3 = ApplicationManager.startApplication("camera-app")
1363+ waitUntilAppWindowIsFullyLoaded(app3);
1365+ // Do a quick alt-tab and see if focus changes
1366+ tryCompare(app3.session.surface, "activeFocus", true)
1367+ keyClick(Qt.Key_Tab, Qt.ControlModifier)
1368+ tryCompare(app2.session.surface, "activeFocus", true)
1371+ tryCompare(desktopStage, "state", "")
1373+ // Just press Alt, make sure the spread comes up
1374+ keyPress(Qt.Key_Control);
1375+ keyClick(Qt.Key_Tab);
1376+ tryCompare(desktopStage, "state", "altTab")
1378+ // Release control, check if spread disappears
1379+ keyRelease(Qt.Key_Control)
1380+ tryCompare(desktopStage, "state", "")
1382+ // Focus should have switched back now
1383+ tryCompare(app3.session.surface, "activeFocus", true)
1386+ function test_altTabWrapAround() {
1387+ loadDesktopShellWithApps();
1389+ var desktopStage = findChild(shell, "stage");
1390+ verify(desktopStage !== null)
1392+ var appContainer = findInvisibleChild(shell, "appContainer")
1393+ verify(appContainer !== null)
1395+ var appRepeater = findInvisibleChild(shell, "appRepeater")
1396+ verify(appRepeater !== null)
1398+ // remember the focused appId
1399+ var focused = ApplicationManager.get(ApplicationManager.findApplication(ApplicationManager.focusedApplicationId));
1401+ tryCompare(desktopStage, "state", "")
1403+ // Just press Alt, make sure the spread comes up
1404+ keyPress(Qt.Key_Control);
1405+ keyClick(Qt.Key_Tab);
1406+ tryCompare(desktopStage, "state", "altTab")
1407+ tryCompare(appRepeater, "highlightedIndex", 1)
1408+ waitForRendering(shell)
1410+ // Now press and hold Tab, make sure the highlight moves all the way but stops at the last one
1411+ // We can't simulate a pressed key with keyPress() currently, so let's inject the events
1412+ // at API level. Jump for 10 times, verify that it's still at the last one and didn't wrap around.
1413+ for (var i = 0; i < 10; i++) {
1414+ appContainer.selectNext(true); // true == isAutoRepeat
1415+ wait(0); // Trigger the event loop to make sure all the things happen
1417+ tryCompare(appRepeater, "highlightedIndex", 6)
1419+ // Now release it once, and verify that it does wrap around with an additional Tab press
1420+ keyRelease(Qt.Key_Tab);
1421+ keyClick(Qt.Key_Tab);
1422+ tryCompare(appRepeater, "highlightedIndex", 0)
1424+ // Release control, check if spread disappears
1425+ keyRelease(Qt.Key_Control)
1426+ tryCompare(desktopStage, "state", "")
1428+ // Make sure that after wrapping around once, we have the same one focused as at the beginning
1429+ tryCompare(focused.session.surface, "activeFocus", true)
1432+ function test_altBackTabNavigation() {
1433+ loadDesktopShellWithApps();
1435+ var appRepeater = findInvisibleChild(shell, "appRepeater");
1436+ verify(appRepeater !== null);
1438+ keyPress(Qt.Key_Control)
1439+ keyClick(Qt.Key_Tab);
1440+ tryCompare(appRepeater, "highlightedIndex", 1);
1442+ keyClick(Qt.Key_Tab);
1443+ tryCompare(appRepeater, "highlightedIndex", 2);
1445+ keyClick(Qt.Key_Tab);
1446+ tryCompare(appRepeater, "highlightedIndex", 3);
1448+ keyClick(Qt.Key_Tab);
1449+ tryCompare(appRepeater, "highlightedIndex", 4);
1451+ keyClick(Qt.Key_Backtab);
1452+ tryCompare(appRepeater, "highlightedIndex", 3);
1454+ keyClick(Qt.Key_Backtab);
1455+ tryCompare(appRepeater, "highlightedIndex", 2);
1457+ keyClick(Qt.Key_Backtab);
1458+ tryCompare(appRepeater, "highlightedIndex", 1);
1460+ keyRelease(Qt.Key_Control);
1463+ function test_highlightFollowsMouse() {
1464+ loadDesktopShellWithApps()
1466+ var appRepeater = findInvisibleChild(shell, "appRepeater");
1467+ verify(appRepeater !== null);
1469+ keyPress(Qt.Key_Control)
1470+ keyClick(Qt.Key_Tab);
1472+ tryCompare(appRepeater, "highlightedIndex", 1);
1475+ var y = shell.height * .75;
1476+ mouseMove(shell, x, y)
1478+ for (var i = 0; i < 7; i++) {
1479+ while (appRepeater.highlightedIndex != i && x <= 4000) {
1481+ mouseMove(shell, x, y)
1482+ waitForRendering(shell)
1488+ keyRelease(Qt.Key_Control);
1491+ function test_closeFromSpread() {
1492+ loadDesktopShellWithApps()
1494+ var appRepeater = findInvisibleChild(shell, "appRepeater");
1495+ verify(appRepeater !== null);
1497+ keyPress(Qt.Key_Control)
1498+ keyClick(Qt.Key_Tab);
1500+ appRemovedSpy.clear();
1502+ var closedAppId = ApplicationManager.get(2).appId;
1503+ var appDelegate2 = appRepeater.itemAt(2);
1504+ var closeMouseArea = findChild(appDelegate2, "closeMouseArea");
1506+ // Move the mosue over tile 2 and verify the close button becomes visible
1508+ var y = shell.height * .5;
1509+ mouseMove(shell, x, y)
1510+ while (appRepeater.highlightedIndex !== 2 && x <= 4000) {
1512+ mouseMove(shell, x, y)
1513+ waitForRendering(shell)
1515+ tryCompare(closeMouseArea, "enabled", true)
1517+ // Close the app using the close button
1518+ mouseClick(closeMouseArea, closeMouseArea.width / 2, closeMouseArea.height / 2)
1520+ // Verify applicationRemoved has been emitted correctly
1521+ tryCompare(appRemovedSpy, "count", 1)
1522+ compare(appRemovedSpy.signalArguments[0][0], closedAppId);
1524+ keyRelease(Qt.Key_Control);
1527+ function test_selectFromSpreadWithMouse_data() {
1529+ {tag: "click on tileInfo", tileInfo: true },
1530+ {tag: "click on surface", tileInfo: false },
1534+ function test_selectFromSpreadWithMouse(data) {
1535+ loadDesktopShellWithApps()
1537+ var appRepeater = findInvisibleChild(shell, "appRepeater");
1538+ verify(appRepeater !== null);
1540+ keyPress(Qt.Key_Control)
1541+ keyClick(Qt.Key_Tab);
1543+ appRemovedSpy.clear();
1545+ var focusAppId = ApplicationManager.get(2).appId;
1546+ var appDelegate2 = appRepeater.itemAt(2);
1547+ var decoratedWindow = findChild(appDelegate2, "decoratedWindow");
1548+ var stage = findChild(shell, "stage");
1550+ tryCompare(stage, "state", "altTab");
1552+ // Move the mouse over tile 2 and verify the highlight becomes visible
1554+ var y = shell.height * (data.tileInfo ? .5 : 0.95)
1555+ mouseMove(shell, x, y)
1556+ while (appRepeater.highlightedIndex !== 2 && x <= 4000) {
1558+ mouseMove(shell, x, y)
1559+ waitForRendering(shell)
1561+ tryCompare(decoratedWindow, "highlightShown", true);
1564+ mouseClick(decoratedWindow, decoratedWindow.width / 2, decoratedWindow.height / 2)
1566+ // Verify that we left the spread and app2 is the focused one now
1567+ tryCompare(stage, "state", "");
1568+ tryCompare(ApplicationManager, "focusedApplicationId", focusAppId);
1570+ keyRelease(Qt.Key_Control);