on xenial help sign in
merge prereq
commitcad55296f0550b85b489428b81fc545a30ae7f2b authorMichael Zanetti <michael.zanetti@canonical.com> dateWed 27 Jan 2016, 23:12 (11 years ago) parent2f4f64d644f2a8
7 files changed+140−33
qml/OrientedShell.qml+13−4 qml/Shell.qml+3−3 qml/Stages/AbstractStage.qml+5−1 qml/Stages/DesktopStage.qml+6−1 qml/Stages/PhoneStage.qml+5−1 qml/Stages/TabletStage.qml+5−1 tests/qmltests/tst_OrientedShell.qml+103−22
qml/OrientedShell.qml+13−4
@@ -202,11 +202,20 @@ Rectangle {
202202 return "tablet";
203203 }
204204 } else { // automatic
205− if (miceModel.count + touchPadModel.count > 0) {
206− return "desktop";
207− } else {
208− return deviceConfiguration.category;
205+ var longEdgeWidth = Math.max(root.width, root.height)
206+ print("Automatic mode:", longEdgeWidth, "gu size", units.gu(1), "kbds", keyboardsModel.count, "mice", miceModel.count + touchPadModel.count, root)
207+ if (longEdgeWidth > units.gu(120)) {
208+ print("longedge is big!")
209+ if (keyboardsModel.count + miceModel.count + touchPadModel.count > 0) {
210+ return "desktop";
211+ }
212+ } else if (longEdgeWidth > units.gu(90)){
213+ if (miceModel.count + touchPadModel.count > 0) {
214+ return "desktop";
215+ }
209216 }
217+
218+ return deviceConfiguration.category;
210219 }
211220 }
212221
qml/Shell.qml+3−3
@@ -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
@@ -84,8 +84,8 @@ Item {
8484 return Qt.PrimaryOrientation;
8585 } else if (greeter && greeter.shown) {
8686 return Qt.PrimaryOrientation;
87− } else if (mainApp) {
88− return shell.orientations.map(mainApp.supportedOrientations);
87+ } else if (applicationsDisplayLoader.item) {
88+ return shell.orientations.map(applicationsDisplayLoader.item.supportedOrientations);
8989 } else {
9090 // we just don't care
9191 return Qt.PortraitOrientation
qml/Stages/AbstractStage.qml+5−1
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2015 Canonical, Ltd.
2+ * Copyright (C) 2015-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
@@ -44,6 +44,10 @@ Rectangle {
4444 property var mainApp: null
4545 property int mainAppWindowOrientationAngle
4646 property bool orientationChangesEnabled
47+ property int supportedOrientations: Qt.PortraitOrientation
48+ | Qt.LandscapeOrientation
49+ | Qt.InvertedPortraitOrientation
50+ | Qt.InvertedLandscapeOrientation
4751
4852 // Shared code for use in stage implementations
4953 GSettings {
qml/Stages/DesktopStage.qml+6−1
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2014-2015 Canonical, Ltd.
2+ * Copyright (C) 2014-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
@@ -40,6 +40,11 @@ AbstractStage {
4040 ? ApplicationManager.findApplication(ApplicationManager.focusedApplicationId)
4141 : null
4242
43+ // application windows never rotate independently
44+ mainAppWindowOrientationAngle: shellOrientationAngle
45+
46+ orientationChangesEnabled: true
47+
4348 Connections {
4449 target: ApplicationManager
4550 onApplicationAdded: {
qml/Stages/PhoneStage.qml+5−1
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2014-2015 Canonical, Ltd.
2+ * Copyright (C) 2014-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
@@ -83,6 +83,10 @@ AbstractStage {
8383 && !(priv.focusedAppDelegate && priv.focusedAppDelegate.xBehavior.running)
8484 && spreadView.phase === 0
8585
86+ supportedOrientations: mainApp ? mainApp.supportedOrientations
87+ : (Qt.PortraitOrientation | Qt.LandscapeOrientation
88+ | Qt.InvertedPortraitOrientation | Qt.InvertedLandscapeOrientation)
89+
8690 // How far left the stage has been dragged
8791 readonly property real dragProgress: spreadRepeater.count > 0 ? -spreadRepeater.itemAt(0).xTranslate : 0
8892
qml/Stages/TabletStage.qml+5−1
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2014-2015 Canonical, Ltd.
2+ * Copyright (C) 2014-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
@@ -72,6 +72,10 @@ AbstractStage {
7272
7373 orientationChangesEnabled: priv.mainAppOrientationChangesEnabled
7474
75+ supportedOrientations: mainApp ? mainApp.supportedOrientations
76+ : (Qt.PortraitOrientation | Qt.LandscapeOrientation
77+ | Qt.InvertedPortraitOrientation | Qt.InvertedLandscapeOrientation)
78+
7579 onWidthChanged: {
7680 spreadView.selectedIndex = -1;
7781 spreadView.phase = 0;
tests/qmltests/tst_OrientedShell.qml+103−22
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2015 Canonical, Ltd.
2+ * Copyright (C) 2015-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
@@ -292,6 +292,9 @@ Rectangle {
292292 activeFocusOnPress: false
293293 text: "Usage Mode"
294294 model: ["Staged", "Windowed", "Automatic"]
295+ function selectStaged() {selectedIndex = 0;}
296+ function selectWindowed() {selectedIndex = 1;}
297+ function selectAutomatic() {selectedIndex = 2;}
295298 }
296299 MouseTouchEmulationCheckbox {
297300 checked: true
@@ -393,7 +396,7 @@ Rectangle {
393396 activeFocusOnPress: false
394397 property string prevDevName: "mako"
395398 onClicked: {
396− usageModeSelector.selectedIndex = 2; // "Automatic"
399+ usageModeSelector.selectAutomatic();
397400
398401 if (applicationArguments.deviceName === "desktop") {
399402 applicationArguments.deviceName = prevDevName;
@@ -457,6 +460,8 @@ Rectangle {
457460 signalSpy.signalName = "";
458461
459462 LightDM.Greeter.authenticate(""); // reset greeter
463+
464+ usageModeSelector.selectStaged();
460465 }
461466
462467 function cleanup() {
@@ -996,37 +1001,55 @@ Rectangle {
9961001 tryCompare(shell, "transformRotationAngle", 0);
9971002 }
9981003
999− function test_attachRemoveInputDevices() {
1000− usageModeSelector.selectedIndex = 2;
1004+ function test_attachRemoveInputDevices_data() {
1005+ return [
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 },
1018+ ]
1019+ }
1020+
1021+ function test_attachRemoveInputDevices(data) {
1022+ usageModeSelector.selectAutomatic();
10011023 tryCompare(mockUnity8Settings, "usageMode", "Automatic")
10021024
10031025 loadShell("mako")
10041026 var shell = findChild(orientedShell, "shell");
10051027
1006− tryCompare(shell, "usageScenario", "phone");
1007− tryCompare(mockOskSettings, "stayHidden", false);
1028+ var oldWidth = orientedShellLoader.width;
1029+ orientedShellLoader.width = data.screenWidth;
10081030
1009− MockInputDeviceBackend.addMockDevice("/kbd0", InputInfo.Keyboard);
10101031 tryCompare(shell, "usageScenario", "phone");
1011− tryCompare(mockOskSettings, "stayHidden", true);
1012−
1013− MockInputDeviceBackend.addMockDevice("/mouse0", InputInfo.Mouse);
1014− tryCompare(shell, "usageScenario", "desktop");
1015− tryCompare(mockOskSettings, "stayHidden", true);
1016−
1017− MockInputDeviceBackend.removeDevice("/kbd0");
1018− tryCompare(shell, "usageScenario", "desktop");
10191032 tryCompare(mockOskSettings, "stayHidden", false);
10201033
1021− MockInputDeviceBackend.removeDevice("/mouse0");
1022− tryCompare(shell, "usageScenario", "phone");
1023− tryCompare(mockOskSettings, "stayHidden", false);
1034+ if (data.kbd) {
1035+ MockInputDeviceBackend.addMockDevice("/kbd0", InputInfo.Keyboard);
1036+ }
1037+ if (data.mouse) {
1038+ MockInputDeviceBackend.addMockDevice("/mouse0", InputInfo.Mouse);
1039+ }
10241040
1025− MockInputDeviceBackend.addMockDevice("/touchpad0", InputInfo.TouchPad);
1026− tryCompare(shell, "usageScenario", "desktop");
1041+ tryCompare(shell, "usageScenario", data.expectedMode);
1042+ tryCompare(mockOskSettings, "stayHidden", !data.oskExpected);
10271043
1028− MockInputDeviceBackend.removeDevice("/touchpad0");
1029− tryCompare(shell, "usageScenario", "phone");
1044+ if (data.kbd) {
1045+ MockInputDeviceBackend.removeDevice("/kbd0");
1046+ }
1047+ if (data.mouse) {
1048+ MockInputDeviceBackend.removeDevice("/mouse0");
1049+ }
1050+
1051+ // Restore width
1052+ orientedShellLoader.width = oldWidth;
10301053 }
10311054
10321055 /*
@@ -1140,6 +1163,61 @@ Rectangle {
11401163 tryCompare(shell, "transformRotationAngle" , 0);
11411164 }
11421165
1166+ /*
1167+ Regression test for https://launchpad.net/bugs/1515977
1168+
1169+ Preconditions:
1170+ UI in Desktop mode and landscape
1171+
1172+ Steps:
1173+ - Launch a portrait-only application
1174+
1175+ Expected outcome:
1176+ - Shell stays in landscape
1177+
1178+ Buggy outcome:
1179+ - Shell would rotate to portrait as the newly-focused app doesn't support landscape
1180+ */
1181+ function test_portraitOnlyAppInLandscapeDesktop_data() {
1182+ return [
1183+ {tag: "mako", deviceName: "mako"},
1184+ {tag: "manta", deviceName: "manta"},
1185+ {tag: "flo", deviceName: "flo"}
1186+ ];
1187+ }
1188+ function test_portraitOnlyAppInLandscapeDesktop(data) {
1189+ loadShell(data.deviceName);
1190+
1191+ ////
1192+ // setup preconditions (put shell in Desktop mode and landscape)
1193+
1194+ usageModeSelector.selectWindowed();
1195+
1196+ orientedShell.physicalOrientation = orientedShell.orientations.landscape;
1197+ waitUntilShellIsInOrientation(orientedShell.orientations.landscape);
1198+ waitForRotationAnimationsToFinish();
1199+
1200+ ////
1201+ // Launch a portrait-only application
1202+
1203+ var dialerApp = ApplicationManager.startApplication("dialer-app");
1204+ verify(dialerApp);
1205+
1206+ // ensure the mock dialer-app is as we expect
1207+ compare(dialerApp.rotatesWindowContents, false);
1208+ compare(dialerApp.supportedOrientations, Qt.PortraitOrientation | Qt.InvertedPortraitOrientation);
1209+
1210+ waitUntilAppSurfaceShowsUp("dialer-app");
1211+ waitUntilAppWindowCanRotate("dialer-app");
1212+ verify(isAppSurfaceFocused("dialer-app"));
1213+
1214+ ////
1215+ // check outcome (shell should stay in landscape)
1216+
1217+ waitForRotationAnimationsToFinish();
1218+ compare(shell.orientation, orientedShell.orientations.landscape);
1219+ }
1220+
11431221 // angle - rotation angle in degrees clockwise, relative to the primary orientation.
11441222 function rotateTo(angle) {
11451223 switch (angle) {
@@ -1158,7 +1236,10 @@ Rectangle {
11581236 default:
11591237 verify(false);
11601238 }
1239+ waitForRotationAnimationsToFinish();
1240+ }
11611241
1242+ function waitForRotationAnimationsToFinish() {
11621243 var rotationStates = findInvisibleChild(orientedShell, "rotationStates");
11631244 verify(rotationStates.d);
11641245 verify(rotationStates.d.stateUpdateTimer);