Merge lp:~mterry/unity8/greeter-focus into lp:unity8
- greeter-focus
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Daniel d'Andrada |
Approved revision: | 2007 |
Merged at revision: | 2540 |
Proposed branch: | lp:~mterry/unity8/greeter-focus |
Merge into: | lp:unity8 |
Prerequisite: | lp:~mterry/unity8/greeter-hide-indicators |
Diff against target: |
880 lines (+249/-98) 14 files modified
qml/Greeter/Greeter.qml (+28/-24) qml/Greeter/GreeterPrompt.qml (+68/-13) qml/Greeter/LoginList.qml (+27/-16) qml/Greeter/NarrowView.qml (+2/-1) qml/Greeter/WideView.qml (+5/-4) qml/Shell.qml (+5/-3) tests/qmltests/Dash/tst_DashShell.qml (+6/-0) tests/qmltests/Greeter/TestView.qml (+0/-1) tests/qmltests/Greeter/tst_Greeter.qml (+3/-13) tests/qmltests/Greeter/tst_WideView.qml (+92/-12) tests/qmltests/Tutorial/tst_Tutorial.qml (+1/-1) tests/qmltests/tst_OrientedShell.qml (+2/-2) tests/qmltests/tst_Shell.qml (+3/-3) tests/qmltests/tst_ShellWithPin.qml (+7/-5) |
To merge this branch: | bzr merge lp:~mterry/unity8/greeter-focus |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Unity8 CI Bot | continuous-integration | Needs Fixing | |
Daniel d'Andrada (community) | Approve | ||
Review via email: mp+299345@code.launchpad.net |
This proposal supersedes a proposal from 2016-06-30.
Commit message
Fix tablet greeter focus to be always-on, no longer hiding the OSK or forcing a mouse click to type a password.
I've also squeezed some other small fixes in:
- Support Up and Down keys in user list.
- Don't accept non-digit characters when prompting for passcode (we ask OSK to show only digits, but due to bug 1586435, it shows other characters too; plus if the user has an external keyboard, they can type anything anyway).
- When prompting for a passcode in wide-view (tablet/desktop), stop at 4 digits just like we do in narrow-view.
- Don't show "Retry" during brief period before a prompt comes in from PAM.
- Don't let user drag user list if there's only one entry.
Now as for the focus changes...
One of the big reasons we lost keyboard focus before was because we set the shell to disabled whenever the greeter was "between PAM events" -- mostly so that the user can't swipe away greeter before we get our first prompt or are otherwise unsure about exactly what authentication is needed.
But disabled qml items can't be focused. So I've rejiggered things a bit. Instead of disabling the whole shell, I just disable the launcher, the indicators, and make the greeter non-swipeable.
I also do some tricks with the prompt so that it looks disabled (while we check with PAM about the password) but isn't actually. I don't want to make it look to the user that pressing backspace while they wait for PAM does anything, so after the user presses Enter, I present a fake label on top of the prompt that looks like a disabled prompt, while simultaneously hiding the prompt contents.
Description of the change
You could mostly just test this on your desktop. Changes are all to the wide-view side of things.
* Are there any related MPs required for this MP to build/function as expected? Please list.
No
* Did you perform an exploratory manual test run of your code change and any related functionality?
Yes
* If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
NA
* If you changed the UI, has there been a design review?
NA
Michael Terry (mterry) wrote : Posted in a previous version of this proposal | # |
Michael Terry (mterry) wrote : Posted in a previous version of this proposal | # |
OK, tests added.
Unity8 CI Bot (unity8-ci-bot) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:2496
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:2497
https:/
Executed test runs:
SUCCESS: https:/
FAILURE: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:2498
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1999
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal | # |
"""
+ // Oddly, a simple "focus: visible" does not stick -- the binding
187 + // gets lost when switching between buttons and prompts. But this
188 + // explicit binding does work.
189 + Binding on focus {
190 + value: passwordInput.
191 + }
"""
It doesn't stick because the focus property gets written directly by someone else. So your biding gets overwritten by a direct assigment. A Binding{} element doesn't share this fate since it's kept separately and works differently. Everytime it's value expression gets reevaluated it makes a direct assigment to its target (or so I believe that's how it works).
Overall I think it's a bad practice to have a binding on the focus property. Qt itself may change the focus property of an item at any time as the result of some other item in the same focus scope having focus.
So for focus setting you either have imperative code like this:
onVisibleChanged: {
focus = true;
}
Or better yet, evaluate if adding a FocusScope somewhere in your item hierarchy wouldn't solve that "mystery". As focus changes outside your FocusScope wouldn't change the focus inside it.
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal | # |
"""
Overall I think it's a bad practice to have a binding on the focus property. Qt itself may change the focus property of an item at any time as the result of some other item in the same focus scope having focus.
"""
Let me rephrase that part: It's a bad practice if you don't have full control over the focus scope of that specific item.
Michael Terry (mterry) wrote : Posted in a previous version of this proposal | # |
I adjusted it to be imperative instead of declarative. Thanks for breaking Qt focus down for me here and on IRC. :)
Unity8 CI Bot (unity8-ci-bot) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:2000
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:2001
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2002
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Michael Terry (mterry) wrote : | # |
OK, fixed testSessionBackend. There was a test executable we weren't installing.
Daniel d'Andrada (dandrader) wrote : | # |
Please update copyright headers of:
qml/Greeter/
qml/Greeter/
tests/qmltests/
tests/qmltests/
- 2003. By Michael Terry
-
Update copyrights
Michael Terry (mterry) wrote : | # |
Updated copyrights. (And whoops, my comment above about testSessionBackend was for another MP.)
Daniel d'Andrada (dandrader) wrote : | # |
"""
- Support Up and Down keys in user list.
"""
Not working in "make tryWideView"
- 2004. By Michael Terry
-
Give wideview test focus to start
Michael Terry (mterry) wrote : | # |
Fixed the focus in tryWideView. But you may get more mileage out of tryShell -- you'll see the different kinds of greeter prompts from the get-go. tryWideView makes ("lets") you assemble the prompts manually.
Daniel d'Andrada (dandrader) wrote : | # |
In GreeterPrompt, you're resisting on doing the imperative way. Let it go! :)
First, there's no point in doing "focus = false". When you do "focus = true" somewhere it will already do "focus = false" on whatever item previously had it.
Secondly, you're still binding to the focus property. The binding on the item initially invisible will be immediately broken. The remaining one will be broken the first time you switch from button to text field or vice versa. Getting bindings broken is bad. Leads to misleading code. When you read a "foo: bar" binding in some qml file you never expect it to stop working out of nowhere.
Third. Since focus really works as if it were a single "property" or "variable" per FocusScope, it makes sense to do this focus assignment in a single place, centrally.
QML would be better off if they designed it as a FocusScope.
So, here's my suggestion:
http://
That way you also don't have to explain yourself.
Daniel d'Andrada (dandrader) wrote : | # |
"[..]What we *really* want is a disabled mode that doesn't lose focus.[...]"
Your wishes have been granted. I believe we can use the TextField.readOnly property for that, like this:
http://
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2003
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2004
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Daniel d'Andrada (dandrader) wrote : | # |
In tst_wideView.qml there's no need for the forceActiveFocus() call:
http://
Daniel d'Andrada (dandrader) wrote : | # |
> "[..]What we *really* want is a disabled mode that doesn't lose focus.[...]"
>
> Your wishes have been granted. I believe we can use the TextField.readOnly
> property for that, like this:
> http://
Scrap that. TextField.readOnly gets OSK hidden just like Item.enabled
- 2005. By Michael Terry
-
Merge focus refactor from dandrader
- 2006. By Michael Terry
-
Merge tryWideView focus refactor from dandrader
- 2007. By Michael Terry
-
Make it clear in GreeterPrompt that fakeLabel is for OSK focus
Michael Terry (mterry) wrote : | # |
OK, I've applied your two focus fixes (GreeterPrompt and WideView) and added the word "OSK" to the fakeLabel comment to make it a little clearer that the OSK is the problem.
Daniel d'Andrada (dandrader) wrote : | # |
Thanks.
Looks good to me.
* Did you perform an exploratory manual test run of the code change and any related functionality?
Yes
* Did CI run pass? If not, please explain why.
No. Unrelated failure in qmltestrunner.
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2007
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 2008. By Michael Terry
-
Fix a test
Preview Diff
1 | === modified file 'qml/Greeter/Greeter.qml' |
2 | --- qml/Greeter/Greeter.qml 2016-07-08 20:44:28 +0000 |
3 | +++ qml/Greeter/Greeter.qml 2016-07-08 20:44:29 +0000 |
4 | @@ -1,5 +1,5 @@ |
5 | /* |
6 | - * Copyright (C) 2013,2014,2015 Canonical, Ltd. |
7 | + * Copyright (C) 2013-2016 Canonical, Ltd. |
8 | * |
9 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by |
11 | @@ -166,31 +166,37 @@ |
12 | return -1; |
13 | } |
14 | |
15 | - function selectUser(uid, reset) { |
16 | - if (uid < 0) |
17 | + function selectUser(index, reset) { |
18 | + if (index < 0 || index >= LightDMService.users.count) |
19 | return; |
20 | d.waiting = true; |
21 | if (reset) { |
22 | loader.item.reset(); |
23 | } |
24 | - currentIndex = uid; |
25 | - var user = LightDMService.users.data(uid, LightDMService.userRoles.NameRole); |
26 | + currentIndex = index; |
27 | + var user = LightDMService.users.data(index, LightDMService.userRoles.NameRole); |
28 | AccountsService.user = user; |
29 | LauncherModel.setUser(user); |
30 | LightDMService.greeter.authenticate(user); // always resets auth state |
31 | } |
32 | |
33 | + function hideView() { |
34 | + if (loader.item) { |
35 | + loader.item.enabled = false; // drop OSK and prevent interaction |
36 | + loader.item.notifyAuthenticationSucceeded(false /* showFakePassword */); |
37 | + loader.item.hide(); |
38 | + } |
39 | + } |
40 | + |
41 | function login() { |
42 | - enabled = false; |
43 | + d.waiting = true; |
44 | if (LightDMService.greeter.startSessionSync()) { |
45 | sessionStarted(); |
46 | - if (loader.item) { |
47 | - loader.item.notifyAuthenticationSucceeded(false /* showFakePassword */); |
48 | - } |
49 | + hideView(); |
50 | } else if (loader.item) { |
51 | loader.item.notifyAuthenticationFailed(); |
52 | } |
53 | - enabled = true; |
54 | + d.waiting = false; |
55 | } |
56 | |
57 | function startUnlock(toTheRight) { |
58 | @@ -202,10 +208,8 @@ |
59 | } |
60 | |
61 | function checkForcedUnlock(hideNow) { |
62 | - if (forcedUnlock && shown && loader.item) { |
63 | - // pretend we were just authenticated |
64 | - loader.item.notifyAuthenticationSucceeded(false /* showFakePassword */); |
65 | - loader.item.hide(); |
66 | + if (forcedUnlock && shown) { |
67 | + hideView(); |
68 | if (hideNow) { |
69 | root.hideNow(); // skip hide animation |
70 | } |
71 | @@ -326,7 +330,7 @@ |
72 | |
73 | onLoaded: { |
74 | root.lockedApp = ""; |
75 | - root.forceActiveFocus(); |
76 | + item.forceActiveFocus(); |
77 | d.selectUser(d.currentIndex, true); |
78 | LightDMService.infographic.readyForDataChange(); |
79 | } |
80 | @@ -336,13 +340,11 @@ |
81 | onSelected: { |
82 | d.selectUser(index, true); |
83 | } |
84 | - onPromptlessLogin: d.login(); |
85 | onResponded: { |
86 | if (root.locked) { |
87 | LightDMService.greeter.respond(response); |
88 | } else { |
89 | d.login(); |
90 | - loader.item.hide(); |
91 | } |
92 | } |
93 | onTease: root.tease() |
94 | @@ -392,6 +394,12 @@ |
95 | |
96 | Binding { |
97 | target: loader.item |
98 | + property: "waiting" |
99 | + value: d.waiting |
100 | + } |
101 | + |
102 | + Binding { |
103 | + target: loader.item |
104 | property: "alphanumeric" |
105 | value: d.alphanumeric |
106 | } |
107 | @@ -420,10 +428,7 @@ |
108 | |
109 | onShowGreeter: root.forceShow() |
110 | |
111 | - onHideGreeter: { |
112 | - d.login(); |
113 | - loader.item.hide(); |
114 | - } |
115 | + onHideGreeter: d.login() |
116 | |
117 | onShowMessage: { |
118 | // inefficient, but we only rarely deal with messages |
119 | @@ -441,11 +446,11 @@ |
120 | } |
121 | |
122 | onShowPrompt: { |
123 | - d.waiting = false; |
124 | - |
125 | if (loader.item) { |
126 | loader.item.showPrompt(text, isSecret, isDefaultPrompt); |
127 | } |
128 | + |
129 | + d.waiting = false; |
130 | } |
131 | |
132 | onAuthenticationComplete: { |
133 | @@ -454,7 +459,6 @@ |
134 | if (LightDMService.greeter.authenticated) { |
135 | if (!LightDMService.greeter.promptless) { |
136 | d.login(); |
137 | - loader.item.hide(); |
138 | } |
139 | } else { |
140 | if (!LightDMService.greeter.promptless) { |
141 | |
142 | === modified file 'qml/Greeter/GreeterPrompt.qml' |
143 | --- qml/Greeter/GreeterPrompt.qml 2016-06-06 18:21:22 +0000 |
144 | +++ qml/Greeter/GreeterPrompt.qml 2016-07-08 20:44:29 +0000 |
145 | @@ -16,6 +16,7 @@ |
146 | |
147 | import QtQuick 2.4 |
148 | import Ubuntu.Components 1.3 |
149 | +import "../Components" |
150 | |
151 | FocusScope { |
152 | id: root |
153 | @@ -33,6 +34,7 @@ |
154 | |
155 | function reset() { |
156 | passwordInput.text = ""; |
157 | + fakeLabel.text = ""; |
158 | d.enabled = true; |
159 | } |
160 | |
161 | @@ -58,14 +60,28 @@ |
162 | color: "transparent" |
163 | } |
164 | |
165 | + Component.onCompleted: updateFocus() |
166 | + onIsPromptChanged: updateFocus() |
167 | + function updateFocus() { |
168 | + if (root.isPrompt) { |
169 | + passwordInput.focus = true; |
170 | + } else { |
171 | + promptButton.focus = true; |
172 | + } |
173 | + } |
174 | + |
175 | AbstractButton { |
176 | + id: promptButton |
177 | objectName: "promptButton" |
178 | anchors.fill: parent |
179 | visible: !root.isPrompt |
180 | - enabled: d.enabled |
181 | - focus: visible |
182 | |
183 | - onClicked: root.clicked() |
184 | + onClicked: { |
185 | + if (d.enabled) { |
186 | + d.enabled = false; |
187 | + root.clicked(); |
188 | + } |
189 | + } |
190 | |
191 | Label { |
192 | anchors.centerIn: parent |
193 | @@ -79,10 +95,15 @@ |
194 | objectName: "promptField" |
195 | anchors.fill: parent |
196 | visible: root.isPrompt |
197 | - enabled: d.enabled |
198 | - focus: visible |
199 | - |
200 | - inputMethodHints: root.isAlphanumeric ? Qt.ImhNone : Qt.ImhDigitsOnly |
201 | + opacity: fakeLabel.visible ? 0 : 1 |
202 | + |
203 | + validator: RegExpValidator { |
204 | + regExp: root.isAlphanumeric ? /^.*$/ : /^\d{4}$/ |
205 | + } |
206 | + |
207 | + inputMethodHints: Qt.ImhSensitiveData | Qt.ImhNoPredictiveText | |
208 | + Qt.ImhMultiLine | // so OSK doesn't close on Enter |
209 | + (root.isAlphanumeric ? Qt.ImhNone : Qt.ImhDigitsOnly) |
210 | echoMode: root.isSecret ? TextInput.Password : TextInput.Normal |
211 | hasClearButton: false |
212 | |
213 | @@ -107,17 +128,35 @@ |
214 | width: units.gu(3) |
215 | color: d.textColor |
216 | visible: root.isSecret && false // TODO: detect when caps lock is on |
217 | + readonly property real visibleWidth: visible ? width + passwordInput.frameSpacing : 0 |
218 | } |
219 | ] |
220 | |
221 | + onDisplayTextChanged: { |
222 | + // We use onDisplayTextChanged instead of onTextChanged because |
223 | + // displayText changes after text and if we did this before it |
224 | + // updated, we would use the wrong displayText for fakeLabel. |
225 | + if (!isAlphanumeric && text.length >= 4) { |
226 | + // hard limit of 4 for passcodes right now |
227 | + respond(); |
228 | + } |
229 | + } |
230 | + |
231 | onAccepted: { |
232 | - if (!enabled) |
233 | - return; |
234 | + if (d.enabled) |
235 | + respond(); |
236 | + } |
237 | + |
238 | + function respond() { |
239 | d.enabled = false; |
240 | + fakeLabel.text = displayText; |
241 | root.responded(text); |
242 | } |
243 | |
244 | - Keys.onEscapePressed: root.canceled() |
245 | + Keys.onEscapePressed: { |
246 | + root.canceled(); |
247 | + event.accepted = true; |
248 | + } |
249 | |
250 | // We use our own custom placeholder label instead of the standard |
251 | // TextField one because the standard one hardcodes baseText as the |
252 | @@ -129,9 +168,7 @@ |
253 | right: parent.right |
254 | verticalCenter: parent.verticalCenter |
255 | leftMargin: units.gu(1.5) |
256 | - rightMargin: anchors.leftMargin + |
257 | - (capsIcon.visible ? capsIcon.width + passwordInput.frameSpacing |
258 | - : 0) |
259 | + rightMargin: anchors.leftMargin + capsIcon.visibleWidth |
260 | } |
261 | text: root.text |
262 | visible: passwordInput.text == "" && !passwordInput.inputMethodComposing |
263 | @@ -139,4 +176,22 @@ |
264 | elide: Text.ElideRight |
265 | } |
266 | } |
267 | + |
268 | + // Have a fake label that covers the text field after the user presses |
269 | + // enter. What we *really* want is a disabled mode that doesn't lose OSK |
270 | + // focus. Because our goal here is simply to keep the OSK up while |
271 | + // we wait for PAM to get back to us, and while waiting, we don't want |
272 | + // the user to be able to edit the field (simply because it would look |
273 | + // weird if we allowed that). But until we have such a disabled mode, |
274 | + // we'll fake it by covering the real text field with a label. |
275 | + FadingLabel { |
276 | + id: fakeLabel |
277 | + anchors.verticalCenter: parent.verticalCenter |
278 | + anchors.left: parent.left |
279 | + anchors.right: parent.right |
280 | + anchors.leftMargin: passwordInput.frameSpacing * 2 |
281 | + anchors.rightMargin: passwordInput.frameSpacing * 2 + capsIcon.visibleWidth |
282 | + color: d.drawColor |
283 | + visible: root.isPrompt && !d.enabled |
284 | + } |
285 | } |
286 | |
287 | === modified file 'qml/Greeter/LoginList.qml' |
288 | --- qml/Greeter/LoginList.qml 2016-07-08 20:44:28 +0000 |
289 | +++ qml/Greeter/LoginList.qml 2016-07-08 20:44:29 +0000 |
290 | @@ -21,11 +21,13 @@ |
291 | |
292 | StyledItem { |
293 | id: root |
294 | + focus: true |
295 | |
296 | property alias model: userList.model |
297 | property bool alphanumeric: true |
298 | property int currentIndex |
299 | property bool locked |
300 | + property bool waiting |
301 | |
302 | readonly property int numAboveBelow: 4 |
303 | readonly property int cellHeight: units.gu(5) |
304 | @@ -36,7 +38,6 @@ |
305 | |
306 | signal selected(int index) |
307 | signal responded(string response) |
308 | - signal promptlessLogin() |
309 | |
310 | function tryToUnlock() { |
311 | if (wasPrompted) { |
312 | @@ -45,7 +46,6 @@ |
313 | if (root.locked) { |
314 | root.selected(currentIndex); |
315 | } else { |
316 | - promptlessLogin(); |
317 | root.responded(""); |
318 | } |
319 | } |
320 | @@ -60,20 +60,18 @@ |
321 | } |
322 | |
323 | function showPrompt(text, isSecret, isDefaultPrompt) { |
324 | - d.promptText = text; |
325 | - passwordInput.reset(); |
326 | + passwordInput.text = isDefaultPrompt ? alphanumeric ? i18n.tr("Passphrase") |
327 | + : i18n.tr("Passcode") |
328 | + : text; |
329 | + passwordInput.isPrompt = true; |
330 | passwordInput.isSecret = isSecret; |
331 | - if (wasPrompted) // stay in text field if second prompt |
332 | - passwordInput.focus = true; |
333 | + passwordInput.reset(); |
334 | wasPrompted = true; |
335 | } |
336 | |
337 | function showError() { |
338 | wrongPasswordAnimation.start(); |
339 | root.resetAuthentication(); |
340 | - if (wasPrompted) { |
341 | - passwordInput.focus = true; |
342 | - } |
343 | } |
344 | |
345 | function reset() { |
346 | @@ -83,15 +81,33 @@ |
347 | QtObject { |
348 | id: d |
349 | |
350 | - property string promptText |
351 | + function checkIfPromptless() { |
352 | + if (!waiting && !wasPrompted) { |
353 | + passwordInput.isPrompt = false; |
354 | + passwordInput.text = root.locked ? i18n.tr("Retry") |
355 | + : i18n.tr("Log In") |
356 | + } |
357 | + } |
358 | } |
359 | |
360 | + onWaitingChanged: d.checkIfPromptless() |
361 | + onLockedChanged: d.checkIfPromptless() |
362 | + |
363 | theme: ThemeSettings { |
364 | name: "Ubuntu.Components.Themes.Ambiance" |
365 | } |
366 | |
367 | + Keys.onUpPressed: { |
368 | + selected(currentIndex - 1); |
369 | + event.accepted = true; |
370 | + } |
371 | + Keys.onDownPressed: { |
372 | + selected(currentIndex + 1); |
373 | + event.accepted = true; |
374 | + } |
375 | Keys.onEscapePressed: { |
376 | selected(currentIndex); |
377 | + event.accepted = true; |
378 | } |
379 | |
380 | onCurrentIndexChanged: { |
381 | @@ -137,6 +153,7 @@ |
382 | highlightRangeMode: ListView.StrictlyEnforceRange |
383 | highlightMoveDuration: root.moveDuration |
384 | flickDeceleration: 10000 |
385 | + interactive: count > 1 |
386 | |
387 | readonly property bool movingInternally: moveTimer.running || userList.moving |
388 | onMovingInternallyChanged: { |
389 | @@ -254,13 +271,8 @@ |
390 | width: highlightItem.width - anchors.margins * 2 |
391 | opacity: userList.movingInternally ? 0 : 1 |
392 | |
393 | - isPrompt: root.wasPrompted |
394 | isAlphanumeric: root.alphanumeric |
395 | |
396 | - text: root.wasPrompted ? d.promptText |
397 | - : (root.locked ? i18n.tr("Retry") |
398 | - : i18n.tr("Log In")) |
399 | - |
400 | onClicked: root.tryToUnlock() |
401 | onResponded: root.responded(text) |
402 | onCanceled: root.selected(currentIndex) |
403 | @@ -280,7 +292,6 @@ |
404 | return; |
405 | } |
406 | infoLabel.text = ""; |
407 | - d.promptText = ""; |
408 | passwordInput.reset(); |
409 | root.wasPrompted = false; |
410 | } |
411 | |
412 | === modified file 'qml/Greeter/NarrowView.qml' |
413 | --- qml/Greeter/NarrowView.qml 2016-06-20 20:23:28 +0000 |
414 | +++ qml/Greeter/NarrowView.qml 2016-07-08 20:44:29 +0000 |
415 | @@ -31,6 +31,7 @@ |
416 | property bool alphanumeric |
417 | property var userModel // unused |
418 | property alias infographicModel: coverPage.infographicModel |
419 | + property bool waiting |
420 | readonly property bool fullyShown: coverPage.showProgress === 1 || lockscreen.shown |
421 | readonly property bool required: coverPage.required || lockscreen.required |
422 | readonly property bool animating: coverPage.showAnimation.running || coverPage.hideAnimation.running |
423 | @@ -71,7 +72,6 @@ |
424 | if (!alphanumeric && showFakePassword) { |
425 | lockscreen.showText("...."); // actual text doesn't matter, we show bullets |
426 | } |
427 | - lockscreen.hide(); |
428 | } |
429 | |
430 | function notifyAuthenticationFailed() { |
431 | @@ -172,6 +172,7 @@ |
432 | height: parent.height |
433 | width: parent.width |
434 | background: root.background |
435 | + draggable: !root.waiting |
436 | onTease: root.tease() |
437 | onClicked: hide() |
438 | |
439 | |
440 | === modified file 'qml/Greeter/WideView.qml' |
441 | --- qml/Greeter/WideView.qml 2016-07-08 20:44:28 +0000 |
442 | +++ qml/Greeter/WideView.qml 2016-07-08 20:44:29 +0000 |
443 | @@ -1,5 +1,5 @@ |
444 | /* |
445 | - * Copyright (C) 2015 Canonical, Ltd. |
446 | + * Copyright (C) 2015-2016 Canonical, Ltd. |
447 | * |
448 | * This program is free software; you can redistribute it and/or modify |
449 | * it under the terms of the GNU General Public License as published by |
450 | @@ -19,6 +19,7 @@ |
451 | |
452 | FocusScope { |
453 | id: root |
454 | + focus: true |
455 | |
456 | property alias dragHandleLeftMargin: coverPage.dragHandleLeftMargin |
457 | property alias launcherOffset: coverPage.launcherOffset |
458 | @@ -30,6 +31,7 @@ |
459 | property alias alphanumeric: loginList.alphanumeric |
460 | property alias userModel: loginList.model |
461 | property alias infographicModel: coverPage.infographicModel |
462 | + property bool waiting |
463 | readonly property bool fullyShown: coverPage.showProgress === 1 |
464 | readonly property bool required: coverPage.required |
465 | readonly property bool animating: coverPage.showAnimation.running || coverPage.hideAnimation.running |
466 | @@ -37,7 +39,6 @@ |
467 | // so that it can be replaced in tests with a mock object |
468 | property var inputMethod: Qt.inputMethod |
469 | |
470 | - signal promptlessLogin() |
471 | signal selected(int index) |
472 | signal responded(string response) |
473 | signal tease() |
474 | @@ -102,7 +103,7 @@ |
475 | objectName: "coverPage" |
476 | height: parent.height |
477 | width: parent.width |
478 | - draggable: !root.locked |
479 | + draggable: !root.locked && !root.waiting |
480 | |
481 | infographics { |
482 | height: 0.75 * parent.height |
483 | @@ -132,8 +133,8 @@ |
484 | Behavior on height { UbuntuNumberAnimation {} } |
485 | |
486 | locked: root.locked |
487 | + waiting: root.waiting |
488 | |
489 | - onPromptlessLogin: root.promptlessLogin() |
490 | onSelected: root.selected(index) |
491 | onResponded: root.responded(response) |
492 | } |
493 | |
494 | === modified file 'qml/Shell.qml' |
495 | --- qml/Shell.qml 2016-07-08 20:44:28 +0000 |
496 | +++ qml/Shell.qml 2016-07-08 20:44:29 +0000 |
497 | @@ -137,9 +137,9 @@ |
498 | // For autopilot consumption |
499 | readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId |
500 | |
501 | - // Disable everything while greeter is waiting, so that the user can't swipe |
502 | - // the greeter or launcher until we know whether the session is locked. |
503 | - enabled: greeter && !greeter.waiting |
504 | + // Note when greeter is waiting on PAM, so that we can disable edges until |
505 | + // we know which user data to show and whether the session is locked. |
506 | + readonly property bool waitingOnGreeter: greeter && greeter.waiting |
507 | |
508 | property real edgeSize: units.gu(settings.edgeDragWidth) |
509 | |
510 | @@ -533,6 +533,7 @@ |
511 | available: tutorial.panelEnabled |
512 | && ((!greeter || !greeter.locked) || AccountsService.enableIndicatorsWhileLocked) |
513 | && (!greeter || !greeter.hasLockedApp) |
514 | + && !shell.waitingOnGreeter |
515 | width: parent.width > units.gu(60) ? units.gu(40) : parent.width |
516 | |
517 | minimizedPanelHeight: units.gu(3) |
518 | @@ -583,6 +584,7 @@ |
519 | available: tutorial.launcherEnabled |
520 | && (!greeter.locked || AccountsService.enableLauncherWhileLocked) |
521 | && !greeter.hasLockedApp |
522 | + && !shell.waitingOnGreeter |
523 | inverted: shell.usageScenario !== "desktop" |
524 | superPressed: physicalKeysMapper.superPressed |
525 | superTabPressed: physicalKeysMapper.superTabPressed |
526 | |
527 | === modified file 'tests/qmltests/Dash/tst_DashShell.qml' |
528 | --- tests/qmltests/Dash/tst_DashShell.qml 2016-06-07 03:33:35 +0000 |
529 | +++ tests/qmltests/Dash/tst_DashShell.qml 2016-07-08 20:44:29 +0000 |
530 | @@ -91,6 +91,9 @@ |
531 | var stopY = startY; |
532 | touchFlick(shell, startX, startY, stopX, stopY); |
533 | |
534 | + var greeter = findChild(shell, "greeter"); |
535 | + tryCompare(greeter, "shown", false); |
536 | + |
537 | // bring in the launcher |
538 | var startX = units.gu(1); |
539 | var startY = shell.height / 2; |
540 | @@ -131,6 +134,9 @@ |
541 | var stopY = startY; |
542 | touchFlick(shell, startX, startY, stopX, stopY); |
543 | |
544 | + var greeter = findChild(shell, "greeter"); |
545 | + tryCompare(greeter, "shown", false); |
546 | + |
547 | // Now do a small launcher movement |
548 | touchFlick(shell, stopX, startY, startX, stopY); |
549 | compare(dashContentList.currentIndex, 0, "Small launcher move did not reset dash on non active window"); |
550 | |
551 | === modified file 'tests/qmltests/Greeter/TestView.qml' |
552 | --- tests/qmltests/Greeter/TestView.qml 2016-07-08 20:44:28 +0000 |
553 | +++ tests/qmltests/Greeter/TestView.qml 2016-05-25 19:25:51 +0000 |
554 | @@ -43,7 +43,6 @@ |
555 | signal responded(string response) |
556 | signal tease() |
557 | signal emergencyCall() |
558 | - signal promptlessLogin() |
559 | |
560 | signal _showMessageCalled(string html) |
561 | signal _showPromptCalled(string text, bool isSecret, bool isDefaultPrompt) |
562 | |
563 | === modified file 'tests/qmltests/Greeter/tst_Greeter.qml' |
564 | --- tests/qmltests/Greeter/tst_Greeter.qml 2016-07-08 20:44:28 +0000 |
565 | +++ tests/qmltests/Greeter/tst_Greeter.qml 2016-07-08 20:44:29 +0000 |
566 | @@ -1,5 +1,5 @@ |
567 | /* |
568 | - * Copyright 2015 Canonical Ltd. |
569 | + * Copyright 2015-2016 Canonical Ltd. |
570 | * |
571 | * This program is free software; you can redistribute it and/or modify |
572 | * it under the terms of the GNU General Public License as published by |
573 | @@ -194,6 +194,8 @@ |
574 | var i = getIndexOf(name); |
575 | view.selected(i); |
576 | verifySelected(name); |
577 | + compare(greeter.waiting, true); |
578 | + tryCompare(greeter, "waiting", false); |
579 | return i; |
580 | } |
581 | |
582 | @@ -325,18 +327,6 @@ |
583 | compare(viewShowMessageSpy.signalArguments[2][0], "You should have seen three messages"); |
584 | } |
585 | |
586 | - function test_waiting() { |
587 | - // Make sure we unset 'waiting' on prompt |
588 | - selectUser("has-password"); |
589 | - compare(greeter.waiting, true); |
590 | - tryCompare(greeter, "waiting", false); |
591 | - |
592 | - // Make sure we unset 'waiting' on authentication |
593 | - selectUser("no-password"); |
594 | - compare(greeter.waiting, true); |
595 | - tryCompare(greeter, "waiting", false); |
596 | - } |
597 | - |
598 | function test_locked() { |
599 | selectUser("has-password"); |
600 | compare(view.locked, true); |
601 | |
602 | === modified file 'tests/qmltests/Greeter/tst_WideView.qml' |
603 | --- tests/qmltests/Greeter/tst_WideView.qml 2016-07-08 20:44:28 +0000 |
604 | +++ tests/qmltests/Greeter/tst_WideView.qml 2016-07-08 20:44:29 +0000 |
605 | @@ -26,6 +26,7 @@ |
606 | id: root |
607 | width: units.gu(120) |
608 | height: units.gu(80) |
609 | + focus: true |
610 | |
611 | theme.name: "Ubuntu.Components.Themes.SuruDark" |
612 | |
613 | @@ -41,6 +42,7 @@ |
614 | id: loader |
615 | width: root.width - controls.width |
616 | height: parent.height |
617 | + focus: true |
618 | |
619 | property bool itemDestroyed: false |
620 | sourceComponent: Component { |
621 | @@ -63,7 +65,8 @@ |
622 | } |
623 | |
624 | onSelected: { |
625 | - currentIndexField.text = index; |
626 | + if (index >= 0) |
627 | + currentIndexField.text = index; |
628 | } |
629 | |
630 | QtObject { |
631 | @@ -392,7 +395,7 @@ |
632 | |
633 | function test_respondedWithPassword() { |
634 | view.locked = true; |
635 | - view.showPrompt("Prompt", true, true); |
636 | + view.showPrompt("Prompt", true, false); |
637 | var passwordInput = findChild(view, "passwordInput"); |
638 | compare(passwordInput.text, "Prompt"); |
639 | verify(passwordInput.isSecret); |
640 | @@ -454,13 +457,13 @@ |
641 | view.showPrompt("Prompt", true, true); |
642 | var promptField = findChild(view, "promptField"); |
643 | tap(promptField); |
644 | - compare(promptField.focus, true); |
645 | - compare(promptField.enabled, true); |
646 | + verify(promptField.activeFocus); |
647 | + compare(promptField.opacity, 1); |
648 | |
649 | typeString("password"); |
650 | keyClick(Qt.Key_Enter); |
651 | - compare(promptField.focus, true); |
652 | - compare(promptField.enabled, false); |
653 | + verify(promptField.activeFocus); |
654 | + compare(promptField.opacity, 0); // hidden by fakeLabel |
655 | |
656 | compare(selectedSpy.count, 0); |
657 | keyClick(Qt.Key_Escape); |
658 | @@ -468,8 +471,8 @@ |
659 | compare(selectedSpy.signalArguments[0][0], 1); |
660 | |
661 | view.reset(); |
662 | - compare(promptField.focus, false); |
663 | - compare(promptField.enabled, true); |
664 | + verify(promptField.activeFocus); |
665 | + compare(promptField.opacity, 1); |
666 | } |
667 | |
668 | function test_unicode() { |
669 | @@ -489,6 +492,7 @@ |
670 | compare(selectedSpy.signalArguments[0][0], 0); |
671 | selectedSpy.clear(); |
672 | |
673 | + view.reset(); |
674 | view.locked = false; |
675 | compare(passwordInput.text, "Log In"); |
676 | tap(passwordInput); |
677 | @@ -518,13 +522,89 @@ |
678 | tryCompare(loginList, "height", view.height); |
679 | } |
680 | |
681 | - function test_alphanumeric() { |
682 | - var passwordInput = findChild(view, "passwordInput"); |
683 | + function test_passphrase() { |
684 | + var promptField = findChild(view, "promptField"); |
685 | + view.showPrompt("", true, true); |
686 | |
687 | verify(view.alphanumeric); |
688 | - verify(passwordInput.isAlphanumeric); |
689 | + compare(promptField.inputMethodHints & Qt.ImhDigitsOnly, 0); |
690 | + |
691 | + keyClick(Qt.Key_D); |
692 | + compare(promptField.text, "d"); |
693 | + } |
694 | + |
695 | + function test_passcode() { |
696 | + var promptField = findChild(view, "promptField"); |
697 | + view.showPrompt("", true, true); |
698 | + |
699 | view.alphanumeric = false; |
700 | - verify(!passwordInput.isAlphanumeric); |
701 | + compare(promptField.inputMethodHints & Qt.ImhDigitsOnly, Qt.ImhDigitsOnly); |
702 | + |
703 | + keyClick(Qt.Key_D); |
704 | + compare(promptField.text, ""); |
705 | + |
706 | + keyClick(Qt.Key_0); |
707 | + keyClick(Qt.Key_0); |
708 | + keyClick(Qt.Key_0); |
709 | + keyClick(Qt.Key_0); |
710 | + compare(promptField.text, "0000"); |
711 | + |
712 | + compare(respondedSpy.count, 1); |
713 | + compare(respondedSpy.signalArguments[0][0], "0000"); |
714 | + |
715 | + compare(promptField.opacity, 0); |
716 | + } |
717 | + |
718 | + function test_loginListMovement_data() { |
719 | + return [ |
720 | + {tag: "up", key: Qt.Key_Up, result: -1}, |
721 | + {tag: "down", key: Qt.Key_Down, result: 1}, |
722 | + ] |
723 | + } |
724 | + |
725 | + function test_loginListMovement(data) { |
726 | + keyClick(data.key); |
727 | + compare(selectedSpy.count, 1); |
728 | + compare(selectedSpy.signalArguments[0][0], data.result); |
729 | + } |
730 | + |
731 | + function test_focusStaysActive() { |
732 | + var promptField = findChild(view, "promptField"); |
733 | + var promptButton = findChild(view, "promptButton"); |
734 | + |
735 | + verify(promptButton.activeFocus); |
736 | + keyClick(Qt.Key_Enter); |
737 | + compare(selectedSpy.count, 0); |
738 | + compare(respondedSpy.count, 1); |
739 | + compare(respondedSpy.signalArguments[0][0], ""); |
740 | + verify(promptButton.activeFocus); |
741 | + keyClick(Qt.Key_Enter); |
742 | + compare(respondedSpy.count, 1); |
743 | + |
744 | + view.showPrompt("", true, true); |
745 | + verify(promptField.activeFocus); |
746 | + keyClick(Qt.Key_D); |
747 | + keyClick(Qt.Key_Enter); |
748 | + compare(selectedSpy.count, 0); |
749 | + compare(respondedSpy.count, 2); |
750 | + compare(respondedSpy.signalArguments[1][0], "d"); |
751 | + verify(promptField.activeFocus); |
752 | + keyClick(Qt.Key_Enter); |
753 | + compare(respondedSpy.count, 2); |
754 | + |
755 | + view.reset(); |
756 | + view.locked = true; |
757 | + verify(promptButton.activeFocus); |
758 | + keyClick(Qt.Key_Enter); |
759 | + compare(respondedSpy.count, 2); |
760 | + compare(selectedSpy.count, 1); |
761 | + compare(selectedSpy.signalArguments[0][0], 0); |
762 | + verify(promptButton.activeFocus); |
763 | + keyClick(Qt.Key_Enter); |
764 | + compare(selectedSpy.count, 1); |
765 | + |
766 | + view.showPrompt("", true, true); |
767 | + verify(promptField.activeFocus); |
768 | } |
769 | } |
770 | } |
771 | |
772 | === modified file 'tests/qmltests/Tutorial/tst_Tutorial.qml' |
773 | --- tests/qmltests/Tutorial/tst_Tutorial.qml 2016-07-08 20:44:28 +0000 |
774 | +++ tests/qmltests/Tutorial/tst_Tutorial.qml 2016-07-08 20:44:29 +0000 |
775 | @@ -296,7 +296,7 @@ |
776 | } |
777 | |
778 | function prepareShell() { |
779 | - tryCompare(shell, "enabled", true); // enabled by greeter when ready |
780 | + tryCompare(shell, "waitingOnGreeter", false); // reset by greeter when ready |
781 | |
782 | WindowStateStorage.clear(); |
783 | SurfaceManager.inputMethodSurface.setState(Mir.MinimizedState); |
784 | |
785 | === modified file 'tests/qmltests/tst_OrientedShell.qml' |
786 | --- tests/qmltests/tst_OrientedShell.qml 2016-07-08 20:44:28 +0000 |
787 | +++ tests/qmltests/tst_OrientedShell.qml 2016-07-08 20:44:29 +0000 |
788 | @@ -493,7 +493,7 @@ |
789 | } |
790 | |
791 | function cleanup() { |
792 | - tryCompare(shell, "enabled", true); // make sure greeter didn't leave us in disabled state |
793 | + tryCompare(shell, "waitingOnGreeter", false); // make sure greeter didn't leave us in disabled state |
794 | shell = null; |
795 | topLevelSurfaceList = null; |
796 | |
797 | @@ -1583,7 +1583,7 @@ |
798 | var stageLoader = findChild(shell, "applicationsDisplayLoader"); |
799 | verify(stageLoader); |
800 | |
801 | - tryCompare(shell, "enabled", true); // enabled by greeter when ready |
802 | + tryCompare(shell, "waitingOnGreeter", false); // reset by greeter when ready |
803 | |
804 | waitUntilShellIsInOrientation(root.physicalOrientation0); |
805 | |
806 | |
807 | === modified file 'tests/qmltests/tst_Shell.qml' |
808 | --- tests/qmltests/tst_Shell.qml 2016-07-08 20:44:28 +0000 |
809 | +++ tests/qmltests/tst_Shell.qml 2016-07-08 20:44:29 +0000 |
810 | @@ -456,7 +456,7 @@ |
811 | function cleanup() { |
812 | waitForRendering(shell); |
813 | mouseEmulation.checked = true; |
814 | - tryCompare(shell, "enabled", true); // make sure greeter didn't leave us in disabled state |
815 | + tryCompare(shell, "waitingOnGreeter", false); // make sure greeter didn't leave us in disabled state |
816 | tearDown(); |
817 | WindowStateStorage.clear(); |
818 | } |
819 | @@ -466,7 +466,7 @@ |
820 | shellLoader.active = true; |
821 | tryCompare(shellLoader, "status", Loader.Ready); |
822 | removeTimeConstraintsFromSwipeAreas(shellLoader.item); |
823 | - tryCompare(shell, "enabled", true); // enabled by greeter when ready |
824 | + tryCompare(shell, "waitingOnGreeter", false); // reset by greeter when ready |
825 | |
826 | sessionSpy.target = findChild(shell, "greeter") |
827 | dashCommunicatorSpy.target = findInvisibleChild(shell, "dashCommunicator"); |
828 | @@ -818,7 +818,7 @@ |
829 | tryCompare(userlist, "currentIndex", next) |
830 | tryCompare(userlist, "movingInternally", false) |
831 | } |
832 | - tryCompare(shell, "enabled", true); // wait for PAM to settle |
833 | + tryCompare(shell, "waitingOnGreeter", false); // wait for PAM to settle |
834 | } |
835 | |
836 | function selectUser(name) { |
837 | |
838 | === modified file 'tests/qmltests/tst_ShellWithPin.qml' |
839 | --- tests/qmltests/tst_ShellWithPin.qml 2016-07-08 20:44:28 +0000 |
840 | +++ tests/qmltests/tst_ShellWithPin.qml 2016-07-08 20:44:29 +0000 |
841 | @@ -1,5 +1,5 @@ |
842 | /* |
843 | - * Copyright (C) 2014-2015 Canonical, Ltd. |
844 | + * Copyright (C) 2014-2016 Canonical, Ltd. |
845 | * |
846 | * This program is free software; you can redistribute it and/or modify |
847 | * it under the terms of the GNU General Public License as published by |
848 | @@ -150,7 +150,7 @@ |
849 | property Item shell: shellLoader.status === Loader.Ready ? shellLoader.item : null |
850 | |
851 | function init() { |
852 | - tryCompare(shell, "enabled", true); // will be enabled when greeter is all ready |
853 | + tryCompare(shell, "waitingOnGreeter", false); // will be set when greeter is all ready |
854 | var greeter = findChild(shell, "greeter"); |
855 | sessionSpy.target = greeter; |
856 | swipeAwayGreeter(true); |
857 | @@ -165,7 +165,7 @@ |
858 | } |
859 | |
860 | function cleanup() { |
861 | - tryCompare(shell, "enabled", true); // make sure greeter didn't leave us in disabled state |
862 | + tryCompare(shell, "waitingOnGreeter", false); // make sure greeter didn't leave us in disabled state |
863 | |
864 | shellLoader.itemDestroyed = false |
865 | |
866 | @@ -533,10 +533,12 @@ |
867 | |
868 | // Confirm that we start disabled |
869 | compare(promptSpy.count, 0); |
870 | - verify(!shell.enabled); |
871 | + verify(shell.waitingOnGreeter); |
872 | + var coverPageDragHandle = findChild(shell, "coverPageDragHandle"); |
873 | + verify(!coverPageDragHandle.enabled); |
874 | |
875 | // And that we only become enabled once the lockscreen is up |
876 | - tryCompare(shell, "enabled", true); |
877 | + tryCompare(shell, "waitingOnGreeter", false); |
878 | verify(promptSpy.count > 0); |
879 | var lockscreen = findChild(shell, "lockscreen"); |
880 | verify(lockscreen.shown); |
I'm going to work on some qmltests now, but this branch can be reviewed and tested in meantime.