on xenial help sign in
Merge in lockscreen-nits branch
60dc7a0Michael Terry
qml/Greeter/Greeter.qml+9−9
@@ -26,11 +26,12 @@ Showable {
26 created: greeterContentLoader.status == Loader.Ready && greeterContentLoader.item.ready
26 created: greeterContentLoader.status == Loader.Ready && greeterContentLoader.item.ready
27
27
28 property url defaultBackground
28 property url defaultBackground
29+ property bool loadContent: required
29
30
30 // 1 when fully shown and 0 when fully hidden
31 // 1 when fully shown and 0 when fully hidden
31 property real showProgress: MathUtils.clamp((width - Math.abs(x)) / width, 0, 1)
32 property real showProgress: MathUtils.clamp((width - Math.abs(x)) / width, 0, 1)
32
33
33− showAnimation: StandardAnimation { property: "x"; to: 0 }
34+ showAnimation: StandardAnimation { property: "x"; to: 0; duration: UbuntuAnimation.FastDuration }
34 hideAnimation: __leftHideAnimation
35 hideAnimation: __leftHideAnimation
35
36
36 property alias dragHandleWidth: dragHandle.width
37 property alias dragHandleWidth: dragHandle.width
@@ -58,10 +59,8 @@ Showable {
58
59
59 onRequiredChanged: {
60 onRequiredChanged: {
60 // Reset hide animation to default once we're finished with it
61 // Reset hide animation to default once we're finished with it
61− if (!required) {
62+ if (required) {
62− // Put back on left for reliable show direction and so that
63+ // Reset hide animation so that a hide() call is reliably left
63− // if normal hide() is called, we don't animate from right.
64− x = -width
65 hideAnimation = __leftHideAnimation
64 hideAnimation = __leftHideAnimation
66 }
65 }
67 }
66 }
@@ -90,12 +89,13 @@ Showable {
90 onPressAndHold: {} // eat event, but no need to tease, as drag will cover it
89 onPressAndHold: {} // eat event, but no need to tease, as drag will cover it
91
90
92 onDragEnd: {
91 onDragEnd: {
93− if (rightEvaluator.shouldAutoComplete())
92+ if (greeter.x > 0 && rightEvaluator.shouldAutoComplete()) {
94 greeter.hideRight()
93 greeter.hideRight()
95− else if (leftEvaluator.shouldAutoComplete())
94+ } else if (greeter.x < 0 && leftEvaluator.shouldAutoComplete()) {
96 greeter.hide();
95 greeter.hide();
97− else
96+ } else {
98 greeter.show(); // undo drag
97 greeter.show(); // undo drag
98+ }
99 }
99 }
100
100
101 onDragValueChanged: {
101 onDragValueChanged: {
@@ -127,7 +127,7 @@ Showable {
127 property var infographicModel: LightDM.Infographic
127 property var infographicModel: LightDM.Infographic
128 readonly property int backgroundTopMargin: -greeter.y
128 readonly property int backgroundTopMargin: -greeter.y
129
129
130− source: required ? "GreeterContent.qml" : ""
130+ source: loadContent ? "GreeterContent.qml" : ""
131
131
132 onLoaded: {
132 onLoaded: {
133 selected(currentIndex);
133 selected(currentIndex);
qml/Greeter/Infographics.qml+46−102
@@ -26,6 +26,9 @@ Item {
26
26
27 property int animDuration: 10
27 property int animDuration: 10
28
28
29+ property bool __useDotAnimation: true
30+ property int __circleModifier: __useDotAnimation ? 1 : 2
31+
29 Connections {
32 Connections {
30 target: model
33 target: model
31
34
@@ -41,19 +44,24 @@ Item {
41
44
42 function startShowAnimation() {
45 function startShowAnimation() {
43 dotHideAnimTimer.stop()
46 dotHideAnimTimer.stop()
44− circleShrinkAnimTimer.stop()
45 notification.hideAnim.stop()
47 notification.hideAnim.stop()
46
48
49+ if (__useDotAnimation) {
47− dotShowAnimTimer.startFromBeginning()
50+ dotShowAnimTimer.startFromBeginning()
51+ }
48 notification.showAnim.start()
52 notification.showAnim.start()
49 }
53 }
50
54
51 function startHideAnimation() {
55 function startHideAnimation() {
52 dotShowAnimTimer.stop()
56 dotShowAnimTimer.stop()
53− circleGrowAnimTimer.stop()
57+ circleChangeAnimTimer.stop()
54 notification.showAnim.stop()
58 notification.showAnim.stop()
55
59
60+ if (__useDotAnimation) {
56− dotHideAnimTimer.startFromBeginning()
61+ dotHideAnimTimer.startFromBeginning()
62+ } else {
63+ circleChangeAnimTimer.startFromBeginning()
64+ }
57 notification.hideAnim.start()
65 notification.hideAnim.start()
58 }
66 }
59
67
@@ -73,22 +81,22 @@ Item {
73 anchors.centerIn: parent
81 anchors.centerIn: parent
74
82
75 Timer {
83 Timer {
76− id: circleGrowAnimTimer
84+ id: circleChangeAnimTimer
77
85
78 property int pastCircleCounter
86 property int pastCircleCounter
79 property int presentCircleCounter
87 property int presentCircleCounter
80
88
81− interval: animDuration
89+ interval: notification.duration
82 running: false
90 running: false
83 repeat: true
91 repeat: true
84 onTriggered: {
92 onTriggered: {
85 if (pastCircleCounter < pastCircles.count) {
93 if (pastCircleCounter < pastCircles.count) {
86 var nextCircle = pastCircles.itemAt(pastCircleCounter++)
94 var nextCircle = pastCircles.itemAt(pastCircleCounter++)
87− if (nextCircle !== null) nextCircle.pastCircleGrowAnim.start()
95+ if (nextCircle !== null) nextCircle.pastCircleChangeAnim.start()
88 }
96 }
89 if (pastCircleCounter > pastCircles.count / 2) {
97 if (pastCircleCounter > pastCircles.count / 2) {
90 var nextCircle = presentCircles.itemAt(presentCircleCounter++)
98 var nextCircle = presentCircles.itemAt(presentCircleCounter++)
91− if (nextCircle !== null) nextCircle.presentCircleGrowAnim.start()
99+ if (nextCircle !== null) nextCircle.presentCircleChangeAnim.start()
92 }
100 }
93 if (presentCircleCounter > infographic.model.currentDay && pastCircleCounter >= pastCircles.count) {
101 if (presentCircleCounter > infographic.model.currentDay && pastCircleCounter >= pastCircles.count) {
94 stop()
102 stop()
@@ -96,39 +104,8 @@ Item {
96 }
104 }
97
105
98 function startFromBeginning() {
106 function startFromBeginning() {
99− circleGrowAnimTimer.pastCircleCounter = 0
107+ circleChangeAnimTimer.pastCircleCounter = 0
100− circleGrowAnimTimer.presentCircleCounter = 0
108+ circleChangeAnimTimer.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
132 start()
109 start()
133 }
110 }
134 }
111 }
@@ -139,8 +116,7 @@ Item {
139 model: infographic.model.secondMonth
116 model: infographic.model.secondMonth
140
117
141 delegate: ObjectPositioner {
118 delegate: ObjectPositioner {
142− property alias pastCircleGrowAnim: pastCircleGrowAnim
119+ property alias pastCircleChangeAnim: pastCircleChangeAnim
143− property alias pastCircleShrinkAnim: pastCircleShrinkAnim
144
120
145 index: model.index
121 index: model.index
146 count: pastCircles.count
122 count: pastCircles.count
@@ -160,52 +136,33 @@ Item {
160 opacity: 0.0
136 opacity: 0.0
161 scale: 0.0
137 scale: 0.0
162 visible: modelData !== undefined
138 visible: modelData !== undefined
163− color: Gradient.threeColorByIndex(index, count, infographic.model.secondColor)
139+ color: "transparent"
164
140
165 SequentialAnimation {
141 SequentialAnimation {
166− id: pastCircleGrowAnim
142+ id: pastCircleChangeAnim
167
143
168 loops: 1
144 loops: 1
169 ParallelAnimation {
145 ParallelAnimation {
170 PropertyAnimation {
146 PropertyAnimation {
171 target: pastCircle
147 target: pastCircle
172 property: "opacity"
148 property: "opacity"
173− from: 0.0
174 to: pastCircle.circleOpacity
149 to: pastCircle.circleOpacity
175 easing.type: Easing.OutCurve
150 easing.type: Easing.OutCurve
176− duration: circleGrowAnimTimer.interval * 4
151+ duration: circleChangeAnimTimer.interval * __circleModifier
177 }
152 }
178 PropertyAnimation {
153 PropertyAnimation {
179 target: pastCircle
154 target: pastCircle
180 property: "scale"
155 property: "scale"
181− from: 0.0
182 to: modelData
156 to: modelData
183 easing.type: Easing.OutCurve
157 easing.type: Easing.OutCurve
184− duration: circleGrowAnimTimer.interval * 4
158+ duration: circleChangeAnimTimer.interval * __circleModifier
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
201 }
159 }
202− PropertyAnimation {
160+ ColorAnimation {
203 target: pastCircle
161 target: pastCircle
204− property: "scale"
162+ property: "color"
205− from: modelData
163+ to: Gradient.threeColorByIndex(index, count, infographic.model.secondColor)
206− to: 0.0
207 easing.type: Easing.OutCurve
164 easing.type: Easing.OutCurve
208− duration: circleShrinkAnimTimer.interval * 4
165+ duration: circleChangeAnimTimer.interval * __circleModifier
209 }
166 }
210 }
167 }
211 }
168 }
@@ -219,8 +176,7 @@ Item {
219 model: infographic.model.firstMonth
176 model: infographic.model.firstMonth
220
177
221 delegate: ObjectPositioner {
178 delegate: ObjectPositioner {
222− property alias presentCircleGrowAnim: presentCircleGrowAnim
179+ property alias presentCircleChangeAnim: presentCircleChangeAnim
223− property alias presentCircleShrinkAnim: presentCircleShrinkAnim
224
180
225 index: model.index
181 index: model.index
226 count: presentCircles.count
182 count: presentCircles.count
@@ -240,10 +196,10 @@ Item {
240 opacity: 0.0
196 opacity: 0.0
241 scale: 0.0
197 scale: 0.0
242 visible: modelData !== undefined
198 visible: modelData !== undefined
243− color: Gradient.threeColorByIndex(index, infographic.model.currentDay, infographic.model.firstColor)
199+ color: "transparent"
244
200
245 SequentialAnimation {
201 SequentialAnimation {
246− id: presentCircleGrowAnim
202+ id: presentCircleChangeAnim
247
203
248 loops: 1
204 loops: 1
249
205
@@ -253,36 +209,21 @@ Item {
253 property: "opacity"
209 property: "opacity"
254 to: presentCircle.circleOpacity
210 to: presentCircle.circleOpacity
255 easing.type: Easing.OutCurve
211 easing.type: Easing.OutCurve
256− duration: circleGrowAnimTimer.interval * 4
212+ duration: circleChangeAnimTimer.interval * __circleModifier
257 }
213 }
258 PropertyAnimation {
214 PropertyAnimation {
259 target: presentCircle
215 target: presentCircle
260 property: "scale"
216 property: "scale"
261 to: modelData
217 to: modelData
262 easing.type: Easing.OutCurve
218 easing.type: Easing.OutCurve
263− duration: circleGrowAnimTimer.interval * 4
219+ duration: circleChangeAnimTimer.interval * __circleModifier
264 }
220 }
265− }
221+ ColorAnimation {
266− }
267−
268− SequentialAnimation {
269− id: presentCircleShrinkAnim
270−
271− loops: 1
272− ParallelAnimation {
273− PropertyAnimation {
274 target: presentCircle
222 target: presentCircle
275− property: "opacity"
223+ property: "color"
276− to: 0.0
224+ to: Gradient.threeColorByIndex(index, infographic.model.currentDay, infographic.model.firstColor)
277 easing.type: Easing.OutCurve
225 easing.type: Easing.OutCurve
278− duration: circleShrinkAnimTimer.interval * 4
226+ duration: circleChangeAnimTimer.interval * __circleModifier
279− }
280− PropertyAnimation {
281− target: presentCircle
282− property: "scale"
283− to: 0.0
284− easing.type: Easing.OutCurve
285− duration: circleShrinkAnimTimer.interval * 4
286 }
227 }
287 }
228 }
288 }
229 }
@@ -313,7 +254,7 @@ Item {
313 stop()
254 stop()
314 }
255 }
315 if (dotCounter == Math.round(dots.count / 2)) {
256 if (dotCounter == Math.round(dots.count / 2)) {
316− circleGrowAnimTimer.startFromBeginning()
257+ circleChangeAnimTimer.startFromBeginning()
317 }
258 }
318 }
259 }
319
260
@@ -340,8 +281,8 @@ Item {
340 } else {
281 } else {
341 stop()
282 stop()
342 }
283 }
343− if (dotCounter == Math.round(dots.count / 2)) {
284+ if (dotCounter == 0) {
344− circleShrinkAnimTimer.startFromBeginning()
285+ infographic.model.readyForDataChange()
345 }
286 }
346 }
287 }
347
288
@@ -413,6 +354,7 @@ Item {
413 property alias showAnim: increaseOpacity
354 property alias showAnim: increaseOpacity
414
355
415 property real baseOpacity: 0.6
356 property real baseOpacity: 0.6
357+ property real duration: dotShowAnimTimer.interval * 5
416
358
417 height: 0.7 * backgroundCircle.width
359 height: 0.7 * backgroundCircle.width
418 width: notification.height
360 width: notification.height
@@ -432,7 +374,7 @@ Item {
432 property: "opacity"
374 property: "opacity"
433 from: 0.0
375 from: 0.0
434 to: notification.baseOpacity
376 to: notification.baseOpacity
435− duration: dotShowAnimTimer.interval * dots.count * 5
377+ duration: notification.duration * dots.count
436 }
378 }
437
379
438 PropertyAnimation {
380 PropertyAnimation {
@@ -442,7 +384,8 @@ Item {
442 property: "opacity"
384 property: "opacity"
443 from: notification.baseOpacity
385 from: notification.baseOpacity
444 to: 0.0
386 to: 0.0
445− duration: dotShowAnimTimer.interval * dots.count * 5
387+ duration: notification.duration * dots.count
388+ onStopped: if (!__useDotAnimation) infographic.model.readyForDataChange()
446 }
389 }
447 }
390 }
448 }
391 }
@@ -453,9 +396,10 @@ Item {
453 onDoubleClicked: {
396 onDoubleClicked: {
454 if (!dotHideAnimTimer.running &&
397 if (!dotHideAnimTimer.running &&
455 !dotShowAnimTimer.running &&
398 !dotShowAnimTimer.running &&
456− !circleShrinkAnimTimer.running &&
399+ !circleChangeAnimTimer.running) {
457− !circleGrowAnimTimer.running)
400+ __useDotAnimation = false
458 infographic.model.nextDataSource()
401 infographic.model.nextDataSource()
402+ }
459 }
403 }
460
404
461 onClicked: mouse.accepted = false
405 onClicked: mouse.accepted = false
qml/Shell.qml+6−3
@@ -48,6 +48,8 @@ Item {
48 property url background
48 property url background
49 readonly property real panelHeight: panel.panelHeight
49 readonly property real panelHeight: panel.panelHeight
50
50
51+ readonly property bool locked: LightDM.Greeter.active && !LightDM.Greeter.authenticated
52+
51 property bool sideStageEnabled: shell.width >= units.gu(100)
53 property bool sideStageEnabled: shell.width >= units.gu(100)
52 readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId
54 readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId
53
55
@@ -328,6 +330,7 @@ Item {
328 available: true
330 available: true
329 hides: [launcher, panel.indicators]
331 hides: [launcher, panel.indicators]
330 shown: true
332 shown: true
333+ loadContent: required || lockscreen.required // keeps content in memory for quick show()
331
334
332 defaultBackground: shell.background
335 defaultBackground: shell.background
333
336
@@ -417,7 +420,7 @@ Item {
417 }
420 }
418
421
419 function showDash() {
422 function showDash() {
420− if (LightDM.Greeter.active && !LightDM.Greeter.promptless) {
423+ if (shell.locked) {
421 return;
424 return;
422 }
425 }
423 if (greeter.shown) {
426 if (greeter.shown) {
@@ -441,7 +444,7 @@ Item {
441 anchors.fill: parent //because this draws indicator menus
444 anchors.fill: parent //because this draws indicator menus
442 indicators {
445 indicators {
443 hides: [launcher]
446 hides: [launcher]
444− available: edgeDemo.panelEnabled && greeter.fakeActiveForApp === ""
447+ available: edgeDemo.panelEnabled && !shell.locked
445 contentEnabled: edgeDemo.panelContentEnabled
448 contentEnabled: edgeDemo.panelContentEnabled
446 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
449 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
447 panelHeight: units.gu(3)
450 panelHeight: units.gu(3)
@@ -465,7 +468,7 @@ Item {
465 anchors.bottom: parent.bottom
468 anchors.bottom: parent.bottom
466 width: parent.width
469 width: parent.width
467 dragAreaWidth: shell.edgeSize
470 dragAreaWidth: shell.edgeSize
468− available: edgeDemo.launcherEnabled && greeter.fakeActiveForApp === ""
471+ available: edgeDemo.launcherEnabled && !shell.locked
469
472
470 onShowDashHome: showHome()
473 onShowDashHome: showHome()
471 onDash: showDash()
474 onDash: showDash()
tests/autopilot/unity8/shell/emulators/greeter.py+2−1
@@ -28,6 +28,7 @@ class Greeter(UnityEmulatorBase):
28 def swipe(self):
28 def swipe(self):
29 """Swipe the greeter screen away."""
29 """Swipe the greeter screen away."""
30 self.created.wait_for(True)
30 self.created.wait_for(True)
31+ self.showProgress.wait_for(1)
31
32
32 rect = self.globalRect
33 rect = self.globalRect
33 start_x = rect[0] + rect[2] - 3
34 start_x = rect[0] + rect[2] - 3
@@ -36,7 +37,7 @@ class Greeter(UnityEmulatorBase):
36 stop_y = start_y
37 stop_y = start_y
37 self.pointing_device.drag(start_x, start_y, stop_x, stop_y)
38 self.pointing_device.drag(start_x, start_y, stop_x, stop_y)
38
39
39− self.created.wait_for(False)
40+ self.showProgress.wait_for(0)
40
41
41 def get_prompt(self):
42 def get_prompt(self):
42 return self.select_single(
43 return self.select_single(
tests/qmltests/tst_ShellWithPin.qml+13−4
@@ -116,6 +116,14 @@ Item {
116 tryCompare(sessionSpy, "count", 1)
116 tryCompare(sessionSpy, "count", 1)
117 }
117 }
118
118
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+
119 function test_emergencyCall() {
127 function test_emergencyCall() {
120 var greeter = findChild(shell, "greeter")
128 var greeter = findChild(shell, "greeter")
121 var lockscreen = findChild(shell, "lockscreen")
129 var lockscreen = findChild(shell, "lockscreen")
@@ -130,10 +138,13 @@ Item {
130 tryCompare(greeter, "fakeActiveForApp", "dialer-app")
138 tryCompare(greeter, "fakeActiveForApp", "dialer-app")
131 tryCompare(lockscreen, "shown", false)
139 tryCompare(lockscreen, "shown", false)
132 tryCompare(panel, "fullscreenMode", true)
140 tryCompare(panel, "fullscreenMode", true)
133− tryCompare(indicators, "available", false)
134− tryCompare(launcher, "available", false)
135 tryCompare(stage, "spreadEnabled", false)
141 tryCompare(stage, "spreadEnabled", false)
136
142
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+
137 // Cancel emergency mode, and go back to normal
148 // Cancel emergency mode, and go back to normal
138 waitForRendering(greeter)
149 waitForRendering(greeter)
139 LightDM.Greeter.showGreeter()
150 LightDM.Greeter.showGreeter()
@@ -142,8 +153,6 @@ Item {
142 tryCompare(greeter, "fakeActiveForApp", "")
153 tryCompare(greeter, "fakeActiveForApp", "")
143 tryCompare(lockscreen, "shown", true)
154 tryCompare(lockscreen, "shown", true)
144 tryCompare(panel, "fullscreenMode", false)
155 tryCompare(panel, "fullscreenMode", false)
145− tryCompare(indicators, "available", true)
146− tryCompare(launcher, "available", true)
147 tryCompare(stage, "spreadEnabled", true)
156 tryCompare(stage, "spreadEnabled", true)
148 }
157 }
149
158