on xenial help sign in
Fix a variety of design nits with the current lockscreen:

* disable indicators and launcher when locked * when reversing the direction of a greeter flick, treat it as a cancel * don't animate dots when changing the infographic data source * make cancelling a login nicer: * reduce the delay before greeter starts animating * show the greeter from the same side of the screen that it hid to * don't re-animate the infographic Fixes: 1351027 Approved by: PS Jenkins bot, Albert Astals Cid

commit5e915b4c14293857e43ce334875e91088c71642a authorMichael Terry <michael.terry@canonical.com> dateMon 11 Aug 2014, 19:02 (12 years ago) parent7a8ef730b55bb9
5 files changed+76−119
qml/Greeter/Greeter.qml+9−9 qml/Greeter/Infographics.qml+46−102 qml/Shell.qml+6−3 tests/autopilot/unity8/shell/emulators/greeter.py+2−1 tests/qmltests/tst_ShellWithPin.qml+13−4
qml/Greeter/Greeter.qml+9−9
@@ -26,11 +26,12 @@ Showable {
2626 created: greeterContentLoader.status == Loader.Ready && greeterContentLoader.item.ready
2727
2828 property url defaultBackground
29+ property bool loadContent: required
2930
3031 // 1 when fully shown and 0 when fully hidden
3132 property real showProgress: MathUtils.clamp((width - Math.abs(x)) / width, 0, 1)
3233
33− showAnimation: StandardAnimation { property: "x"; to: 0 }
34+ showAnimation: StandardAnimation { property: "x"; to: 0; duration: UbuntuAnimation.FastDuration }
3435 hideAnimation: __leftHideAnimation
3536
3637 property alias dragHandleWidth: dragHandle.width
@@ -58,10 +59,8 @@ Showable {
5859
5960 onRequiredChanged: {
6061 // Reset hide animation to default once we're finished with it
61− if (!required) {
62− // Put back on left for reliable show direction and so that
63− // if normal hide() is called, we don't animate from right.
64− x = -width
62+ if (required) {
63+ // Reset hide animation so that a hide() call is reliably left
6564 hideAnimation = __leftHideAnimation
6665 }
6766 }
@@ -90,12 +89,13 @@ Showable {
9089 onPressAndHold: {} // eat event, but no need to tease, as drag will cover it
9190
9291 onDragEnd: {
93− if (rightEvaluator.shouldAutoComplete())
92+ if (greeter.x > 0 && rightEvaluator.shouldAutoComplete()) {
9493 greeter.hideRight()
95− else if (leftEvaluator.shouldAutoComplete())
94+ } else if (greeter.x < 0 && leftEvaluator.shouldAutoComplete()) {
9695 greeter.hide();
97− else
96+ } else {
9897 greeter.show(); // undo drag
98+ }
9999 }
100100
101101 onDragValueChanged: {
@@ -127,7 +127,7 @@ Showable {
127127 property var infographicModel: LightDM.Infographic
128128 readonly property int backgroundTopMargin: -greeter.y
129129
130− source: required ? "GreeterContent.qml" : ""
130+ source: loadContent ? "GreeterContent.qml" : ""
131131
132132 onLoaded: {
133133 selected(currentIndex);
qml/Greeter/Infographics.qml+46−102
@@ -26,6 +26,9 @@ Item {
2626
2727 property int animDuration: 10
2828
29+ property bool __useDotAnimation: true
30+ property int __circleModifier: __useDotAnimation ? 1 : 2
31+
2932 Connections {
3033 target: model
3134
@@ -41,19 +44,24 @@ Item {
4144
4245 function startShowAnimation() {
4346 dotHideAnimTimer.stop()
44− circleShrinkAnimTimer.stop()
4547 notification.hideAnim.stop()
4648
47− dotShowAnimTimer.startFromBeginning()
49+ if (__useDotAnimation) {
50+ dotShowAnimTimer.startFromBeginning()
51+ }
4852 notification.showAnim.start()
4953 }
5054
5155 function startHideAnimation() {
5256 dotShowAnimTimer.stop()
53− circleGrowAnimTimer.stop()
57+ circleChangeAnimTimer.stop()
5458 notification.showAnim.stop()
5559
56− dotHideAnimTimer.startFromBeginning()
60+ if (__useDotAnimation) {
61+ dotHideAnimTimer.startFromBeginning()
62+ } else {
63+ circleChangeAnimTimer.startFromBeginning()
64+ }
5765 notification.hideAnim.start()
5866 }
5967
@@ -73,22 +81,22 @@ Item {
7381 anchors.centerIn: parent
7482
7583 Timer {
76− id: circleGrowAnimTimer
84+ id: circleChangeAnimTimer
7785
7886 property int pastCircleCounter
7987 property int presentCircleCounter
8088
81− interval: animDuration
89+ interval: notification.duration
8290 running: false
8391 repeat: true
8492 onTriggered: {
8593 if (pastCircleCounter < pastCircles.count) {
8694 var nextCircle = pastCircles.itemAt(pastCircleCounter++)
87− if (nextCircle !== null) nextCircle.pastCircleGrowAnim.start()
95+ if (nextCircle !== null) nextCircle.pastCircleChangeAnim.start()
8896 }
8997 if (pastCircleCounter > pastCircles.count / 2) {
9098 var nextCircle = presentCircles.itemAt(presentCircleCounter++)
91− if (nextCircle !== null) nextCircle.presentCircleGrowAnim.start()
99+ if (nextCircle !== null) nextCircle.presentCircleChangeAnim.start()
92100 }
93101 if (presentCircleCounter > infographic.model.currentDay && pastCircleCounter >= pastCircles.count) {
94102 stop()
@@ -96,39 +104,8 @@ Item {
96104 }
97105
98106 function startFromBeginning() {
99− circleGrowAnimTimer.pastCircleCounter = 0
100− circleGrowAnimTimer.presentCircleCounter = 0
101− start()
102− }
103− }
104−
105− Timer {
106− id: circleShrinkAnimTimer
107−
108− property int pastCircleCounter
109− property int presentCircleCounter
110−
111− interval: animDuration
112− running: false
113− repeat: true
114− onTriggered: {
115− if (pastCircleCounter >= 0) {
116− var nextCircle = pastCircles.itemAt(pastCircleCounter--)
117− if (nextCircle !== null) nextCircle.pastCircleShrinkAnim.start()
118− }
119− if (pastCircleCounter < pastCircles.count / 2) {
120− var nextCircle = presentCircles.itemAt(presentCircleCounter--)
121− if (nextCircle !== null) nextCircle.presentCircleShrinkAnim.start()
122− }
123− if (presentCircleCounter < 0) {
124− stop()
125− infographic.model.readyForDataChange()
126− }
127− }
128−
129− function startFromBeginning() {
130− pastCircleCounter = pastCircles.count - 1
131− presentCircleCounter = model.currentDay
107+ circleChangeAnimTimer.pastCircleCounter = 0
108+ circleChangeAnimTimer.presentCircleCounter = 0
132109 start()
133110 }
134111 }
@@ -139,8 +116,7 @@ Item {
139116 model: infographic.model.secondMonth
140117
141118 delegate: ObjectPositioner {
142− property alias pastCircleGrowAnim: pastCircleGrowAnim
143− property alias pastCircleShrinkAnim: pastCircleShrinkAnim
119+ property alias pastCircleChangeAnim: pastCircleChangeAnim
144120
145121 index: model.index
146122 count: pastCircles.count
@@ -160,52 +136,33 @@ Item {
160136 opacity: 0.0
161137 scale: 0.0
162138 visible: modelData !== undefined
163− color: Gradient.threeColorByIndex(index, count, infographic.model.secondColor)
139+ color: "transparent"
164140
165141 SequentialAnimation {
166− id: pastCircleGrowAnim
142+ id: pastCircleChangeAnim
167143
168144 loops: 1
169145 ParallelAnimation {
170146 PropertyAnimation {
171147 target: pastCircle
172148 property: "opacity"
173− from: 0.0
174149 to: pastCircle.circleOpacity
175150 easing.type: Easing.OutCurve
176− duration: circleGrowAnimTimer.interval * 4
151+ duration: circleChangeAnimTimer.interval * __circleModifier
177152 }
178153 PropertyAnimation {
179154 target: pastCircle
180155 property: "scale"
181− from: 0.0
182156 to: modelData
183157 easing.type: Easing.OutCurve
184− duration: circleGrowAnimTimer.interval * 4
185− }
186− }
187− }
188−
189− SequentialAnimation {
190− id: pastCircleShrinkAnim
191−
192− loops: 1
193− ParallelAnimation {
194− PropertyAnimation {
195− target: pastCircle
196− property: "opacity"
197− from: pastCircle.circleOpacity
198− to: 0.0
199− easing.type: Easing.OutCurve
200− duration: circleShrinkAnimTimer.interval * 4
158+ duration: circleChangeAnimTimer.interval * __circleModifier
201159 }
202− PropertyAnimation {
160+ ColorAnimation {
203161 target: pastCircle
204− property: "scale"
205− from: modelData
206− to: 0.0
162+ property: "color"
163+ to: Gradient.threeColorByIndex(index, count, infographic.model.secondColor)
207164 easing.type: Easing.OutCurve
208− duration: circleShrinkAnimTimer.interval * 4
165+ duration: circleChangeAnimTimer.interval * __circleModifier
209166 }
210167 }
211168 }
@@ -219,8 +176,7 @@ Item {
219176 model: infographic.model.firstMonth
220177
221178 delegate: ObjectPositioner {
222− property alias presentCircleGrowAnim: presentCircleGrowAnim
223− property alias presentCircleShrinkAnim: presentCircleShrinkAnim
179+ property alias presentCircleChangeAnim: presentCircleChangeAnim
224180
225181 index: model.index
226182 count: presentCircles.count
@@ -240,10 +196,10 @@ Item {
240196 opacity: 0.0
241197 scale: 0.0
242198 visible: modelData !== undefined
243− color: Gradient.threeColorByIndex(index, infographic.model.currentDay, infographic.model.firstColor)
199+ color: "transparent"
244200
245201 SequentialAnimation {
246− id: presentCircleGrowAnim
202+ id: presentCircleChangeAnim
247203
248204 loops: 1
249205
@@ -253,36 +209,21 @@ Item {
253209 property: "opacity"
254210 to: presentCircle.circleOpacity
255211 easing.type: Easing.OutCurve
256− duration: circleGrowAnimTimer.interval * 4
212+ duration: circleChangeAnimTimer.interval * __circleModifier
257213 }
258214 PropertyAnimation {
259215 target: presentCircle
260216 property: "scale"
261217 to: modelData
262218 easing.type: Easing.OutCurve
263− duration: circleGrowAnimTimer.interval * 4
219+ duration: circleChangeAnimTimer.interval * __circleModifier
264220 }
265− }
266− }
267−
268− SequentialAnimation {
269− id: presentCircleShrinkAnim
270−
271− loops: 1
272− ParallelAnimation {
273− PropertyAnimation {
221+ ColorAnimation {
274222 target: presentCircle
275− property: "opacity"
276− to: 0.0
223+ property: "color"
224+ to: Gradient.threeColorByIndex(index, infographic.model.currentDay, infographic.model.firstColor)
277225 easing.type: Easing.OutCurve
278− duration: circleShrinkAnimTimer.interval * 4
279− }
280− PropertyAnimation {
281− target: presentCircle
282− property: "scale"
283− to: 0.0
284− easing.type: Easing.OutCurve
285− duration: circleShrinkAnimTimer.interval * 4
226+ duration: circleChangeAnimTimer.interval * __circleModifier
286227 }
287228 }
288229 }
@@ -313,7 +254,7 @@ Item {
313254 stop()
314255 }
315256 if (dotCounter == Math.round(dots.count / 2)) {
316− circleGrowAnimTimer.startFromBeginning()
257+ circleChangeAnimTimer.startFromBeginning()
317258 }
318259 }
319260
@@ -340,8 +281,8 @@ Item {
340281 } else {
341282 stop()
342283 }
343− if (dotCounter == Math.round(dots.count / 2)) {
344− circleShrinkAnimTimer.startFromBeginning()
284+ if (dotCounter == 0) {
285+ infographic.model.readyForDataChange()
345286 }
346287 }
347288
@@ -413,6 +354,7 @@ Item {
413354 property alias showAnim: increaseOpacity
414355
415356 property real baseOpacity: 0.6
357+ property real duration: dotShowAnimTimer.interval * 5
416358
417359 height: 0.7 * backgroundCircle.width
418360 width: notification.height
@@ -432,7 +374,7 @@ Item {
432374 property: "opacity"
433375 from: 0.0
434376 to: notification.baseOpacity
435− duration: dotShowAnimTimer.interval * dots.count * 5
377+ duration: notification.duration * dots.count
436378 }
437379
438380 PropertyAnimation {
@@ -442,7 +384,8 @@ Item {
442384 property: "opacity"
443385 from: notification.baseOpacity
444386 to: 0.0
445− duration: dotShowAnimTimer.interval * dots.count * 5
387+ duration: notification.duration * dots.count
388+ onStopped: if (!__useDotAnimation) infographic.model.readyForDataChange()
446389 }
447390 }
448391 }
@@ -453,9 +396,10 @@ Item {
453396 onDoubleClicked: {
454397 if (!dotHideAnimTimer.running &&
455398 !dotShowAnimTimer.running &&
456− !circleShrinkAnimTimer.running &&
457− !circleGrowAnimTimer.running)
399+ !circleChangeAnimTimer.running) {
400+ __useDotAnimation = false
458401 infographic.model.nextDataSource()
402+ }
459403 }
460404
461405 onClicked: mouse.accepted = false
qml/Shell.qml+6−3
@@ -48,6 +48,8 @@ Item {
4848 property url background
4949 readonly property real panelHeight: panel.panelHeight
5050
51+ readonly property bool locked: LightDM.Greeter.active && !LightDM.Greeter.authenticated
52+
5153 property bool sideStageEnabled: shell.width >= units.gu(100)
5254 readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId
5355
@@ -323,6 +325,7 @@ Item {
323325 available: true
324326 hides: [launcher, panel.indicators]
325327 shown: true
328+ loadContent: required || lockscreen.required // keeps content in memory for quick show()
326329
327330 defaultBackground: shell.background
328331
@@ -412,7 +415,7 @@ Item {
412415 }
413416
414417 function showDash() {
415− if (LightDM.Greeter.active && !LightDM.Greeter.promptless) {
418+ if (shell.locked) {
416419 return;
417420 }
418421 if (greeter.shown) {
@@ -436,7 +439,7 @@ Item {
436439 anchors.fill: parent //because this draws indicator menus
437440 indicators {
438441 hides: [launcher]
439− available: edgeDemo.panelEnabled && greeter.fakeActiveForApp === ""
442+ available: edgeDemo.panelEnabled && !shell.locked
440443 contentEnabled: edgeDemo.panelContentEnabled
441444 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
442445 panelHeight: units.gu(3)
@@ -460,7 +463,7 @@ Item {
460463 anchors.bottom: parent.bottom
461464 width: parent.width
462465 dragAreaWidth: shell.edgeSize
463− available: edgeDemo.launcherEnabled && greeter.fakeActiveForApp === ""
466+ available: edgeDemo.launcherEnabled && !shell.locked
464467
465468 onShowDashHome: showHome()
466469 onDash: showDash()
tests/autopilot/unity8/shell/emulators/greeter.py+2−1
@@ -28,6 +28,7 @@ class Greeter(UnityEmulatorBase):
2828 def swipe(self):
2929 """Swipe the greeter screen away."""
3030 self.created.wait_for(True)
31+ self.showProgress.wait_for(1)
3132
3233 rect = self.globalRect
3334 start_x = rect[0] + rect[2] - 3
@@ -36,7 +37,7 @@ class Greeter(UnityEmulatorBase):
3637 stop_y = start_y
3738 self.pointing_device.drag(start_x, start_y, stop_x, stop_y)
3839
39− self.created.wait_for(False)
40+ self.showProgress.wait_for(0)
4041
4142 def get_prompt(self):
4243 return self.select_single(
tests/qmltests/tst_ShellWithPin.qml+13−4
@@ -116,6 +116,14 @@ Item {
116116 tryCompare(sessionSpy, "count", 1)
117117 }
118118
119+ function test_disabledEdges() {
120+ var launcher = findChild(shell, "launcher")
121+ tryCompare(launcher, "available", false)
122+
123+ var indicators = findChild(shell, "indicators")
124+ tryCompare(indicators, "available", false)
125+ }
126+
119127 function test_emergencyCall() {
120128 var greeter = findChild(shell, "greeter")
121129 var lockscreen = findChild(shell, "lockscreen")
@@ -130,10 +138,13 @@ Item {
130138 tryCompare(greeter, "fakeActiveForApp", "dialer-app")
131139 tryCompare(lockscreen, "shown", false)
132140 tryCompare(panel, "fullscreenMode", true)
133− tryCompare(indicators, "available", false)
134− tryCompare(launcher, "available", false)
135141 tryCompare(stage, "spreadEnabled", false)
136142
143+ // These are normally false anyway, but confirm they remain so in
144+ // emergency mode.
145+ tryCompare(launcher, "available", false)
146+ tryCompare(indicators, "available", false)
147+
137148 // Cancel emergency mode, and go back to normal
138149 waitForRendering(greeter)
139150 LightDM.Greeter.showGreeter()
@@ -142,8 +153,6 @@ Item {
142153 tryCompare(greeter, "fakeActiveForApp", "")
143154 tryCompare(lockscreen, "shown", true)
144155 tryCompare(panel, "fullscreenMode", false)
145− tryCompare(indicators, "available", true)
146− tryCompare(launcher, "available", true)
147156 tryCompare(stage, "spreadEnabled", true)
148157 }
149158