on xenial help sign in
Fix splashscreen orientation when app rotates own contents
commit2111ffdc41e80ec6447ec58b3d069174ce92960a authorDaniel d'Andrada <daniel.dandrada@canonical.com> dateWed 22 Jun 2016, 10:53 (10 years ago) parent3de69ce
5 files changed+78−91
qml/Stages/ApplicationWindow.qml+6 qml/Stages/SpreadDelegate.qml+63−87 tests/mocks/Unity/Application/MirSurfaceItem.cpp+1 tests/mocks/Unity/Application/MirSurfaceItem.h+1−1 tests/qmltests/Stages/tst_SpreadDelegate.qml+7−3
qml/Stages/ApplicationWindow.qml+6
@@ -46,6 +46,7 @@ FocusScope {
4646 property alias resizeSurface: surfaceContainer.resizeSurface
4747 property int requestedWidth: -1
4848 property int requestedHeight: -1
49+ property real splashRotation: 0
4950
5051 readonly property int minimumWidth: surface ? surface.minimumWidth : 0
5152 readonly property int minimumHeight: surface ? surface.minimumHeight : 0
@@ -184,6 +185,11 @@ FocusScope {
184185 backgroundColor: d.splashColor
185186 headerColor: d.splashColorHeader
186187 footerColor: d.splashColorFooter
188+
189+ rotation: root.splashRotation
190+ anchors.centerIn: parent
191+ width: rotation == 0 || rotation == 180 ? root.width : root.height
192+ height: rotation == 0 || rotation == 180 ? root.height : root.width
187193 }
188194 }
189195 }
qml/Stages/SpreadDelegate.qml+63−87
@@ -82,12 +82,69 @@ FocusScope {
8282
8383 QtObject {
8484 id: priv
85+ objectName: "spreadDelegatePriv"
8586 property bool startingUp: true
8687 }
8788
8889 Component.onCompleted: { finishStartUpTimer.start(); }
8990 Timer { id: finishStartUpTimer; interval: 400; onTriggered: priv.startingUp = false }
9091
92+ // JS version of QPlatformScreen::angleBetween C++ implementation.
93+ // So don't ask me how it works because I don't know.
94+ // Calling Screen.angleBetween from within a Binding component doesn't work for some reason.
95+ function angleBetween(a, b) {
96+ if (a == b)
97+ return 0;
98+
99+ var ia = Math.log(a) / Math.LN2;
100+ var ib = Math.log(b) / Math.LN2;
101+
102+ var delta = ia - ib;
103+
104+ if (delta < 0)
105+ delta = delta + 4;
106+
107+ var angles = [ 0, 90, 180, 270 ];
108+ return angles[delta];
109+ }
110+
111+ // Sets the initial orientationAngle of the window, when it first slides into view
112+ // (with the splash screen likely being displayed). At that point we just try to
113+ // match shell's current orientation. We need a bit of time in this state as the
114+ // information we need to decide orientationAngle may take a few cycles to
115+ // be set.
116+ Binding {
117+ target: appWindowWithShadow
118+ property: "orientationAngle"
119+ when: priv.startingUp
120+ value: {
121+ var supportedOrientations = root.supportedOrientations;
122+
123+ if (supportedOrientations === Qt.PrimaryOrientation) {
124+ supportedOrientations = root.orientations.primary;
125+ }
126+
127+ // If it doesn't support shell's current orientation
128+ // then simply pick some arbitraty one that it does support
129+ var chosenOrientation = 0;
130+ if (supportedOrientations & root.shellOrientation) {
131+ chosenOrientation = root.shellOrientation;
132+ } else if (supportedOrientations & Qt.PortraitOrientation) {
133+ chosenOrientation = root.orientations.portrait;
134+ } else if (supportedOrientations & Qt.LandscapeOrientation) {
135+ chosenOrientation = root.orientations.landscape;
136+ } else if (supportedOrientations & Qt.InvertedPortraitOrientation) {
137+ chosenOrientation = root.orientations.invertedPortrait;
138+ } else if (supportedOrientations & Qt.InvertedLandscapeOrientation) {
139+ chosenOrientation = root.orientations.invertedLandscape;
140+ } else {
141+ chosenOrientation = root.orientations.primary;
142+ }
143+
144+ return angleBetween(root.orientations.native_, chosenOrientation);
145+ }
146+ }
147+
91148 Rectangle {
92149 id: background
93150 color: "black"
@@ -129,9 +186,7 @@ FocusScope {
129186 }
130187
131188 state: {
132− if (priv.startingUp) {
133− return "startingUp";
134− } else if (root.application && root.application.rotatesWindowContents) {
189+ if (root.application && root.application.rotatesWindowContents) {
135190 return "counterRotate";
136191 } else if (orientationChangeAnimation.running) {
137192 return "animatingRotation";
@@ -149,109 +204,29 @@ FocusScope {
149204 }
150205
151206 states: [
152− // Sets the initial orientationAngle of the window, when it first slides into view
153− // (with the splash screen likely being displayed). At that point we just try to
154− // match shell's current orientation. We need a bit of time in this state as the
155− // information we need to decide orientationAngle may take a few cycles to
156− // be set.
157− State {
158− name: "startingUp"
159− PropertyChanges {
160− target: appWindowWithShadow
161− restoreEntryValues: false
162− orientationAngle: {
163− if (!root.application || root.application.rotatesWindowContents) {
164− return 0;
165− }
166−
167− var supportedOrientations = root.supportedOrientations;
168−
169− if (supportedOrientations === Qt.PrimaryOrientation) {
170− supportedOrientations = root.orientations.primary;
171− }
172−
173− // If it doesn't support shell's current orientation
174− // then simply pick some arbitraty one that it does support
175− var chosenOrientation = 0;
176− if (supportedOrientations & root.shellOrientation) {
177− chosenOrientation = root.shellOrientation;
178− } else if (supportedOrientations & Qt.PortraitOrientation) {
179− chosenOrientation = root.orientations.portrait;
180− } else if (supportedOrientations & Qt.LandscapeOrientation) {
181− chosenOrientation = root.orientations.landscape;
182− } else if (supportedOrientations & Qt.InvertedPortraitOrientation) {
183− chosenOrientation = root.orientations.invertedPortrait;
184− } else if (supportedOrientations & Qt.InvertedLandscapeOrientation) {
185− chosenOrientation = root.orientations.invertedLandscape;
186− } else {
187− chosenOrientation = root.orientations.primary;
188− }
189−
190− return Screen.angleBetween(root.orientations.native_, chosenOrientation);
191− }
192−
193− rotation: normalizeAngle(appWindowWithShadow.orientationAngle - root.shellOrientationAngle)
194− width: {
195− if (rotation == 0 || rotation == 180) {
196− return root.width;
197− } else {
198− return root.height;
199− }
200− }
201− height: {
202− if (rotation == 0 || rotation == 180)
203− return root.height;
204− else
205− return root.width;
206− }
207− }
208− },
209207 // In this state we stick to our currently set orientationAngle, which may change only due
210208 // to calls made to matchShellOrientation() or animateToShellOrientation()
211209 State {
212− id: keepSceneRotationState
213210 name: "keepSceneRotation"
214−
215− StateChangeScript { script: {
216− // break binding
217− appWindowWithShadow.orientationAngle = appWindowWithShadow.orientationAngle;
218− } }
219211 PropertyChanges {
220212 target: appWindowWithShadow
221213 restoreEntryValues: false
222214 rotation: normalizeAngle(appWindowWithShadow.orientationAngle - root.shellOrientationAngle)
223− width: {
224− if (rotation == 0 || rotation == 180) {
225− return root.width;
226− } else {
227− return root.height;
228− }
229− }
230− height: {
231− if (rotation == 0 || rotation == 180)
232− return root.height;
233− else
234− return root.width;
235− }
236215 }
237216 },
238217 // In this state we counteract any shell rotation so that the window, in scene coordinates,
239218 // remains unrotated.
219+ // But the splash screen should still obey the set orientationAngle set by shell
240220 State {
241221 name: "counterRotate"
242− StateChangeScript { script: {
243− // break binding
244− appWindowWithShadow.orientationAngle = appWindowWithShadow.orientationAngle;
245− } }
246222 PropertyChanges {
247223 target: appWindowWithShadow
248− width: root.shellOrientationAngle == 0 || root.shellOrientationAngle == 180 ? root.width : root.height
249− height: root.shellOrientationAngle == 0 || root.shellOrientationAngle == 180 ? root.height : root.width
250224 rotation: normalizeAngle(-root.shellOrientationAngle)
251225 }
252226 PropertyChanges {
253227 target: appWindow
254228 surfaceOrientationAngle: appWindowWithShadow.orientationAngle
229+ splashRotation: appWindowWithShadow.orientationAngle
255230 }
256231 },
257232 State {
@@ -259,8 +234,9 @@ FocusScope {
259234 }
260235 ]
261236
262− x: (parent.width - width) / 2
263− y: (parent.height - height) / 2
237+ anchors.centerIn: parent
238+ width: rotation == 0 || rotation == 180 ? root.width : root.height
239+ height: rotation == 0 || rotation == 180 ? root.height : root.width
264240
265241 BorderImage {
266242 anchors {
tests/mocks/Unity/Application/MirSurfaceItem.cpp+1
@@ -43,6 +43,7 @@ MirSurfaceItem::MirSurfaceItem(QQuickItem *parent)
4343 , m_qmlContentComponent(nullptr)
4444 , m_qmlItem(nullptr)
4545 , m_consumesInput(false)
46+ , m_orientationAngle(nullptr)
4647 , m_surfaceWidth(0)
4748 , m_surfaceHeight(0)
4849 , m_touchPressCount(0)
tests/mocks/Unity/Application/MirSurfaceItem.h+1−1
@@ -117,7 +117,7 @@ private:
117117
118118 bool m_consumesInput;
119119
120− Mir::OrientationAngle *m_orientationAngle{nullptr};
120+ Mir::OrientationAngle *m_orientationAngle;
121121
122122 int m_surfaceWidth;
123123 int m_surfaceHeight;
tests/qmltests/Stages/tst_SpreadDelegate.qml+7−3
@@ -278,12 +278,16 @@ Rectangle {
278278 function test_keepsSceneTransformationWhenShellRotates(data) {
279279 loadWithGalleryApp.clicked();
280280
281+ {
282+ var priv = findInvisibleChild(spreadDelegate, "spreadDelegatePriv");
283+ verify(priv);
284+ tryCompare(priv, "startingUp", false);
285+ }
286+
281287 var appWindowWithShadow = findChild(spreadDelegate, "appWindowWithShadow");
282288 verify(appWindowWithShadow);
283289
284− // Wait until it reaches the state we are interested on.
285− // It begins with "startingUp"
286− tryCompare(appWindowWithShadow, "state", "keepSceneRotation");
290+ compare(appWindowWithShadow.state, "keepSceneRotation");
287291
288292 shellOrientationAngleSelector.selectedIndex = data.selectedIndex;
289293