@@ -1,5 +1,5 @@
2− * Copyright (C) 2015 Canonical, Ltd.
2+ * Copyright (C) 2015-2016 Canonical, Ltd.
4 * This program is free software; you can redistribute it and/or modify
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
5 * it under the terms of the GNU General Public License as published by
@@ -292,6 +292,9 @@ Rectangle {
292 activeFocusOnPress: false
292 activeFocusOnPress: false
293 text: "Usage Mode"
293 text: "Usage Mode"
294 model: ["Staged", "Windowed", "Automatic"]
294 model: ["Staged", "Windowed", "Automatic"]
295+ function selectStaged() {selectedIndex = 0;}
296+ function selectWindowed() {selectedIndex = 1;}
297+ function selectAutomatic() {selectedIndex = 2;}
296 MouseTouchEmulationCheckbox {
299 MouseTouchEmulationCheckbox {
297 checked: true
300 checked: true
@@ -393,7 +396,7 @@ Rectangle {
393 activeFocusOnPress: false
396 activeFocusOnPress: false
394 property string prevDevName: "mako"
397 property string prevDevName: "mako"
395 onClicked: {
398 onClicked: {
396− usageModeSelector.selectedIndex = 2; // "Automatic"
399+ usageModeSelector.selectAutomatic();
398 if (applicationArguments.deviceName === "desktop") {
401 if (applicationArguments.deviceName === "desktop") {
399 applicationArguments.deviceName = prevDevName;
402 applicationArguments.deviceName = prevDevName;
@@ -457,6 +460,8 @@ Rectangle {
457 signalSpy.signalName = "";
460 signalSpy.signalName = "";
459 LightDM.Greeter.authenticate(""); // reset greeter
462 LightDM.Greeter.authenticate(""); // reset greeter
464+ usageModeSelector.selectStaged();
462 function cleanup() {
467 function cleanup() {
@@ -996,37 +1001,58 @@ Rectangle {
996 tryCompare(shell, "transformRotationAngle", 0);
1001 tryCompare(shell, "transformRotationAngle", 0);
1004+ function test_attachRemoveInputDevices_data() {
1006+ { tag: "small screen, no devices", screenWidth: units.gu(50), mouse: false, kbd: false, expectedMode: "phone", oskExpected: true },
1007+ { tag: "medium screen, no devices", screenWidth: units.gu(100), mouse: false, kbd: false, expectedMode: "phone", oskExpected: true },
1008+ { tag: "big screen, no devices", screenWidth: units.gu(200), mouse: false, kbd: false, expectedMode: "phone", oskExpected: true },
1009+ { tag: "small screen, mouse", screenWidth: units.gu(50), mouse: true, kbd: false, expectedMode: "phone", oskExpected: true },
1010+ { tag: "medium screen, mouse", screenWidth: units.gu(100), mouse: true, kbd: false, expectedMode: "desktop", oskExpected: true },
1011+ { tag: "big screen, mouse", screenWidth: units.gu(200), mouse: true, kbd: false, expectedMode: "desktop", oskExpected: true },
1012+ { tag: "small screen, kbd", screenWidth: units.gu(50), mouse: false, kbd: true, expectedMode: "phone", oskExpected: false },
1013+ { tag: "medium screen, kbd", screenWidth: units.gu(100), mouse: false, kbd: true, expectedMode: "phone", oskExpected: false },
1014+ { tag: "big screen, kbd", screenWidth: units.gu(200), mouse: false, kbd: true, expectedMode: "desktop", oskExpected: false },
1015+ { tag: "small screen, mouse & kbd", screenWidth: units.gu(50), mouse: true, kbd: true, expectedMode: "phone", oskExpected: false },
1016+ { tag: "medium screen, mouse & kbd", screenWidth: units.gu(100), mouse: true, kbd: true, expectedMode: "desktop", oskExpected: false },
1017+ { tag: "big screen, mouse & kbd", screenWidth: units.gu(200), mouse: true, kbd: true, expectedMode: "desktop", oskExpected: false },
999− function test_attachRemoveInputDevices() {
1021+ function test_attachRemoveInputDevices(data) {
1000− usageModeSelector.selectedIndex = 2;
1022+ usageModeSelector.selectAutomatic();
1001 tryCompare(mockUnity8Settings, "usageMode", "Automatic")
1023 tryCompare(mockUnity8Settings, "usageMode", "Automatic")
1003 loadShell("mako")
1025 loadShell("mako")
1004 var shell = findChild(orientedShell, "shell");
1026 var shell = findChild(orientedShell, "shell");
1027+ var inputMethod = findChild(shell, "inputMethod");
1006− tryCompare(shell, "usageScenario", "phone");
1029+ var oldWidth = orientedShellLoader.width;
1007− tryCompare(mockOskSettings, "stayHidden", false);
1030+ orientedShellLoader.width = data.screenWidth;
1009− MockInputDeviceBackend.addMockDevice("/kbd0", InputInfo.Keyboard);
1010 tryCompare(shell, "usageScenario", "phone");
1032 tryCompare(shell, "usageScenario", "phone");
1011− tryCompare(mockOskSettings, "stayHidden", true);
1033+ tryCompare(inputMethod, "enabled", true);
1012−
1034+ tryCompare(mockOskSettings, "disableHeight", false);
1013− MockInputDeviceBackend.addMockDevice("/mouse0", InputInfo.Mouse);
1014− tryCompare(shell, "usageScenario", "desktop");
1015− tryCompare(mockOskSettings, "stayHidden", true);
1017− MockInputDeviceBackend.removeDevice("/kbd0");
1037+ MockInputDeviceBackend.addMockDevice("/kbd0", InputInfo.Keyboard);
1018− tryCompare(shell, "usageScenario", "desktop");
1038+ }
1019− tryCompare(mockOskSettings, "stayHidden", false);
1039+ if (data.mouse) {
1040+ MockInputDeviceBackend.addMockDevice("/mouse0", InputInfo.Mouse);
1021− MockInputDeviceBackend.removeDevice("/mouse0");
1022− tryCompare(shell, "usageScenario", "phone");
1043+ tryCompare(shell, "usageScenario", data.expectedMode);
1044+ tryCompare(inputMethod, "enabled", data.oskExpected);
1023− tryCompare(mockOskSettings, "stayHidden", false);
1045+ tryCompare(mockOskSettings, "disableHeight", data.expectedMode == "desktop" || data.kbd);
1025− MockInputDeviceBackend.addMockDevice("/touchpad0", InputInfo.TouchPad);
1048+ MockInputDeviceBackend.removeDevice("/kbd0");
1026− tryCompare(shell, "usageScenario", "desktop");
1049+ }
1051+ MockInputDeviceBackend.removeDevice("/mouse0");
1028− MockInputDeviceBackend.removeDevice("/touchpad0");
1054+ // Restore width
1029− tryCompare(shell, "usageScenario", "phone");
1055+ orientedShellLoader.width = oldWidth;
@@ -1140,6 +1166,61 @@ Rectangle {
1140 tryCompare(shell, "transformRotationAngle" , 0);
1166 tryCompare(shell, "transformRotationAngle" , 0);
1170+ Regression test for https://launchpad.net/bugs/1515977
1173+ UI in Desktop mode and landscape
1176+ - Launch a portrait-only application
1179+ - Shell stays in landscape
1182+ - Shell would rotate to portrait as the newly-focused app doesn't support landscape
1184+ function test_portraitOnlyAppInLandscapeDesktop_data() {
1186+ {tag: "mako", deviceName: "mako"},
1187+ {tag: "manta", deviceName: "manta"},
1188+ {tag: "flo", deviceName: "flo"}
1191+ function test_portraitOnlyAppInLandscapeDesktop(data) {
1192+ loadShell(data.deviceName);
1195+ // setup preconditions (put shell in Desktop mode and landscape)
1197+ usageModeSelector.selectWindowed();
1199+ orientedShell.physicalOrientation = orientedShell.orientations.landscape;
1200+ waitUntilShellIsInOrientation(orientedShell.orientations.landscape);
1201+ waitForRotationAnimationsToFinish();
1204+ // Launch a portrait-only application
1206+ var dialerApp = ApplicationManager.startApplication("dialer-app");
1209+ // ensure the mock dialer-app is as we expect
1210+ compare(dialerApp.rotatesWindowContents, false);
1211+ compare(dialerApp.supportedOrientations, Qt.PortraitOrientation | Qt.InvertedPortraitOrientation);
1213+ waitUntilAppSurfaceShowsUp("dialer-app");
1214+ waitUntilAppWindowCanRotate("dialer-app");
1215+ verify(isAppSurfaceFocused("dialer-app"));
1218+ // check outcome (shell should stay in landscape)
1220+ waitForRotationAnimationsToFinish();
1221+ compare(shell.orientation, orientedShell.orientations.landscape);
1143 // angle - rotation angle in degrees clockwise, relative to the primary orientation.
1224 // angle - rotation angle in degrees clockwise, relative to the primary orientation.
1144 function rotateTo(angle) {
1225 function rotateTo(angle) {
1145 switch (angle) {
1226 switch (angle) {
@@ -1158,7 +1239,10 @@ Rectangle {
1158 default:
1239 default:
1159 verify(false);
1240 verify(false);
1242+ waitForRotationAnimationsToFinish();
1245+ function waitForRotationAnimationsToFinish() {
1162 var rotationStates = findInvisibleChild(orientedShell, "rotationStates");
1246 var rotationStates = findInvisibleChild(orientedShell, "rotationStates");
1163 verify(rotationStates.d);
1247 verify(rotationStates.d);
1164 verify(rotationStates.d.stateUpdateTimer);
1248 verify(rotationStates.d.stateUpdateTimer);