on xenial help sign in
merge with shellRotation
commite01fa7841f380dac1b8665fee9ad7d8781ae8eb1 authorMichael Zanetti <michael.zanetti@canonical.com> dateMon 18 May 2015, 17:21 (11 years ago) parent9f59192015ddf9
13 files changed+152−51
debian/control−4 qml/Dash/DashApplication.qml+3−3 qml/OrientedShell.qml+3 qml/Rotation/RotationStates.qml+7 qml/Shell.qml+2 qml/Stages/SpreadDelegate.qml+15−7 qml/Stages/TabletStage.qml+1 qml/Stages/TransformedSpreadDelegate.qml+2−16 src/ApplicationArguments.h−9 src/Dash/main.cpp+12−6 src/main.cpp+6−1 tests/qmltests/tst_OrientedShell.qml+59−5 tests/utils/modules/Unity/Test/UnityTestCase.qml+42
debian/control−4
@@ -169,12 +169,8 @@ Pre-Depends: ${misc:Pre-Depends},
169169Depends: ${misc:Depends},
170170 ${shlibs:Depends},
171171Provides: unity-application-impl,
172−<<<<<<< TREE
173172 unity-application-impl-6,
174−=======
175− unity-application-impl-4,
176173Replaces: unity8-autopilot (<< 8.02+15.04.20150422-0ubuntu1)
177−>>>>>>> MERGE-SOURCE
178174Description: Fake environment for running Unity 8 shell
179175 Provides fake implementations of some QML modules used by Unity 8 shell
180176 (e.g Ubuntu.Application) so that you can run it in a sandboxed environment.
qml/Dash/DashApplication.qml+3−3
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2014 Canonical, Ltd.
2+ * Copyright (C) 2014,2015 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
@@ -19,8 +19,8 @@ import Ubuntu.Components 1.0
1919import Ubuntu.Thumbnailer 0.1 // Register support for image://thumbnailer/ and image://albumart/
2020
2121MainView {
22− width: applicationArguments.hasGeometry() ? applicationArguments.width() : units.gu(40)
23− height: applicationArguments.hasGeometry() ? applicationArguments.height() : units.gu(68)
22+ implicitWidth: units.gu(40)
23+ implicitHeight: units.gu(68)
2424
2525 useDeprecatedToolbar: false
2626
qml/OrientedShell.qml+3
@@ -25,6 +25,9 @@ Rectangle {
2525 id: root
2626 color: "black"
2727
28+ implicitWidth: units.gu(40)
29+ implicitHeight: units.gu(71)
30+
2831 // NB: native and primary orientations here don't map exactly to their QScreen counterparts
2932 readonly property int nativeOrientation: width > height ? Qt.LandscapeOrientation : Qt.PortraitOrientation
3033
qml/Rotation/RotationStates.qml+7
@@ -16,6 +16,7 @@
1616
1717import QtQuick 2.0
1818import Ubuntu.Components 1.1
19+import Powerd 0.1
1920
2021// Why the state machine is done that way:
2122// We cannot use regular PropertyChanges{} inside the State elements as steps in the
@@ -121,6 +122,12 @@ StateGroup {
121122 // During start up, inital property values are still settling while we're still
122123 // to render the very first frame
123124 d.animationType = d.noAnimation;
125+ } else if (Powerd.status === Powerd.Off) {
126+ // There's no point in animating if the user can't see it (display is off).
127+ d.animationType = d.noAnimation;
128+ } else if (root.shell.showingGreeter) {
129+ // A rotating greeter looks weird.
130+ d.animationType = d.noAnimation;
124131 } else {
125132 if (!root.shell.mainApp) {
126133 // shouldn't happen but, anyway
qml/Shell.qml+2
@@ -70,6 +70,8 @@ Item {
7070 && (applicationsDisplayLoader.item && applicationsDisplayLoader.item.orientationChangesEnabled)
7171 && !greeter.animating
7272
73+ readonly property bool showingGreeter: greeter.shown
74+
7375 property bool startingUp: true
7476 Timer { id: finishStartUpTimer; interval: 500; onTriggered: startingUp = false }
7577
qml/Stages/SpreadDelegate.qml+15−7
@@ -131,6 +131,14 @@ FocusScope {
131131 }
132132 }
133133
134+ // Ensures the given angle is in the form (0,90,180,270)
135+ function normalizeAngle(angle) {
136+ while (angle < 0) {
137+ angle += 360;
138+ }
139+ return angle % 360;
140+ }
141+
134142 states: [
135143 // Sets the initial orientationAngle of the window, when it first slides into view
136144 // (with the splash screen likely being displayed). At that point we just try to
@@ -172,16 +180,16 @@ FocusScope {
172180 return Screen.angleBetween(root.nativeOrientation, chosenOrientation);
173181 }
174182
175− rotation: appWindowWithShadow.orientationAngle - root.shellOrientationAngle
183+ rotation: normalizeAngle(appWindowWithShadow.orientationAngle - root.shellOrientationAngle)
176184 width: {
177− if (rotation == 0 || Math.abs(rotation) == 180) {
185+ if (rotation == 0 || rotation == 180) {
178186 return root.width;
179187 } else {
180188 return root.height;
181189 }
182190 }
183191 height: {
184− if (rotation == 0 || Math.abs(rotation) == 180)
192+ if (rotation == 0 || rotation == 180)
185193 return root.height;
186194 else
187195 return root.width;
@@ -201,16 +209,16 @@ FocusScope {
201209 PropertyChanges {
202210 target: appWindowWithShadow
203211 restoreEntryValues: false
204− rotation: appWindowWithShadow.orientationAngle - root.shellOrientationAngle
212+ rotation: normalizeAngle(appWindowWithShadow.orientationAngle - root.shellOrientationAngle)
205213 width: {
206− if (rotation == 0 || Math.abs(rotation) == 180) {
214+ if (rotation == 0 || rotation == 180) {
207215 return root.width;
208216 } else {
209217 return root.height;
210218 }
211219 }
212220 height: {
213− if (rotation == 0 || Math.abs(rotation) == 180)
221+ if (rotation == 0 || rotation == 180)
214222 return root.height;
215223 else
216224 return root.width;
@@ -229,7 +237,7 @@ FocusScope {
229237 target: appWindowWithShadow
230238 width: root.shellOrientationAngle == 0 || root.shellOrientationAngle == 180 ? root.width : root.height
231239 height: root.shellOrientationAngle == 0 || root.shellOrientationAngle == 180 ? root.height : root.width
232− rotation: -root.shellOrientationAngle
240+ rotation: normalizeAngle(-root.shellOrientationAngle)
233241 }
234242 PropertyChanges {
235243 target: appWindow
qml/Stages/TabletStage.qml+1
@@ -728,6 +728,7 @@ Rectangle {
728728
729729 DirectionalDragArea {
730730 id: spreadDragArea
731+ objectName: "spreadDragArea"
731732 anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
732733 width: root.dragAreaWidth
733734 direction: Direction.Leftwards
qml/Stages/TransformedSpreadDelegate.qml+2−16
@@ -312,27 +312,13 @@ SpreadDelegate {
312312 // non-fullscreen window when they're stacked on top of each other on the
313313 // far left of the spread.
314314 Translate {
315− y: !fullscreen && Math.abs(appWindowRotation) === 180
315+ y: !fullscreen && appWindowRotation === 180
316316 ? priv.topMarginProgress * maximizedAppTopMargin
317317 : 0
318318 },
319319 Scale {
320320 origin {
321− x: {
322− switch (appWindowRotation) {
323− case 0:
324− return 0;
325− break;
326− case 90:
327− return 0;
328− break;
329− case 270:
330− return spreadView.width;
331− break;
332− default: // 180
333− return 0;
334− }
335− }
321+ x: appWindowRotation === 270 ? spreadView.width : 0
336322 y: spreadView.height
337323 }
338324
src/ApplicationArguments.h−9
@@ -31,18 +31,9 @@ public:
3131 ApplicationArguments(QObject *parent = nullptr);
3232
3333 void setDeviceName(QString deviceName) { m_deviceName = deviceName; }
34−
35− void setSize(const QSize &size) {
36− m_size = size;
37− }
38−
39− Q_INVOKABLE int width() const { return m_size.width(); }
40− Q_INVOKABLE int height() const { return m_size.height(); }
41−
4234 QString deviceName() const { return m_deviceName; }
4335
4436private:
45− QSize m_size;
4637 QString m_deviceName;
4738};
4839
src/Dash/main.cpp+12−6
@@ -61,12 +61,6 @@ int main(int argc, const char *argv[])
6161 parser.process(*application);
6262
6363 ApplicationArguments qmlArgs;
64− if (parser.isSet(windowGeometryOption) &&
65− parser.value(windowGeometryOption).split('x').size() == 2)
66− {
67− QStringList geom = parser.value(windowGeometryOption).split('x');
68− qmlArgs.setSize(QSize(geom.at(0).toInt(), geom.at(1).toInt()));
69− }
7064
7165 if (getenv("QT_LOAD_TESTABILITY")) {
7266 QLibrary testLib(QLatin1String("qttestability"));
@@ -88,6 +82,18 @@ int main(int argc, const char *argv[])
8882
8983 QQuickView* view = new QQuickView();
9084 view->setResizeMode(QQuickView::SizeRootObjectToView);
85+
86+ if (parser.isSet(windowGeometryOption) &&
87+ parser.value(windowGeometryOption).split('x').size() == 2)
88+ {
89+ QStringList geom = parser.value(windowGeometryOption).split('x');
90+ QSize windowSize(geom.at(0).toInt(), geom.at(1).toInt());
91+ if (windowSize.isValid()) {
92+ view->setWidth(windowSize.width());
93+ view->setHeight(windowSize.height());
94+ }
95+ }
96+
9197 view->setTitle("Scopes");
9298 view->rootContext()->setContextProperty("applicationArguments", &qmlArgs);
9399
src/main.cpp+6−1
@@ -54,7 +54,6 @@ int main(int argc, const char *argv[])
5454 UnityCommandLineParser parser(*application);
5555
5656 ApplicationArguments qmlArgs;
57− qmlArgs.setSize(parser.windowGeometry());
5857
5958 if (!parser.deviceName().isEmpty()) {
6059 qmlArgs.setDeviceName(parser.deviceName());
@@ -88,6 +87,12 @@ int main(int argc, const char *argv[])
8887 view->setResizeMode(QQuickView::SizeRootObjectToView);
8988 view->setColor("black");
9089 view->setTitle("Unity8 Shell");
90+
91+ if (parser.windowGeometry().isValid()) {
92+ view->setWidth(parser.windowGeometry().width());
93+ view->setHeight(parser.windowGeometry().height());
94+ }
95+
9196 view->engine()->setBaseUrl(QUrl::fromLocalFile(::qmlDirectory()));
9297 view->rootContext()->setContextProperty("applicationArguments", &qmlArgs);
9398 view->rootContext()->setContextProperty("shellMode", parser.mode());
tests/qmltests/tst_OrientedShell.qml+59−5
@@ -22,6 +22,7 @@ import Ubuntu.Components.ListItems 1.0 as ListItem
2222import Unity.Application 0.1
2323import Unity.Test 0.1
2424import LightDM 0.1 as LightDM
25+import Powerd 0.1
2526
2627import "../../qml"
2728
@@ -161,8 +162,16 @@ Rectangle {
161162 }
162163
163164 Rectangle {
164− id: controls
165+ width: controls.width
166+ anchors {
167+ top: parent.top
168+ bottom: parent.bottom
169+ right: parent.right
170+ }
165171 color: "darkgrey"
172+ }
173+ Flickable {
174+ id: controls
166175 width: units.gu(30)
167176 anchors {
168177 top: parent.top
@@ -170,7 +179,11 @@ Rectangle {
170179 right: parent.right
171180 }
172181
182+ boundsBehavior: Flickable.StopAtBounds
183+ contentHeight: controlsColumn.height
184+
173185 Column {
186+ id: controlsColumn
174187 anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
175188 spacing: units.gu(1)
176189 Button {
@@ -281,6 +294,17 @@ Rectangle {
281294 anchors.verticalCenter: parent.verticalCenter
282295 }
283296 }
297+ Button {
298+ text: Powerd.status === Powerd.On ? "Display ON" : "Display OFF"
299+ activeFocusOnPress: false
300+ onClicked: {
301+ if (Powerd.status === Powerd.On) {
302+ Powerd.status = Powerd.Off;
303+ } else {
304+ Powerd.status = Powerd.On;
305+ }
306+ }
307+ }
284308 }
285309 }
286310
@@ -947,16 +971,31 @@ Rectangle {
947971 // If we swipe too much we will trigger the spread mode
948972 // and we don't want that.
949973 var spreadView = findChild(shell, "spreadView");
950− var swipeLength = (spreadView.positionMarker1 * spreadView.width) * 0.5;
974+ verify(spreadView);
951975
952976 verify(ApplicationManager.count >= 2);
953977 var previousApp = ApplicationManager.get(1);
954978
955979 var touchStartX = shell.width - 1;
956980 var touchStartY = shell.height / 2;
957− touchFlick(shell,
958− touchStartX, touchStartY,
959− touchStartX - swipeLength, touchStartY);
981+
982+ var condition;
983+ if (applicationArguments.deviceName === "phone") {
984+ condition = function() {
985+ return spreadView.shiftedContentX > units.gu(2) &&
986+ spreadView.shiftedContentX < spreadView.positionMarker1 * spreadView.width;
987+ };
988+ } else {
989+ condition = function() {
990+ return spreadView.shiftedContentX > spreadView.width * spreadView.positionMarker1
991+ && spreadView.shiftedContentX < spreadView.width * spreadView.positionMarker2;
992+ };
993+ }
994+
995+ touchDragUntil(shell,
996+ touchStartX, touchStartY,
997+ -units.gu(1), 0,
998+ condition);
960999
9611000 // ensure the app switch animation has ended
9621001 tryCompare(spreadView, "shiftedContentX", 0);
@@ -1039,6 +1078,8 @@ Rectangle {
10391078
10401079 waitUntilShellIsInOrientation(root.physicalOrientation0);
10411080
1081+ waitForGreeterToStabilize();
1082+
10421083 swipeAwayGreeter();
10431084
10441085 var spreadRepeater = findChild(shell, "spreadRepeater");
@@ -1047,6 +1088,19 @@ Rectangle {
10471088 }
10481089 }
10491090
1091+ function waitForGreeterToStabilize() {
1092+ var greeter = findChild(shell, "greeter");
1093+ verify(greeter);
1094+
1095+ var loginList = findChild(greeter, "loginList");
1096+ // Only present in WideView
1097+ if (loginList) {
1098+ var userList = findChild(loginList, "userList");
1099+ verify(userList);
1100+ tryCompare(userList, "movingInternally", false);
1101+ }
1102+ }
1103+
10501104 // expectedAngle is in orientedShell's coordinate system
10511105 function checkAppSurfaceOrientation(app, expectedAngle) {
10521106 var surface = app.session.surface;
tests/utils/modules/Unity/Test/UnityTestCase.qml+42
@@ -308,6 +308,48 @@ TestCase {
308308 }
309309 }
310310
311+ // perform a drag in the given direction until the given condition is true
312+ // The condition is a function to be evaluated after every step
313+ function touchDragUntil(item, startX, startY, stepX, stepY, condition) {
314+
315+ var root = fetchRootItem(item);
316+ var pos = item.mapToItem(root, startX, startY);
317+
318+ // convert step to scene coords
319+ {
320+ var stepStart = item.mapToItem(root, 0, 0);
321+ var stepEnd = item.mapToItem(root, stepX, stepY);
322+ }
323+ stepX = stepEnd.x - stepStart.x;
324+ stepY = stepEnd.y - stepStart.y;
325+
326+ var event = touchEvent(item)
327+ event.press(0 /* touchId */, pos.x, pos.y)
328+ event.commit()
329+
330+ // we have to stop at some point
331+ var maxSteps = 100;
332+ var stepsDone = 0;
333+
334+ while (!condition() && stepsDone < maxSteps) {
335+ wait(25);
336+ fakeDateTime.currentTimeMs += 25;
337+
338+ pos.x += stepX;
339+ pos.y += stepY;
340+
341+ event = touchEvent(item);
342+ event.move(0 /* touchId */, pos.x, pos.y);
343+ event.commit();
344+
345+ stepsDone += 1;
346+ }
347+
348+ event = touchEvent(item)
349+ event.release(0 /* touchId */, pos.x, pos.y)
350+ event.commit()
351+ }
352+
311353 function touchPinch(item, x1Start, y1Start, x1End, y1End, x2Start, y2Start, x2End, y2End) {
312354 // Make sure the item is rendered
313355 waitForRendering(item);