on xenial help sign in
Support shell rotation

Applications also rotate themselves, so we counter-rotate them to undo the shell rotation. Otherwise their UIs would be rotated twice

commit784c062158e79ed45bc07d2aeaaf03234c011c0a authorDaniel d'Andrada <daniel.dandrada@canonical.com> dateMon 19 May 2014, 10:11 (12 years ago) parent171d0dc
7 files changed+175−11
debian/unity8.install+1 qml/Greeter/Greeter.qml+14 qml/OrientedShell.qml+84 qml/Shell.qml+11−7 qml/Stages/PhoneStage.qml+9 qml/Stages/SpreadDelegate.qml+55−3 src/main.cpp+1−1
debian/unity8.install+1
@@ -6,4 +6,5 @@ usr/share/unity8/Hud
66usr/share/unity8/Launcher
77usr/share/unity8/Panel
88usr/share/unity8/Shell.qml
9+usr/share/unity8/OrientedShell.qml
910usr/share/unity8/Stages
qml/Greeter/Greeter.qml+14
@@ -30,6 +30,20 @@ Showable {
3030 // 1 when fully shown and 0 when fully hidden
3131 property real showProgress: MathUtils.clamp((width - Math.abs(x)) / width, 0, 1)
3232
33+ // Adjust the "hidden" position of the greeter when its size changes,
34+ // otherwise parts of it might show up on the screen.
35+ // Also, showProgress property will show up a greater than 0 value in such case, and
36+ // that must not happen
37+ onWidthChanged: {
38+ if (!shown) {
39+ if (x > 0) {
40+ x = width;
41+ } else {
42+ x = -width;
43+ }
44+ }
45+ }
46+
3347 showAnimation: StandardAnimation { property: "x"; to: 0 }
3448 hideAnimation: __leftHideAnimation
3549
qml/OrientedShell.qmlnew file+84
@@ -0,0 +1,84 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
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
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+import QtQuick.Window 2.0
19+import Ubuntu.Components 0.1
20+
21+Item {
22+ id: orientedShell
23+
24+ // this is only here to select the width / height of the window if not running fullscreen
25+ property bool tablet: false
26+ width: tablet ? units.gu(160) : applicationArguments.hasGeometry() ? applicationArguments.width() : units.gu(40)
27+ height: tablet ? units.gu(100) : applicationArguments.hasGeometry() ? applicationArguments.height() : units.gu(71)
28+
29+ property int orientationAngle: Screen.angleBetween(Screen.primaryOrientation, Screen.orientation)
30+
31+ state: orientationAngle.toString()
32+ states: [
33+ State {
34+ name: "0"
35+ PropertyChanges {
36+ target: shell
37+ rotation: 0
38+ x: 0
39+ y: 0
40+ width: orientedShell.width
41+ height: orientedShell.height
42+ }
43+ },
44+ State {
45+ name: "180"
46+ PropertyChanges {
47+ target: shell
48+ rotation: 180
49+ x: orientedShell.width
50+ y: orientedShell.height
51+ width: orientedShell.width
52+ height: orientedShell.height
53+ }
54+ },
55+ State {
56+ name: "270"
57+ PropertyChanges {
58+ target: shell
59+ rotation: 270
60+ x: 0
61+ y: orientedShell.height
62+ width: orientedShell.height
63+ height: orientedShell.width
64+ }
65+ },
66+ State {
67+ name: "90"
68+ PropertyChanges {
69+ target: shell
70+ rotation: 90
71+ x: orientedShell.width
72+ y: 0
73+ width: orientedShell.height
74+ height: orientedShell.width
75+ }
76+ }
77+ ]
78+
79+ Shell {
80+ id: shell
81+ transformOrigin: Item.TopLeft
82+ orientationAngle: orientedShell.orientationAngle
83+ }
84+}
qml/Shell.qml+11−7
@@ -36,11 +36,7 @@ import Unity.Notifications 1.0 as NotificationBackend
3636FocusScope {
3737 id: shell
3838
39− // this is only here to select the width / height of the window if not running fullscreen
40− property bool tablet: false
41− width: tablet ? units.gu(160) : applicationArguments.hasGeometry() ? applicationArguments.width() : units.gu(40)
42− height: tablet ? units.gu(100) : applicationArguments.hasGeometry() ? applicationArguments.height() : units.gu(71)
43−
39+ property int orientationAngle
4440 property real edgeSize: units.gu(2)
4541 property url defaultBackground: Qt.resolvedUrl(shell.width >= units.gu(60) ? "graphics/tablet_background.jpg" : "graphics/phone_background.jpg")
4642 property url background
@@ -181,11 +177,14 @@ FocusScope {
181177 color: "khaki"
182178
183179 x: shown ? launcher.progress : stagesDragArea.progress
184− Behavior on x { SmoothedAnimation { velocity: 600; duration: UbuntuAnimation.FastDuration } }
180+ //Behavior on x { SmoothedAnimation { velocity: 600; duration: UbuntuAnimation.FastDuration } }
185181
186182 property bool shown: false
187183
188− property real showProgress: MathUtils.clamp(1 - x / shell.width, 0, 1)
184+ // Avoid a silent "divide by zero -> NaN" situation during init as shell.width will be
185+ // zero. That breaks the property binding and the function won't be reevaluated once
186+ // shell.width is set, with the NaN result staying there for good.
187+ property real showProgress: shell.width ? MathUtils.clamp(1 - x / shell.width, 0, 1) : 0
189188
190189 property bool fullyShown: x == 0
191190 property bool fullyHidden: x == width
@@ -217,6 +216,11 @@ FocusScope {
217216 property: "dragAreaWidth"
218217 value: shell.edgeSize
219218 }
219+ Binding {
220+ target: applicationsDisplayLoader.item
221+ property: "orientationAngleOfSurfaces"
222+ value: shell.orientationAngle
223+ }
220224 }
221225 }
222226
qml/Stages/PhoneStage.qml+9
@@ -25,6 +25,8 @@ Rectangle {
2525 id: root
2626 color: "green"
2727
28+ property int orientationAngleOfSurfaces
29+
2830 // Controls to be set from outside
2931 property int dragAreaWidth
3032
@@ -39,6 +41,12 @@ Rectangle {
3941 spreadView.snapTo(priv.indexOf(appId))
4042 }
4143
44+ onWidthChanged: {
45+ spreadView.selectedIndex = -1;
46+ spreadView.phase = 0;
47+ spreadView.contentX = -spreadView.shift;
48+ }
49+
4250 Connections {
4351 target: ApplicationManager
4452
@@ -232,6 +240,7 @@ Rectangle {
232240 delegate: TransformedSpreadDelegate {
233241 id: appDelegate
234242 objectName: "appDelegate" + index
243+ orientationAngle: root.orientationAngleOfSurfaces
235244 startAngle: 45
236245 endAngle: 5
237246 startScale: 1.1
qml/Stages/SpreadDelegate.qml+55−3
@@ -24,21 +24,73 @@ Item {
2424 signal clicked()
2525 property real topMarginProgress
2626 property bool interactive: true
27+ property int orientationAngle
2728
2829 // FIXME: This really should be invisible to QML code.
2930 // e.g. Create a SurfaceItem {} in C++ which we just use without any imperative hacks.
3031 property var surface
3132 onSurfaceChanged: {
3233 if (surface) {
33− root.width = surface.implicitWidth;
34− root.height = surface.implicitHeight;
3534 surface.parent = root;
36− surface.anchors.fill = root;
3735 surface.enabled = root.interactive;
3836 surface.z = 1;
37+
38+ // for the counter-rotation
39+ surface.transformOrigin = Item.TopLeft;
3940 }
4041 }
4142
43+ // Applications already rotate automatically. And so does the shell
44+ // Therefore we have to counter-rotate the app item to undo the rotation applied to
45+ // it by the shell
46+ state: orientationAngle.toString()
47+ states: [
48+ State {
49+ name: "0"
50+ PropertyChanges {
51+ target: surface
52+ rotation: 0
53+ x: 0
54+ y: 0
55+ width: root.width
56+ height: root.height
57+ }
58+ },
59+ State {
60+ name: "90"
61+ PropertyChanges {
62+ target: surface
63+ rotation: -90
64+ x: 0
65+ y: root.height
66+ width: root.height
67+ height: root.width
68+ }
69+ },
70+ State {
71+ name: "180"
72+ PropertyChanges {
73+ target: surface
74+ rotation: -180
75+ x: root.width
76+ y: root.height
77+ width: root.width
78+ height: root.height
79+ }
80+ },
81+ State {
82+ name: "270"
83+ PropertyChanges {
84+ target: surface
85+ rotation: -270
86+ x: root.width
87+ y: 0
88+ width: root.height
89+ height: root.width
90+ }
91+ }
92+ ]
93+
4294 Component.onDestruction: {
4395 if (surface) {
4496 surface.release();
src/main.cpp+1−1
@@ -135,7 +135,7 @@ Load the testability driver");
135135 nativeInterface->setProperty("ubuntuSessionType", 1);
136136 view->setProperty("role", 2); // INDICATOR_ACTOR_ROLE
137137
138− QUrl source(::qmlDirectory()+"Shell.qml");
138+ QUrl source(::qmlDirectory()+"OrientedShell.qml");
139139 prependImportPaths(view->engine(), ::overrideImportPaths());
140140 if (!isMirServer) {
141141 prependImportPaths(view->engine(), ::nonMirImportPaths());