on xenial help sign in
Switch from lockscreen PIN pad to a passcode entry box that uses the OSK.
80ab351Michael Terry
qml/Components/Lockscreen.qml−23
@@ -41,9 +41,6 @@ Showable {
41 // The text to be displayed in case the login failed
41 // The text to be displayed in case the login failed
42 property string errorText: ""
42 property string errorText: ""
43
43
44− // If > 0, a forced delay is happening
45− property int delayMinutes: 0
46−
47 // Set those to a value greater 0 to restrict the pin length.
44 // Set those to a value greater 0 to restrict the pin length.
48 // If both are unset, the Lockscreen will show a confirm button and allow typing any length of pin before
45 // If both are unset, the Lockscreen will show a confirm button and allow typing any length of pin before
49 // confirming. If minPinLength is set to a value > 0, the confirm button will only become active when the
46 // confirming. If minPinLength is set to a value > 0, the confirm button will only become active when the
@@ -91,14 +88,6 @@ Showable {
91 popup.z = Number.MAX_VALUE
88 popup.z = Number.MAX_VALUE
92 }
89 }
93
90
94− function showText(text) {
95− // Programmatically enters the given text into the lockscreen
96− if (pinPadLoader.item) {
97− pinPadLoader.item.showText(text);
98− pinPadLoader.waiting = true;
99− }
100− }
101−
102 Rectangle {
91 Rectangle {
103 // In case background fails to load
92 // In case background fails to load
104 id: backgroundBackup
93 id: backgroundBackup
@@ -141,8 +130,6 @@ Showable {
141 source: {
130 source: {
142 if (resetting || !root.required) {
131 if (resetting || !root.required) {
143 return ""
132 return ""
144− } else if (root.delayMinutes > 0) {
145− return "DelayedLockscreen.qml"
146 } else if (root.alphaNumeric) {
133 } else if (root.alphaNumeric) {
147 return "PassphraseLockscreen.qml"
134 return "PassphraseLockscreen.qml"
148 } else {
135 } else {
@@ -197,16 +184,6 @@ Showable {
197 property: "entryEnabled"
184 property: "entryEnabled"
198 value: !pinPadLoader.waiting
185 value: !pinPadLoader.waiting
199 }
186 }
200− Binding {
201− target: pinPadLoader.item
202− property: "alphaNumeric"
203− value: root.alphaNumeric
204− }
205− Binding {
206− target: pinPadLoader.item
207− property: "delayMinutes"
208− value: root.delayMinutes
209− }
210 Binding {
187 Binding {
211 target: pinPadLoader.item
188 target: pinPadLoader.item
212 property: "showCancelButton"
189 property: "showCancelButton"
qml/Components/PassphraseLockscreen.qml−4
@@ -43,10 +43,6 @@ FocusScope {
43 }
43 }
44 }
44 }
45
45
46− function showText(text) {
47− pinentryField.text = text;
48− }
49−
50 Column {
46 Column {
51 id: shakeContainer
47 id: shakeContainer
52 anchors.horizontalCenter: parent.horizontalCenter
48 anchors.horizontalCenter: parent.horizontalCenter
qml/Components/PinLockscreen.qml−4
@@ -46,10 +46,6 @@ FocusScope {
46 }
46 }
47 }
47 }
48
48
49− function showText(text) {
50− pinentryField.text = text;
51− }
52−
53 Keys.onPressed: {
49 Keys.onPressed: {
54 if (pinentryField.text.length == root.maxPinLength)
50 if (pinentryField.text.length == root.maxPinLength)
55 return;
51 return;
qml/Components/DelayedLockscreen.qml → qml/Greeter/DelayedLockscreen.qmlrenamed+6−15
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013,2014 Canonical, Ltd.
2+ * Copyright (C) 2013-2016 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -16,7 +16,6 @@
16
16
17import QtQuick 2.4
17import QtQuick 2.4
18import Ubuntu.Components 1.3
18import Ubuntu.Components 1.3
19−import "../Components"
20
19
21Item {
20Item {
22 id: root
21 id: root
@@ -24,12 +23,6 @@ Item {
24 property int delayMinutes
23 property int delayMinutes
25 property bool alphaNumeric
24 property bool alphaNumeric
26
25
27− signal entered(string passphrase) // unused
28− signal cancel() // unused
29−
30− function clear(playAnimation) {}
31− function showText(text) {}
32−
33 Column {
26 Column {
34 anchors.left: parent.left
27 anchors.left: parent.left
35 anchors.right: parent.right
28 anchors.right: parent.right
@@ -46,7 +39,7 @@ Item {
46 horizontalAlignment: Text.AlignHCenter
39 horizontalAlignment: Text.AlignHCenter
47 wrapMode: Text.Wrap
40 wrapMode: Text.Wrap
48 fontSize: "x-large"
41 fontSize: "x-large"
49− color: "#f3f3e7"
42+ color: "white"
50 text: i18n.tr("Device Locked")
43 text: i18n.tr("Device Locked")
51 }
44 }
52
45
@@ -60,7 +53,7 @@ Item {
60 anchors.right: parent.right
53 anchors.right: parent.right
61 horizontalAlignment: Text.AlignHCenter
54 horizontalAlignment: Text.AlignHCenter
62 wrapMode: Text.Wrap
55 wrapMode: Text.Wrap
63− color: "#f3f3e7"
56+ color: "white"
64 text: alphaNumeric ?
57 text: alphaNumeric ?
65 i18n.tr("You have been locked out due to too many failed passphrase attempts.") :
58 i18n.tr("You have been locked out due to too many failed passphrase attempts.") :
66 i18n.tr("You have been locked out due to too many failed passcode attempts.")
59 i18n.tr("You have been locked out due to too many failed passcode attempts.")
@@ -71,7 +64,7 @@ Item {
71 anchors.right: parent.right
64 anchors.right: parent.right
72 horizontalAlignment: Text.AlignHCenter
65 horizontalAlignment: Text.AlignHCenter
73 wrapMode: Text.Wrap
66 wrapMode: Text.Wrap
74− color: "#f3f3e7"
67+ color: "white"
75 text: i18n.tr("Please wait %1 minute and then try again…",
68 text: i18n.tr("Please wait %1 minute and then try again…",
76 "Please wait %1 minutes and then try again…",
69 "Please wait %1 minutes and then try again…",
77 root.delayMinutes).arg(root.delayMinutes)
70 root.delayMinutes).arg(root.delayMinutes)
@@ -83,10 +76,8 @@ Item {
83 }
76 }
84
77
85 Icon {
78 Icon {
86− // It would be nice to use a less network-specific name,
79+ name: "lock"
87− // but this is the only lock icon we have.
88− name: "network-secure"
89− color: "#f3f3e7"
80+ color: "white"
90 height: units.gu(4)
81 height: units.gu(4)
91 width: units.gu(4)
82 width: units.gu(4)
92 anchors.horizontalCenter: parent.horizontalCenter
83 anchors.horizontalCenter: parent.horizontalCenter
qml/Greeter/Greeter.qml+34−21
@@ -72,9 +72,12 @@ Showable {
72 }
72 }
73 forcedUnlock = false;
73 forcedUnlock = false;
74 if (required) {
74 if (required) {
75+ if (loader.item) {
76+ loader.item.reset(true /* forceShow */);
77+ }
75 // Normally loader.onLoaded will select a user, but if we're
78 // Normally loader.onLoaded will select a user, but if we're
76 // already shown, do it manually.
79 // already shown, do it manually.
77− d.selectUser(d.currentIndex, true);
80+ d.selectUser(d.currentIndex, false);
78 }
81 }
79
82
80 // Even though we may already be shown, we want to call show() for its
83 // Even though we may already be shown, we want to call show() for its
@@ -194,7 +197,7 @@ Showable {
194 return;
197 return;
195 d.waiting = true;
198 d.waiting = true;
196 if (reset) {
199 if (reset) {
197− loader.item.reset();
200+ loader.item.reset(false /* forceShow */);
198 }
201 }
199 currentIndex = index;
202 currentIndex = index;
200 var user = LightDMService.users.data(index, LightDMService.userRoles.NameRole);
203 var user = LightDMService.users.data(index, LightDMService.userRoles.NameRole);
@@ -238,6 +241,29 @@ Showable {
238 }
241 }
239 }
242 }
240 }
243 }
244+
245+ function showPromptMessage(text, isError) {
246+ // inefficient, but we only rarely deal with messages
247+ var html = text.replace(/&/g, "&")
248+ .replace(/</g, "&lt;")
249+ .replace(/>/g, "&gt;")
250+ .replace(/\n/g, "<br>");
251+ if (isError) {
252+ html = "<font color=\"#df382c\">" + html + "</font>";
253+ }
254+
255+ if (loader.item) {
256+ loader.item.showMessage(html);
257+ }
258+ }
259+
260+ function showFingerprintMessage(msg) {
261+ if (loader.item) {
262+ loader.item.reset(false /* forceShow */);
263+ loader.item.showErrorMessage(msg);
264+ }
265+ showPromptMessage(msg, true);
266+ }
241 }
267 }
242
268
243 onLauncherOffsetChanged: {
269 onLauncherOffsetChanged: {
@@ -452,20 +478,7 @@ Showable {
452 onShowGreeter: root.forceShow()
478 onShowGreeter: root.forceShow()
453 onHideGreeter: root.forcedUnlock = true
479 onHideGreeter: root.forcedUnlock = true
454
480
455− onShowMessage: {
481+ onShowMessage: d.showPromptMessage(text, isError)
456− // inefficient, but we only rarely deal with messages
457− var html = text.replace(/&/g, "&amp;")
458− .replace(/</g, "&lt;")
459− .replace(/>/g, "&gt;")
460− .replace(/\n/g, "<br>");
461− if (isError) {
462− html = "<font color=\"#df382c\">" + html + "</font>";
463− }
464−
465− if (loader.item) {
466− loader.item.showMessage(html);
467− }
468− }
469
482
470 onShowPrompt: {
483 onShowPrompt: {
471 if (loader.item) {
484 if (loader.item) {
@@ -573,10 +586,8 @@ Showable {
573 if (!d.secureFingerprint) {
586 if (!d.secureFingerprint) {
574 d.startUnlock(false /* toTheRight */); // use normal login instead
587 d.startUnlock(false /* toTheRight */); // use normal login instead
575 }
588 }
576− if (loader.item) {
577− var msg = d.secureFingerprint ? i18n.tr("Try again") : "";
589+ var msg = d.secureFingerprint ? i18n.tr("Try again") : "";
578− loader.item.showErrorMessage(msg);
590+ d.showFingerprintMessage(msg);
579− }
580 }
591 }
581
592
582 Component.onCompleted: restartOperation()
593 Component.onCompleted: restartOperation()
@@ -594,8 +605,10 @@ Showable {
594 return;
605 return;
595 }
606 }
596 console.log("Identified user by fingerprint:", result);
607 console.log("Identified user by fingerprint:", result);
597− if (loader.item)
608+ if (loader.item) {
609+ loader.item.enabled = false;
598 loader.item.notifyAuthenticationSucceeded(true /* showFakePassword */);
610 loader.item.notifyAuthenticationSucceeded(true /* showFakePassword */);
611+ }
599 if (root.active)
612 if (root.active)
600 root.forcedUnlock = true;
613 root.forcedUnlock = true;
601 }
614 }
qml/Greeter/GreeterPrompt.qml+21−7
@@ -38,6 +38,16 @@ FocusScope {
38 d.enabled = true;
38 d.enabled = true;
39 }
39 }
40
40
41+ function showFakePassword() {
42+ // Just a silly hack for looking like 4 pin numbers got entered, if
43+ // a fingerprint was used and we happen to be using a pin. This was
44+ // a request from Design.
45+ if (isSecret && isPrompt && !isAlphanumeric) {
46+ d.enabled = false;
47+ text = "...."; // actual text doesn't matter
48+ }
49+ }
50+
41 StyledItem {
51 StyledItem {
42 id: d
52 id: d
43
53
@@ -50,6 +60,12 @@ FocusScope {
50 : theme.palette.disabled.raisedSecondaryText
60 : theme.palette.disabled.raisedSecondaryText
51 readonly property color errorColor: passwordInput.enabled ? theme.palette.normal.negative
61 readonly property color errorColor: passwordInput.enabled ? theme.palette.normal.negative
52 : theme.palette.disabled.negative
62 : theme.palette.disabled.negative
63+
64+ onEnabledChanged: {
65+ if (!enabled) {
66+ fakeLabel.text = passwordInput.displayText;
67+ }
68+ }
53 }
69 }
54
70
55 Rectangle {
71 Rectangle {
@@ -142,15 +158,13 @@ FocusScope {
142 }
158 }
143 }
159 }
144
160
145− onAccepted: {
161+ onAccepted: respond()
146− if (d.enabled)
147− respond();
148− }
149
162
150 function respond() {
163 function respond() {
164+ if (d.enabled) {
151− d.enabled = false;
165+ d.enabled = false;
152− fakeLabel.text = displayText;
153− root.responded(text);
166+ root.responded(text);
167+ }
154 }
168 }
155
169
156 Keys.onEscapePressed: {
170 Keys.onEscapePressed: {
qml/Greeter/LoginList.qml+9−3
@@ -29,6 +29,7 @@ StyledItem {
29 property int currentIndex
29 property int currentIndex
30 property bool locked
30 property bool locked
31 property bool waiting
31 property bool waiting
32+ property alias boxVerticalOffset: highlightItem.y
32
33
33 readonly property alias passwordInput: passwordInput
34 readonly property alias passwordInput: passwordInput
34 readonly property int numAboveBelow: 4
35 readonly property int numAboveBelow: 4
@@ -84,6 +85,10 @@ StyledItem {
84 root.resetAuthentication();
85 root.resetAuthentication();
85 }
86 }
86
87
88+ function showFakePassword() {
89+ passwordInput.showFakePassword();
90+ }
91+
87 QtObject {
92 QtObject {
88 id: d
93 id: d
89
94
@@ -123,12 +128,12 @@ StyledItem {
123
128
124 LoginAreaContainer {
129 LoginAreaContainer {
125 id: highlightItem
130 id: highlightItem
131+ objectName: "highlightItem"
126 anchors {
132 anchors {
127 left: parent.left
133 left: parent.left
128 leftMargin: units.gu(2)
134 leftMargin: units.gu(2)
129 right: parent.right
135 right: parent.right
130 rightMargin: units.gu(2)
136 rightMargin: units.gu(2)
131− verticalCenter: parent.verticalCenter
132 }
137 }
133
138
134 height: root.highlightedHeight
139 height: root.highlightedHeight
@@ -142,8 +147,8 @@ StyledItem {
142 anchors.leftMargin: units.gu(2)
147 anchors.leftMargin: units.gu(2)
143 anchors.rightMargin: units.gu(2)
148 anchors.rightMargin: units.gu(2)
144
149
145− preferredHighlightBegin: userList.height / 2 - root.highlightedHeight / 2
150+ preferredHighlightBegin: highlightItem.y
146− preferredHighlightEnd: userList.height / 2 - root.highlightedHeight / 2
151+ preferredHighlightEnd: highlightItem.y
147 highlightRangeMode: ListView.StrictlyEnforceRange
152 highlightRangeMode: ListView.StrictlyEnforceRange
148 highlightMoveDuration: root.moveDuration
153 highlightMoveDuration: root.moveDuration
149 flickDeceleration: 10000
154 flickDeceleration: 10000
@@ -352,6 +357,7 @@ StyledItem {
352
357
353 WrongPasswordAnimation {
358 WrongPasswordAnimation {
354 id: wrongPasswordAnimation
359 id: wrongPasswordAnimation
360+ objectName: "wrongPasswordAnimation"
355 target: passwordInput
361 target: passwordInput
356 }
362 }
357 }
363 }
qml/Greeter/NarrowView.qml+147−61
@@ -15,7 +15,9 @@
15 */
15 */
16
16
17import QtQuick 2.4
17import QtQuick 2.4
18+import QtQuick.Window 2.2
18import Ubuntu.Components 1.3
19import Ubuntu.Components 1.3
20+import Ubuntu.Telephony 0.1 as Telephony
19import "../Components"
21import "../Components"
20
22
21FocusScope {
23FocusScope {
@@ -23,13 +25,13 @@ FocusScope {
23
25
24 property alias dragHandleLeftMargin: coverPage.dragHandleLeftMargin
26 property alias dragHandleLeftMargin: coverPage.dragHandleLeftMargin
25 property alias launcherOffset: coverPage.launcherOffset
27 property alias launcherOffset: coverPage.launcherOffset
26− property int currentIndex // unused
28+ property alias currentIndex: loginList.currentIndex
27− property alias delayMinutes: lockscreen.delayMinutes
29+ property alias delayMinutes: delayedLockscreen.delayMinutes
28 property alias backgroundTopMargin: coverPage.backgroundTopMargin
30 property alias backgroundTopMargin: coverPage.backgroundTopMargin
29 property url background
31 property url background
30 property bool locked
32 property bool locked
31− property bool alphanumeric
33+ property alias alphanumeric: loginList.alphanumeric
32− property var userModel // unused
34+ property alias userModel: loginList.model
33 property alias infographicModel: coverPage.infographicModel
35 property alias infographicModel: coverPage.infographicModel
34 property string sessionToStart
36 property string sessionToStart
35 property bool waiting
37 property bool waiting
@@ -37,21 +39,25 @@ FocusScope {
37 readonly property bool required: coverPage.required || lockscreen.required
39 readonly property bool required: coverPage.required || lockscreen.required
38 readonly property bool animating: coverPage.showAnimation.running || coverPage.hideAnimation.running
40 readonly property bool animating: coverPage.showAnimation.running || coverPage.hideAnimation.running
39
41
42+ // so that it can be replaced in tests with a mock object
43+ property var inputMethod: Qt.inputMethod
44+
40− signal selected(int index) // unused
45+ signal selected(int index)
41 signal responded(string response)
46 signal responded(string response)
42 signal tease()
47 signal tease()
43 signal emergencyCall()
48 signal emergencyCall()
44
49
45 function showMessage(html) {
50 function showMessage(html) {
46− // TODO
51+ loginList.showMessage(html);
47 }
52 }
48
53
49 function showPrompt(text, isSecret, isDefaultPrompt) {
54 function showPrompt(text, isSecret, isDefaultPrompt) {
50− lockscreen.promptText = isDefaultPrompt ? "" : text.toLowerCase();
55+ loginList.showPrompt(text, isSecret, isDefaultPrompt);
51− lockscreen.maybeShow();
52 }
56 }
53
57
54 function showLastChance() {
58 function showLastChance() {
59+ /* TODO: when we finish support for resetting device after too many
60+ failed logins, we should re-add this popup.
55 var title = lockscreen.alphaNumeric ?
61 var title = lockscreen.alphaNumeric ?
56 i18n.tr("Sorry, incorrect passphrase.") :
62 i18n.tr("Sorry, incorrect passphrase.") :
57 i18n.tr("Sorry, incorrect passcode.");
63 i18n.tr("Sorry, incorrect passcode.");
@@ -60,6 +66,7 @@ FocusScope {
60 i18n.tr("If passphrase is entered incorrectly, your phone will conduct a factory reset and all personal data will be deleted.") :
66 i18n.tr("If passphrase is entered incorrectly, your phone will conduct a factory reset and all personal data will be deleted.") :
61 i18n.tr("If passcode is entered incorrectly, your phone will conduct a factory reset and all personal data will be deleted."));
67 i18n.tr("If passcode is entered incorrectly, your phone will conduct a factory reset and all personal data will be deleted."));
62 lockscreen.showInfoPopup(title, text);
68 lockscreen.showInfoPopup(title, text);
69+ */
63 }
70 }
64
71
65 function hide() {
72 function hide() {
@@ -68,27 +75,24 @@ FocusScope {
68 }
75 }
69
76
70 function notifyAuthenticationSucceeded(showFakePassword) {
77 function notifyAuthenticationSucceeded(showFakePassword) {
71− // When using an alternate log in mechanism like fingerprints, the
72− // design is it looks like the user entered a passcode.
73− if (!alphanumeric && showFakePassword) {
78+ if (showFakePassword) {
74− lockscreen.showText("...."); // actual text doesn't matter, we show bullets
79+ loginList.showFakePassword();
75 }
80 }
76 }
81 }
77
82
78 function notifyAuthenticationFailed() {
83 function notifyAuthenticationFailed() {
79− lockscreen.customError = "";
84+ loginList.showError();
80− lockscreen.clear(true);
81 }
85 }
82
86
83 function showErrorMessage(msg) {
87 function showErrorMessage(msg) {
84 coverPage.showErrorMessage(msg);
88 coverPage.showErrorMessage(msg);
85− lockscreen.customError = msg ? msg : " "; // avoid default message
86− lockscreen.clear(true);
87 }
89 }
88
90
89− function reset() {
91+ function reset(forceShow) {
90− lockscreen.customError = "";
92+ loginList.reset();
93+ if (forceShow) {
91− coverPage.show();
94+ coverPage.show();
95+ }
92 }
96 }
93
97
94 function tryToUnlock(toTheRight) {
98 function tryToUnlock(toTheRight) {
@@ -110,48 +114,62 @@ FocusScope {
110 }
114 }
111 }
115 }
112
116
113− Lockscreen {
117+ Showable {
114 id: lockscreen
118 id: lockscreen
115 objectName: "lockscreen"
119 objectName: "lockscreen"
116−
120+ anchors.fill: parent
117 shown: false
121 shown: false
122+
118 showAnimation: StandardAnimation { property: "opacity"; to: 1 }
123 showAnimation: StandardAnimation { property: "opacity"; to: 1 }
119 hideAnimation: StandardAnimation { property: "opacity"; to: 0 }
124 hideAnimation: StandardAnimation { property: "opacity"; to: 0 }
125+
126+ CrossFadeImage {
127+ id: lockscreenBackground
128+ objectName: "lockscreenBackground"
129+ anchors {
120− anchors.fill: parent
130+ fill: parent
121− visible: required
131+ topMargin: root.backgroundTopMargin
122− enabled: !coverPage.shown
123− background: root.background
124− darkenBackground: 0.4
125− alphaNumeric: root.alphanumeric
126− minPinLength: 4
127− maxPinLength: 4
128−
129− property string promptText
130− infoText: promptText !== "" ? i18n.tr("Enter %1").arg(promptText) :
131− alphaNumeric ? i18n.tr("Enter passphrase") :
132− i18n.tr("Enter passcode")
133−
134− property string customError
135− errorText: customError !== "" ? customError :
136− promptText !== "" ? i18n.tr("Sorry, incorrect %1").arg(promptText) :
137− alphaNumeric ? i18n.tr("Sorry, incorrect passphrase") + "\n" +
138− i18n.ctr("passphrase", "Please re-enter") :
139− i18n.tr("Sorry, incorrect passcode")
140−
141− onEntered: root.responded(passphrase)
142− onCancel: coverPage.show()
143− onEmergencyCall: root.emergencyCall()
144−
145− onEnabledChanged: {
146− if (enabled) {
147− lockscreen.forceActiveFocus();
148 }
132 }
133+ source: root.background
134+ fillMode: Image.PreserveAspectCrop
135+ // Limit how much memory we'll reserve for this image
136+ sourceSize.height: Math.max(Screen.width, Screen.height)
137+ sourceSize.width: 0
149 }
138 }
150
139
151− onVisibleChanged: {
140+ // Darken background to match CoverPage
152− if (visible) {
141+ Rectangle {
153− lockscreen.forceActiveFocus();
142+ anchors.fill: parent
143+ color: "black"
144+ opacity: 0.4
145+ }
146+
147+ LoginList {
148+ id: loginList
149+ objectName: "loginList"
150+
151+ anchors {
152+ horizontalCenter: parent.horizontalCenter
153+ top: parent.top
154+ bottom: parent.bottom
154 }
155 }
156+ width: units.gu(40)
157+ boxVerticalOffset: units.gu(14)
158+ enabled: !coverPage.shown && visible
159+ visible: !delayedLockscreen.visible
160+
161+ locked: root.locked
162+
163+ onSelected: if (enabled) root.selected(index)
164+ onResponded: root.responded(response)
165+ }
166+
167+ DelayedLockscreen {
168+ id: delayedLockscreen
169+ objectName: "delayedLockscreen"
170+ anchors.fill: parent
171+ visible: delayMinutes > 0
172+ alphaNumeric: loginList.alphanumeric
155 }
173 }
156
174
157 function maybeShow() {
175 function maybeShow() {
@@ -179,15 +197,9 @@ FocusScope {
179
197
180 onShowProgressChanged: {
198 onShowProgressChanged: {
181 if (showProgress === 1) {
199 if (showProgress === 1) {
182− lockscreen.reset();
200+ loginList.reset();
183− }
184−
185− if (showProgress === 0) {
201+ } else if (showProgress === 0) {
186− if (root.locked) {
202+ loginList.tryToUnlock();
187− lockscreen.clear(false); // to reset focus if necessary
188− } else {
189− root.responded("");
190− }
191 }
203 }
192 }
204 }
193
205
@@ -199,4 +211,78 @@ FocusScope {
199 }
211 }
200 }
212 }
201 }
213 }
214+
215+ StyledItem {
216+ id: bottomBar
217+ visible: lockscreen.shown
218+ height: units.gu(4)
219+
220+ anchors.left: parent.left
221+ anchors.right: parent.right
222+ anchors.top: parent.bottom
223+ anchors.topMargin: - height * (1 - coverPage.showProgress)
224+ - (inputMethod && inputMethod.visible ?
225+ inputMethod.keyboardRectangle.height : 0)
226+
227+ Rectangle {
228+ color: UbuntuColors.porcelain // matches OSK background
229+ anchors.fill: parent
230+ }
231+
232+ Label {
233+ text: i18n.tr("Cancel")
234+ anchors.left: parent.left
235+ anchors.leftMargin: units.gu(2)
236+ anchors.top: parent.top
237+ anchors.bottom: parent.bottom
238+ verticalAlignment: Text.AlignVCenter
239+ font.weight: Font.Light
240+ fontSize: "small"
241+ color: UbuntuColors.slate
242+
243+ AbstractButton {
244+ anchors.fill: parent
245+ anchors.leftMargin: -units.gu(2)
246+ anchors.rightMargin: -units.gu(2)
247+ onClicked: coverPage.show()
248+ }
249+ }
250+
251+ Label {
252+ objectName: "emergencyCallLabel"
253+ text: callManager.hasCalls ? i18n.tr("Return to Call") : i18n.tr("Emergency")
254+ anchors.right: parent.right
255+ anchors.rightMargin: units.gu(2)
256+ anchors.top: parent.top
257+ anchors.bottom: parent.bottom
258+ verticalAlignment: Text.AlignVCenter
259+ font.weight: Font.Light
260+ fontSize: "small"
261+ color: UbuntuColors.slate
262+ // TODO: uncomment once bug 1616538 is fixed
263+ // visible: telepathyHelper.ready && telepathyHelper.emergencyCallsAvailable
264+ enabled: visible
265+
266+ AbstractButton {
267+ anchors.fill: parent
268+ anchors.leftMargin: -units.gu(2)
269+ anchors.rightMargin: -units.gu(2)
270+ onClicked: root.emergencyCall()
271+ }
272+ }
273+ }
274+
275+ // FIXME: It's difficult to keep something tied closely to the OSK (bug
276+ // 1616163). But as a hack to avoid the background peeking out,
277+ // we add an extra Rectangle that just serves to hide the background
278+ // during OSK animations.
279+ Rectangle {
280+ visible: bottomBar.visible
281+ height: inputMethod && inputMethod.visible ?
282+ inputMethod.keyboardRectangle.height : 0
283+ anchors.bottom: parent.bottom
284+ anchors.left: parent.left
285+ anchors.right: parent.right
286+ color: UbuntuColors.porcelain
287+ }
202}
288}
qml/Greeter/WideView.qml+11−5
@@ -51,7 +51,7 @@ FocusScope {
51 loginList.showError();
51 loginList.showError();
52 }
52 }
53
53
54− function reset() {
54+ function reset(forceShow) {
55 loginList.reset();
55 loginList.reset();
56 }
56 }
57
57
@@ -83,8 +83,10 @@ FocusScope {
83 coverPage.hide();
83 coverPage.hide();
84 }
84 }
85
85
86− function notifyAuthenticationSucceeded() {
86+ function notifyAuthenticationSucceeded(showFakePassword) {
87− // Nothing needed
87+ if (showFakePassword) {
88+ loginList.showFakePassword();
89+ }
88 }
90 }
89
91
90 function showLastChance() {
92 function showLastChance() {
@@ -122,15 +124,19 @@ FocusScope {
122 id: loginList
124 id: loginList
123 objectName: "loginList"
125 objectName: "loginList"
124
126
125− height: inputMethod && inputMethod.visible ?
126− parent.height - inputMethod.keyboardRectangle.height : parent.height
127 width: units.gu(40)
127 width: units.gu(40)
128 anchors {
128 anchors {
129 left: parent.left
129 left: parent.left
130 leftMargin: Math.min(parent.width * 0.16, units.gu(20))
130 leftMargin: Math.min(parent.width * 0.16, units.gu(20))
131 top: parent.top
131 top: parent.top
132+ bottom: parent.bottom
132 }
133 }
133
134
135+ boxVerticalOffset: (height - highlightedHeight -
136+ (inputMethod && inputMethod.visible ?
137+ inputMethod.keyboardRectangle.height : 0)) / 2
138+ Behavior on boxVerticalOffset { UbuntuNumberAnimation {} }
139+
134 model: root.userModel
140 model: root.userModel
135 currentSession: LightDMService.greeter.defaultSession
141 currentSession: LightDMService.greeter.defaultSession
136 onResponded: root.responded(response)
142 onResponded: root.responded(response)
tests/mocks/Ubuntu/Telephony/MockTelepathyHelper.cpp+27
@@ -20,6 +20,8 @@
20
20
21MockTelepathyHelper::MockTelepathyHelper(QObject *parent)
21MockTelepathyHelper::MockTelepathyHelper(QObject *parent)
22 : QObject(parent)
22 : QObject(parent)
23+ , m_ready(true)
24+ , m_emergencyCallsAvailable(true)
23{
25{
24}
26}
25
27
@@ -33,3 +35,28 @@ void MockTelepathyHelper::registerChannelObserver(const QString& name)
33{
35{
34 Q_UNUSED(name);
36 Q_UNUSED(name);
35}
37}
38+
39+bool MockTelepathyHelper::ready() const
40+{
41+ return m_ready;
42+}
43+
44+void MockTelepathyHelper::setReady(bool value)
45+{
46+ if (m_ready != value) {
47+ m_ready = value;
48+ Q_EMIT readyChanged();
49+ }
50+}
51+bool MockTelepathyHelper::emergencyCallsAvailable() const
52+{
53+ return m_emergencyCallsAvailable;
54+}
55+
56+void MockTelepathyHelper::setEmergencyCallsAvailable(bool value)
57+{
58+ if (m_emergencyCallsAvailable != value) {
59+ m_emergencyCallsAvailable = value;
60+ Q_EMIT emergencyCallsAvailableChanged();
61+ }
62+}
tests/mocks/Ubuntu/Telephony/MockTelepathyHelper.h+22
@@ -24,6 +24,14 @@
24class MockTelepathyHelper : public QObject
24class MockTelepathyHelper : public QObject
25{
25{
26 Q_OBJECT
26 Q_OBJECT
27+ Q_PROPERTY(bool ready
28+ READ ready
29+ WRITE setReady // only in mock
30+ NOTIFY readyChanged)
31+ Q_PROPERTY(bool emergencyCallsAvailable
32+ READ emergencyCallsAvailable
33+ WRITE setEmergencyCallsAvailable // only in mock
34+ NOTIFY emergencyCallsAvailableChanged)
27 Q_DISABLE_COPY(MockTelepathyHelper)
35 Q_DISABLE_COPY(MockTelepathyHelper)
28public:
36public:
29 MockTelepathyHelper(QObject *parent = 0);
37 MockTelepathyHelper(QObject *parent = 0);
@@ -31,6 +39,20 @@ public:
31 static MockTelepathyHelper *instance();
39 static MockTelepathyHelper *instance();
32
40
33 Q_INVOKABLE void registerChannelObserver(const QString& name);
41 Q_INVOKABLE void registerChannelObserver(const QString& name);
42+
43+ bool ready() const;
44+ void setReady(bool value);
45+
46+ bool emergencyCallsAvailable() const;
47+ void setEmergencyCallsAvailable(bool value);
48+
49+Q_SIGNALS:
50+ void readyChanged();
51+ void emergencyCallsAvailableChanged();
52+
53+private:
54+ bool m_ready;
55+ bool m_emergencyCallsAvailable;
34};
56};
35
57
36#endif // MOCKCONTACTWATCHER_H
58#endif // MOCKCONTACTWATCHER_H
tests/qmltests/Components/tst_Lockscreen.qml−38
@@ -37,7 +37,6 @@ Rectangle {
37 alphaNumeric: pinPadCheckBox.checked
37 alphaNumeric: pinPadCheckBox.checked
38 minPinLength: minPinLengthTextField.text
38 minPinLength: minPinLengthTextField.text
39 maxPinLength: maxPinLengthTextField.text
39 maxPinLength: maxPinLengthTextField.text
40− delayMinutes: delayMinutesTextField.text
41 background: "../../../qml/graphics/phone_background.jpg"
40 background: "../../../qml/graphics/phone_background.jpg"
42 }
41 }
43
42
@@ -109,16 +108,6 @@ Rectangle {
109 text: "Retries left"
108 text: "Retries left"
110 }
109 }
111 }
110 }
112− Row {
113− TextField {
114− id: delayMinutesTextField
115− width: units.gu(7)
116− text: "0"
117− }
118− Label {
119− text: "Delay Minutes"
120− }
121− }
122 Label {
111 Label {
123 id: pinLabel
112 id: pinLabel
124 anchors.verticalCenter: parent.verticalCenter
113 anchors.verticalCenter: parent.verticalCenter
@@ -172,7 +161,6 @@ Rectangle {
172
161
173 function cleanup() {
162 function cleanup() {
174 lockscreen.clear(false);
163 lockscreen.clear(false);
175− delayMinutesTextField.text = "0"
176 enteredLabel.text = "";
164 enteredLabel.text = "";
177
165
178 // Reset sizing
166 // Reset sizing
@@ -455,32 +443,6 @@ Rectangle {
455 compare(label.text, data.text);
443 compare(label.text, data.text);
456 }
444 }
457
445
458− function test_delayMinutes() {
459− delayMinutesTextField.text = "4"
460− waitForLockscreenReady()
461− var label = findChild(lockscreen, "deviceLockedLabel")
462− compare(label.text, "Device Locked")
463− }
464−
465− function test_showText_data() {
466− return [
467− { tag: "alphanumeric", alphanumeric: true },
468− { tag: "pinPad", alphanumeric: false },
469− ]
470− }
471−
472− function test_showText(data) {
473− pinPadCheckBox.checked = data.alphanumeric;
474− waitForLockscreenReady();
475−
476− lockscreen.showText("test");
477−
478− var pinPadLoader = findChild(lockscreen, "pinPadLoader");
479− verify(pinPadLoader.waiting);
480− compare(enteredLabel.text, ""); // no entered signal should occur
481− compare(lockscreen.passphrase, "test");
482− }
483−
484 function test_resize_data() {
446 function test_resize_data() {
485 return [
447 return [
486 { tag: "small", width: units.gu(40), height: units.gu(76) },
448 { tag: "small", width: units.gu(40), height: units.gu(76) },
tests/qmltests/Greeter/TestView.qml+3−3
@@ -51,7 +51,7 @@ Item {
51 signal _notifyAuthenticationSucceededCalled(bool showFakePassword)
51 signal _notifyAuthenticationSucceededCalled(bool showFakePassword)
52 signal _notifyAuthenticationFailedCalled()
52 signal _notifyAuthenticationFailedCalled()
53 signal _showErrorMessageCalled(string msg)
53 signal _showErrorMessageCalled(string msg)
54− signal _resetCalled()
54+ signal _resetCalled(bool forceShow)
55 signal _tryToUnlockCalled(bool toTheRight)
55 signal _tryToUnlockCalled(bool toTheRight)
56
56
57 function showMessage(html) {
57 function showMessage(html) {
@@ -84,8 +84,8 @@ Item {
84 _showErrorMessageCalled(msg);
84 _showErrorMessageCalled(msg);
85 }
85 }
86
86
87− function reset() {
87+ function reset(forceShow) {
88− _resetCalled();
88+ _resetCalled(forceShow);
89 }
89 }
90
90
91 function tryToUnlock(toTheRight) {
91 function tryToUnlock(toTheRight) {
tests/qmltests/Greeter/tst_Greeter.qml+1
@@ -559,6 +559,7 @@ Item {
559
559
560 LightDM.Greeter.showGreeter();
560 LightDM.Greeter.showGreeter();
561 compare(viewResetSpy.count, 1);
561 compare(viewResetSpy.count, 1);
562+ compare(viewResetSpy.signalArguments[0][0], true);
562 tryCompare(viewShowPromptSpy, "count", 1);
563 tryCompare(viewShowPromptSpy, "count", 1);
563 }
564 }
564
565
tests/qmltests/Greeter/tst_NarrowView.qml+34−11
@@ -20,6 +20,7 @@ import ".."
20import "../../../qml/Greeter"
20import "../../../qml/Greeter"
21import LightDM.IntegratedLightDM 0.1 as LightDM
21import LightDM.IntegratedLightDM 0.1 as LightDM
22import Ubuntu.Components 1.3
22import Ubuntu.Components 1.3
23+import Ubuntu.Telephony 0.1 as Telephony
23import Unity.Test 0.1 as UT
24import Unity.Test 0.1 as UT
24
25
25Item {
26Item {
@@ -293,6 +294,8 @@ Item {
293 function init() {
294 function init() {
294 view.currentIndex = 0; // break binding with text field
295 view.currentIndex = 0; // break binding with text field
295
296
297+ telepathyHelper.ready = true;
298+ telepathyHelper.emergencyCallsAvailable = true;
296 selectedSpy.clear();
299 selectedSpy.clear();
297 respondedSpy.clear();
300 respondedSpy.clear();
298 teaseSpy.clear();
301 teaseSpy.clear();
@@ -328,14 +331,6 @@ Item {
328 waitForRendering(view);
331 waitForRendering(view);
329 }
332 }
330
333
331− function enterPin(pin) {
332− for (var i = 0; i < pin.length; ++i) {
333− var character = pin.charAt(i);
334− var button = findChild(view, "pinPadButton" + character);
335− tap(button);
336− }
337− }
338−
339 function test_tease_data() {
334 function test_tease_data() {
340 return [
335 return [
341 {tag: "left", x: 0, offset: 0, count: 1},
336 {tag: "left", x: 0, offset: 0, count: 1},
@@ -352,8 +347,9 @@ Item {
352
347
353 function test_respondedWithPin() {
348 function test_respondedWithPin() {
354 view.locked = true;
349 view.locked = true;
350+ view.showPrompt("", true, true);
355 swipeAwayCover();
351 swipeAwayCover();
356− enterPin("1234");
352+ typeString("1234");
357 compare(respondedSpy.count, 1);
353 compare(respondedSpy.count, 1);
358 compare(respondedSpy.signalArguments[0][0], "1234");
354 compare(respondedSpy.signalArguments[0][0], "1234");
359 }
355 }
@@ -361,6 +357,7 @@ Item {
361 function test_respondedWithPassphrase() {
357 function test_respondedWithPassphrase() {
362 view.locked = true;
358 view.locked = true;
363 view.alphanumeric = true;
359 view.alphanumeric = true;
360+ view.showPrompt("", true, true);
364 swipeAwayCover();
361 swipeAwayCover();
365 typeString("test");
362 typeString("test");
366 keyClick(Qt.Key_Enter);
363 keyClick(Qt.Key_Enter);
@@ -382,12 +379,38 @@ Item {
382 compare(respondedSpy.signalArguments[0][0], "");
379 compare(respondedSpy.signalArguments[0][0], "");
383 }
380 }
384
381
382+ function test_emergencyCall_data() {
383+ return [
384+ {tag: "phone", available: true},
385+ {tag: "desktop", available: false},
386+ ];
387+ }
385− function test_emergencyCall() {
388+ function test_emergencyCall(data) {
389+ telepathyHelper.emergencyCallsAvailable = data.available;
386 view.locked = true;
390 view.locked = true;
387 swipeAwayCover();
391 swipeAwayCover();
388 var emergencyCallLabel = findChild(view, "emergencyCallLabel");
392 var emergencyCallLabel = findChild(view, "emergencyCallLabel");
389 tap(emergencyCallLabel);
393 tap(emergencyCallLabel);
394+ if (!data.available) {
395+ expectFail("", "Bug 1616538 prevents us supporting conditional emergency button support");
396+ }
397+ compare(emergencyCallLabel.visible, data.available ? true : false);
390− compare(emergencySpy.count, 1);
398+ compare(emergencySpy.count, data.available ? 1 : 0);
399+ }
400+
401+ function test_emergencyCallAvailability() {
402+ view.locked = true;
403+ var emergencyCallLabel = findChild(view, "emergencyCallLabel");
404+ verify(emergencyCallLabel.visible);
405+
406+ telepathyHelper.emergencyCallsAvailable = false;
407+ telepathyHelper.ready = true;
408+ expectFail("", "Bug 1616538 prevents us supporting conditional emergency button support");
409+ verify(!emergencyCallLabel.visible);
410+
411+ telepathyHelper.emergencyCallsAvailable = true;
412+ telepathyHelper.ready = false;
413+ verify(!emergencyCallLabel.visible);
391 }
414 }
392
415
393 function test_fullyShown() {
416 function test_fullyShown() {
tests/qmltests/Greeter/tst_WideView.qml+8−4
@@ -641,17 +641,21 @@ StyledItem {
641
641
642 keyboardVisibleCheckBox.checked = true;
642 keyboardVisibleCheckBox.checked = true;
643
643
644+ var halfway = (view.height - loginList.highlightedHeight) / 2;
644− tryCompare(loginList, "height", view.height - view.inputMethod.keyboardRectangle.height);
645+ var halfwayWithOsk = halfway - view.inputMethod.keyboardRectangle.height / 2;
646+ tryCompare(loginList, "boxVerticalOffset", halfwayWithOsk);
647+
648+ var highlightItem = findChild(loginList, "highlightItem");
645 tryCompareFunction( function() {
649 tryCompareFunction( function() {
646− var loginListRect = loginList.mapToItem(view, 0, 0, loginList.width, loginList.height);
650+ var highlightRect = highlightItem.mapToItem(view, 0, 0, highlightItem.width, highlightItem.height);
647− return loginListRect.y + loginListRect.height <= view.inputMethod.keyboardRectangle.y;
651+ return highlightRect.y + highlightRect.height <= view.inputMethod.keyboardRectangle.y;
648 }, true);
652 }, true);
649
653
650 // once the vkb goes away, loginList goes back to its full height
654 // once the vkb goes away, loginList goes back to its full height
651
655
652 keyboardVisibleCheckBox.checked = false;
656 keyboardVisibleCheckBox.checked = false;
653
657
654− tryCompare(loginList, "height", view.height);
658+ tryCompare(loginList, "boxVerticalOffset", halfway);
655 }
659 }
656
660
657 function test_passphrase() {
661 function test_passphrase() {
tests/qmltests/tst_ShellWithPin.qml+28−39
@@ -154,7 +154,6 @@ Item {
154 var greeter = findChild(shell, "greeter");
154 var greeter = findChild(shell, "greeter");
155 sessionSpy.target = greeter;
155 sessionSpy.target = greeter;
156 swipeAwayGreeter(true);
156 swipeAwayGreeter(true);
157− waitForLockscreen()
158 greeter.failedLoginsDelayAttempts = -1;
157 greeter.failedLoginsDelayAttempts = -1;
159 greeter.maxFailedLogins = -1;
158 greeter.maxFailedLogins = -1;
160
159
@@ -214,20 +213,16 @@ Item {
214 }
213 }
215 }
214 }
216
215
217− function waitForLockscreen() {
216+ function enterPin(pin) {
218− var lockscreen = findChild(shell, "lockscreen");
217+ typeString(pin);
219− var pinPadLoader = findChild(lockscreen, "pinPadLoader");
220− tryCompare(pinPadLoader, "status", Loader.Ready)
221− waitForRendering(lockscreen)
222 }
218 }
223
219
224− function enterPin(pin) {
220+ function showGreeter() {
225− for (var i = 0; i < pin.length; ++i) {
221+ LightDM.Greeter.showGreeter();
226− var character = pin.charAt(i)
222+ tryCompare(shell, "waitingOnGreeter", false);
227− var button = findChild(shell, "pinPadButton" + character)
223+ var coverPage = findChild(shell, "coverPage");
228− tryCompare(button, "enabled", true);
224+ tryCompare(coverPage, "showProgress", 1);
229− tap(button)
225+ removeTimeConstraintsFromSwipeAreas(shell);
230− }
231 }
226 }
232
227
233 function confirmLockedApp(app) {
228 function confirmLockedApp(app) {
@@ -248,7 +243,7 @@ Item {
248 LightDM.Greeter.hideGreeter();
243 LightDM.Greeter.hideGreeter();
249 tryCompare(panel.indicators.indicatorsModel, "profile", shell.indicatorProfile);
244 tryCompare(panel.indicators.indicatorsModel, "profile", shell.indicatorProfile);
250
245
251− LightDM.Greeter.showGreeter();
246+ showGreeter();
252 tryCompare(panel.indicators.indicatorsModel, "profile", shell.indicatorProfile + "_greeter");
247 tryCompare(panel.indicators.indicatorsModel, "profile", shell.indicatorProfile + "_greeter");
253
248
254 LightDM.Greeter.hideGreeter();
249 LightDM.Greeter.hideGreeter();
@@ -293,7 +288,7 @@ Item {
293
288
294 // Cancel emergency mode, and go back to normal
289 // Cancel emergency mode, and go back to normal
295 waitForRendering(greeter)
290 waitForRendering(greeter)
296− LightDM.Greeter.showGreeter()
291+ showGreeter()
297
292
298 tryCompare(greeter, "shown", true)
293 tryCompare(greeter, "shown", true)
299 tryCompare(greeter, "lockedApp", "")
294 tryCompare(greeter, "lockedApp", "")
@@ -336,7 +331,7 @@ Item {
336 enterPin("1234");
331 enterPin("1234");
337 tryCompare(tutorial, "paused", false);
332 tryCompare(tutorial, "paused", false);
338
333
339− LightDM.Greeter.showGreeter();
334+ showGreeter();
340 verify(tutorial.paused);
335 verify(tutorial.paused);
341
336
342 swipeAwayGreeter(true);
337 swipeAwayGreeter(true);
@@ -358,22 +353,23 @@ Item {
358 var greeter = findChild(shell, "greeter");
353 var greeter = findChild(shell, "greeter");
359 greeter.failedLoginsDelayAttempts = 3;
354 greeter.failedLoginsDelayAttempts = 3;
360
355
361− var placeHolder = findChild(shell, "wrongNoticeLabel")
356+ var wrongPasswordAnimation = findInvisibleChild(shell, "wrongPasswordAnimation");
362− tryCompare(placeHolder, "text", "")
363
357
364 enterPin("1111")
358 enterPin("1111")
365− tryCompare(placeHolder, "text", "Sorry, incorrect passcode")
359+ verify(wrongPasswordAnimation.running);
366
360
367 enterPin("1111")
361 enterPin("1111")
368− tryCompare(placeHolder, "text", "Sorry, incorrect passcode")
362+ verify(wrongPasswordAnimation.running);
369
363
370− var lockscreen = findChild(shell, "lockscreen")
364+ var delayedLockscreen = findChild(shell, "delayedLockscreen");
371− tryCompare(lockscreen, "delayMinutes", 0)
365+ tryCompare(delayedLockscreen, "delayMinutes", 0);
372 enterPin("1111")
366 enterPin("1111")
373− tryCompare(lockscreen, "delayMinutes", greeter.failedLoginsDelayMinutes);
367+ tryCompare(delayedLockscreen, "delayMinutes", greeter.failedLoginsDelayMinutes);
374 }
368 }
375
369
376 function test_factoryReset() {
370 function test_factoryReset() {
371+ skip("Factory reset support is not finished")
372+
377 maxRetriesTextField.text = "3"
373 maxRetriesTextField.text = "3"
378 resetSpy.clear()
374 resetSpy.clear()
379
375
@@ -404,8 +400,7 @@ Item {
404 compare(shell.usageScenario, "phone");
400 compare(shell.usageScenario, "phone");
405 compare(applicationsDisplayLoader.usageScenario, "phone");
401 compare(applicationsDisplayLoader.usageScenario, "phone");
406
402
407− var lockscreen = findChild(shell, "lockscreen")
403+ tap(findChild(shell, "emergencyCallLabel"));
408− lockscreen.emergencyCall()
409 confirmLockedApp("dialer-app")
404 confirmLockedApp("dialer-app")
410
405
411 // OK, we're in. Now try (but fail) to switch to tablet mode
406 // OK, we're in. Now try (but fail) to switch to tablet mode
@@ -432,16 +427,13 @@ Item {
432 // - Should be back in emergency mode dialer
427 // - Should be back in emergency mode dialer
433
428
434 var greeter = findChild(shell, "greeter");
429 var greeter = findChild(shell, "greeter");
435− var lockscreen = findChild(shell, "lockscreen");
436− verify(lockscreen);
437
430
438− lockscreen.emergencyCall();
431+ tap(findChild(shell, "emergencyCallLabel"));
439 confirmLockedApp("dialer-app");
432 confirmLockedApp("dialer-app");
440 callManager.foregroundCall = phoneCall;
433 callManager.foregroundCall = phoneCall;
441
434
442− LightDM.Greeter.showGreeter();
435+ showGreeter();
443− lockscreen = findChild(shell, "lockscreen");
436+ var lockscreen = findChild(shell, "lockscreen");
444− verify(lockscreen);
445 tryCompare(lockscreen, "shown", true);
437 tryCompare(lockscreen, "shown", true);
446 tryCompare(greeter, "hasLockedApp", false);
438 tryCompare(greeter, "hasLockedApp", false);
447
439
@@ -484,7 +476,7 @@ Item {
484 }
476 }
485
477
486 function test_focusRequestedHidesCoverPage() {
478 function test_focusRequestedHidesCoverPage() {
487− LightDM.Greeter.showGreeter();
479+ showGreeter();
488
480
489 var app = ApplicationManager.startApplication("gallery-app");
481 var app = ApplicationManager.startApplication("gallery-app");
490 // wait until the app is fully loaded (ie, real surface replaces splash screen)
482 // wait until the app is fully loaded (ie, real surface replaces splash screen)
@@ -496,8 +488,7 @@ Item {
496 tryCompare(coverPage, "showProgress", 0);
488 tryCompare(coverPage, "showProgress", 0);
497 tryCompare(greeter, "fullyShown", true);
489 tryCompare(greeter, "fullyShown", true);
498
490
499− LightDM.Greeter.showGreeter();
491+ showGreeter();
500− tryCompare(coverPage, "showProgress", 1);
501
492
502 // Make sure focusing same app triggers same behavior
493 // Make sure focusing same app triggers same behavior
503 ApplicationManager.requestFocusApplication("gallery-app");
494 ApplicationManager.requestFocusApplication("gallery-app");
@@ -571,9 +562,7 @@ Item {
571 only after its idle timeout is triggered.
562 only after its idle timeout is triggered.
572 */
563 */
573 function test_shortLeftEdgeSwipeMakesLauncherStayVisible() {
564 function test_shortLeftEdgeSwipeMakesLauncherStayVisible() {
574− LightDM.Greeter.showGreeter();
565+ showGreeter();
575− var coverPage = testCase.findChild(shell, "coverPage");
576− tryCompare(coverPage, "showProgress", 1);
577
566
578 var launcher = testCase.findChild(shell, "launcher")
567 var launcher = testCase.findChild(shell, "launcher")
579 var launcherPanel = testCase.findChild(launcher, "launcherPanel");
568 var launcherPanel = testCase.findChild(launcher, "launcherPanel");
@@ -589,6 +578,7 @@ Item {
589 tryCompare(launcherPanel, "x", 0);
578 tryCompare(launcherPanel, "x", 0);
590
579
591 // Greeter should be displaced
580 // Greeter should be displaced
581+ var coverPage = findChild(shell, "coverPage");
592 tryCompareFunction(function() { return coverPage.mapToItem(shell, 0, 0).x > shell.width*0.2; }, true);
582 tryCompareFunction(function() { return coverPage.mapToItem(shell, 0, 0).x > shell.width*0.2; }, true);
593
583
594 touchRelease(shell, toX, shell.height * 0.5);
584 touchRelease(shell, toX, shell.height * 0.5);
@@ -611,8 +601,7 @@ Item {
611 tryCompare(shell, "mainApp", galleryApp);
601 tryCompare(shell, "mainApp", galleryApp);
612
602
613 // Show greeter
603 // Show greeter
614− LightDM.Greeter.showGreeter();
604+ showGreeter();
615− tryCompare(coverPage, "showProgress", 1);
616
605
617 // Swipe cover page away
606 // Swipe cover page away
618 touchFlick(shell, 2, shell.height / 2, units.gu(30), shell.height / 2);
607 touchFlick(shell, 2, shell.height / 2, units.gu(30), shell.height / 2);