on xenial help sign in
PhoneStage: ensure you're left in a consistent state after being reset Fixes: #1476757

Approved by: Michael Zanetti

commit6b199883eec7313bfe7d1e91bfb1b63dc59098db authorDaniel d'Andrada <daniel.dandrada@canonical.com> dateFri 25 Sep 2015, 12:12 (11 years ago) parent643e2b50bb912b
3 files changed+122−9
qml/Stages/PhoneStage.qml+15−7 qml/Stages/SpreadDelegate.qml+1−1 tests/qmltests/tst_OrientedShell.qml+106−1
qml/Stages/PhoneStage.qml+15−7
@@ -48,17 +48,12 @@ Rectangle {
4848 onBeingResizedChanged: {
4949 if (beingResized) {
5050 // Brace yourselves for impact!
51− spreadView.selectedIndex = -1;
52− spreadView.phase = 0;
53− spreadView.contentX = -spreadView.shift;
51+ priv.reset();
5452 }
5553 }
5654 onSpreadEnabledChanged: {
5755 if (!spreadEnabled) {
58− // reset. go back to display the focused app
59− spreadView.selectedIndex = -1;
60− spreadView.phase = 0;
61− spreadView.contentX = -spreadView.shift;
56+ priv.reset();
6257 }
6358 }
6459 function updateFocusedAppOrientation() {
@@ -94,6 +89,7 @@ Rectangle {
9489 readonly property var mainApp: applicationManager.focusedApplicationId
9590 ? applicationManager.findApplication(applicationManager.focusedApplicationId)
9691 : null
92+
9793 property int mainAppWindowOrientationAngle: 0
9894 readonly property bool orientationChangesEnabled: priv.focusedAppOrientationChangesEnabled
9995 && !priv.focusedAppDelegateIsDislocated
@@ -216,6 +212,18 @@ Rectangle {
216212 // Is more stable than "spreadView.shiftedContentX === 0" as it filters out noise caused by
217213 // Flickable.contentX changing due to resizes.
218214 property bool fullyShowingFocusedApp: true
215+
216+ function reset() {
217+ // The app that's about to go to foreground has to be focused, otherwise
218+ // it would leave us in an inconsistent state.
219+ if (!root.applicationManager.focusedApplicationId && root.applicationManager.count > 0) {
220+ root.applicationManager.focusApplication(root.applicationManager.get(0).appId);
221+ }
222+
223+ spreadView.selectedIndex = -1;
224+ spreadView.phase = 0;
225+ spreadView.contentX = -spreadView.shift;
226+ }
219227 }
220228 Timer {
221229 id: fullyShowingFocusedAppUpdateTimer
qml/Stages/SpreadDelegate.qml+1−1
@@ -268,7 +268,7 @@ FocusScope {
268268 focus: true
269269 anchors {
270270 fill: parent
271− topMargin: appWindow.fullscreen || application.rotatesWindowContents
271+ topMargin: appWindow.fullscreen || (application && application.rotatesWindowContents)
272272 ? 0 : maximizedAppTopMargin
273273 }
274274
tests/qmltests/tst_OrientedShell.qml+106−1
@@ -996,6 +996,60 @@ Rectangle {
996996 tryCompare(shell, "transformRotationAngle", root.primaryOrientationAngle);
997997 }
998998
999+ /*
1000+ Regression test for https://bugs.launchpad.net/ubuntu/+source/unity8/+bug/1476757
1001+
1002+ Steps:
1003+ 1- have a portrait-only app in foreground (eg unity8-dash)
1004+ 2- launch or switch to some other application
1005+ 3- right-edge swipe to show the apps spread
1006+ 4- swipe up to close the current app (the one from step 2)
1007+ 5- lock the phone (press the power button)
1008+ 6- unlock the phone (press power button again and swipe greeter away)
1009+ * app from step 1 should be on foreground and focused
1010+ 7- rotate phone
1011+
1012+ Expected outcome:
1013+ - The portrait-only application stays put
1014+
1015+ Actual outcome:
1016+ - The portrait-only application rotates freely
1017+ */
1018+ function test_lockPhoneAfterClosingAppInSpreadThenUnlockAndRotate() {
1019+ loadShell("mako");
1020+
1021+ var gmailApp = ApplicationManager.startApplication("gmail-webapp");
1022+ verify(gmailApp);
1023+
1024+ waitUntilAppSurfaceShowsUp("gmail-webapp");
1025+
1026+ performEdgeSwipeToShowAppSpread();
1027+
1028+ swipeToCloseCurrentAppInSpread();
1029+
1030+ // press the power key once
1031+ Powerd.setStatus(Powerd.Off, Powerd.Unknown);
1032+ var greeter = findChild(shell, "greeter");
1033+ tryCompare(greeter, "fullyShown", true);
1034+
1035+ // and a second time to turn the display back on
1036+ Powerd.setStatus(Powerd.On, Powerd.Unknown);
1037+
1038+ swipeAwayGreeter();
1039+
1040+ verify(isAppSurfaceFocused("unity8-dash"))
1041+
1042+ signalSpy.clear();
1043+ signalSpy.target = shell;
1044+ signalSpy.signalName = "widthChanged";
1045+ verify(signalSpy.valid);
1046+
1047+ rotateTo(90);
1048+
1049+ // shell shouldn't have change its orientation at any moment
1050+ compare(signalSpy.count, 0);
1051+ }
1052+
9991053 // angle - rotation angle in degrees clockwise, relative to the primary orientation.
10001054 function rotateTo(angle) {
10011055 switch (angle) {
@@ -1016,6 +1070,12 @@ Rectangle {
10161070 }
10171071
10181072 var rotationStates = findInvisibleChild(orientedShell, "rotationStates");
1073+ verify(rotationStates.d);
1074+ verify(rotationStates.d.stateUpdateTimer);
1075+
1076+ // wait for the delayed state update to take place, if any
1077+ tryCompare(rotationStates.d.stateUpdateTimer, "running", false);
1078+
10191079 waitUntilTransitionsEnd(rotationStates);
10201080 }
10211081
@@ -1239,7 +1299,6 @@ Rectangle {
12391299 var childs = new Array(0);
12401300 childs.push(obj)
12411301 while (childs.length > 0) {
1242− console.log("Checking " + childs[0].objectName);
12431302 if (childs[0].objectName === "surfaceItem"
12441303 && childs[0].surface !== undefined
12451304 && childs[0].surface === surface) {
@@ -1252,5 +1311,51 @@ Rectangle {
12521311 }
12531312 return null;
12541313 }
1314+
1315+ function swipeToCloseCurrentAppInSpread() {
1316+ var spreadView = findChild(shell, "spreadView");
1317+ verify(spreadView);
1318+
1319+ var delegateToClose = findChild(spreadView, "appDelegate0");
1320+ verify(delegateToClose);
1321+
1322+ var appIdToClose = ApplicationManager.get(0).appId;;
1323+ var appCountBefore = ApplicationManager.count;
1324+
1325+ // ensure the current app is widely visible by swiping to the right,
1326+ // which will move the app windows accordingly
1327+ touchFlick(shell,
1328+ shell.width * 0.25, shell.width / 2,
1329+ shell.width, shell.width / 2);
1330+
1331+ tryCompare(spreadView, "flicking", false);
1332+ tryCompare(spreadView, "moving", false);
1333+
1334+ // Swipe up close to its left edge, as it is the only area of it guaranteed to be exposed
1335+ // in the spread. Eg: its center could be covered by some other delegate.
1336+ touchFlick(delegateToClose,
1337+ 1, delegateToClose.height / 2,
1338+ 1, - delegateToClose.height / 4);
1339+
1340+ // ensure it got closed
1341+ tryCompare(ApplicationManager, "count", appCountBefore - 1);
1342+ compare(ApplicationManager.findApplication(appIdToClose), null);
1343+ }
1344+
1345+ function isAppSurfaceFocused(appId) {
1346+ var appWindow = findChild(shell, "appWindow_" + appId);
1347+ verify(appWindow);
1348+
1349+ var app = ApplicationManager.findApplication(appId);
1350+ verify(app);
1351+
1352+ var surface = app.session.surface;
1353+ verify(surface);
1354+
1355+ var surfaceItem = findSurfaceItem(appWindow, surface);
1356+ verify(surfaceItem);
1357+
1358+ return surfaceItem.activeFocus;
1359+ }
12551360 }
12561361}