Merge lp:~mterry/unity8/greeter-arrangement into lp:unity8
- greeter-arrangement
- Merge into trunk
Status: | Needs review | ||||
---|---|---|---|---|---|
Proposed branch: | lp:~mterry/unity8/greeter-arrangement | ||||
Merge into: | lp:unity8 | ||||
Diff against target: |
1470 lines (+515/-396) 16 files modified
qml/Greeter/CoverPage.qml (+9/-4) qml/Greeter/Greeter.qml (+22/-4) qml/Greeter/LoginAreaContainer.qml (+4/-0) qml/Greeter/LoginList.qml (+7/-1) qml/Greeter/LoginPage.qml (+211/-0) qml/Greeter/NarrowView.qml (+35/-93) qml/Greeter/WideView.qml (+83/-164) qml/Launcher/Launcher.qml (+2/-2) qml/Rotation/RotationStates.qml (+1/-2) qml/Shell.qml (+13/-12) tests/qmltests/Greeter/TestView.qml (+3/-1) tests/qmltests/Greeter/tst_Greeter.qml (+8/-0) tests/qmltests/Greeter/tst_NarrowView.qml (+1/-3) tests/qmltests/Greeter/tst_WideView.qml (+31/-58) tests/qmltests/tst_OrientedShell.qml (+28/-22) tests/qmltests/tst_Shell.qml (+57/-30) |
||||
To merge this branch: | bzr merge lp:~mterry/unity8/greeter-arrangement | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Unity8 CI Bot | continuous-integration | Needs Fixing | |
Albert Astals Cid (community) | Abstain | ||
Josh Arenson | Needs Fixing | ||
Review via email: mp+313404@code.launchpad.net |
Commit message
Allow tablet greeter to rotate.
Description of the change
I simplified and consolidated code in NarrowView and WideView. They share a lot more, and should be more convergent as a result.
All this is per the following spec:
https:/
The futzing with mainApp vs focusedApplicat
* Are there any related MPs required for this MP to build/function as expected? Please list.
Just pre-reqs.
* Did you perform an exploratory manual test run of your code change and any related functionality?
Sort of? I tested the basics on a phone and a phone in fake-tablet mode, but haven't actually tested on a tablet yet as I don't have a good tablet that rotates.
* 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, just implementing spec.
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2581
https:/
Executed test runs:
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2581
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
UNSTABLE: 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:/
Click here to trigger a rebuild:
https:/
Albert Astals Cid (aacid) wrote : | # |
greeter-
This seems to be new (or at least i don't get it without this MR) can you check if you can make it go away?
Albert Astals Cid (aacid) wrote : | # |
Otherwise looks good (even though i did not get to try it neither on a phone nor a tablet)
Albert Astals Cid (aacid) wrote : | # |
Also one of the failed tests is in NarrowView but i could not reproduce the test failure locally.
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:2582
https:/
Executed test runs:
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:/
Click here to trigger a rebuild:
https:/
Michael Terry (mterry) wrote : | # |
OK I believe I fixed the binding loop and the test failure.
Albert Astals Cid (aacid) wrote : | # |
Not top approving in case Josh wants to weight in too.
* Did you perform an exploratory manual test run of the code change and any related functionality?
Yes (even though I don't have phone nor tablet to try)
* Did CI run pass? If not, please explain why.
Yes
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:2583
https:/
Executed test runs:
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:/
Click here to trigger a rebuild:
https:/
Albert Astals Cid (aacid) wrote : | # |
Text conflict in tests/qmltests/
1 conflicts encountered.
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2584
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2584
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
UNSTABLE: 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:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2584
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
UNSTABLE: 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:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:2584
https:/
Executed test runs:
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:/
Click here to trigger a rebuild:
https:/
Josh Arenson (josharenson) wrote : | # |
All keyboard input is broken for me. I can't navigate or type my password in the greeter. If I add Keys.onPressed as far up the stack as Shell.qml, key events are visible in the mock, but not in the real thing. Trying to get some more info for you, but have been unsuccessful so far.
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2585
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: 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:2585
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: 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:/
Click here to trigger a rebuild:
https:/
Albert Astals Cid (aacid) wrote : | # |
Text conflict in qml/Greeter/
Text conflict in qml/Greeter/
Text conflict in qml/Greeter/
Text conflict in tests/qmltests/
4 conflicts encountered.
Michael Terry (mterry) wrote : | # |
After merging with trunk, cleaning up the tests (I believe), and testing that the keyboard issue might have gone away(?), I'm re-enabling this MP in order to get debs and CI for further testing.
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2590
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
- 2591. By Michael Terry
-
Fix whitespace
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2591
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: 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:/
Click here to trigger a rebuild:
https:/
Albert Astals Cid (aacid) wrote : | # |
Text conflict in qml/Greeter/
Text conflict in qml/Greeter/
2 conflicts encountered.
Unmerged revisions
- 2591. By Michael Terry
-
Fix whitespace
- 2590. By Michael Terry
-
Fix some shell tests
- 2589. By Michael Terry
-
Merge from trunk
- 2588. By Michael Terry
-
Testing merge
- 2587. By Michael Terry
-
Merge from trunk
- 2586. By Michael Terry
-
Merge from trunk; this broke some tests, needs further investigation and testing
- 2585. By Michael Terry
-
Merge trunk
- 2584. By Michael Terry
-
Merge trunk
- 2583. By Michael Terry
-
Map supported orientations before using them
- 2582. By Michael Terry
-
Try to fix test, though I can't reproduce; and avoid binding loop
Preview Diff
1 | === modified file 'qml/Greeter/CoverPage.qml' |
2 | --- qml/Greeter/CoverPage.qml 2016-09-07 17:13:38 +0000 |
3 | +++ qml/Greeter/CoverPage.qml 2017-03-22 18:36:14 +0000 |
4 | @@ -27,11 +27,9 @@ |
5 | property alias background: greeterBackground.source |
6 | property alias hasCustomBackground: backgroundShade.visible |
7 | property real backgroundTopMargin |
8 | - property var infographicModel |
9 | + property alias infographicModel: infographics.model |
10 | property bool draggable: true |
11 | |
12 | - property alias infographics: infographics |
13 | - |
14 | readonly property real showProgress: MathUtils.clamp((width - Math.abs(x + launcherOffset)) / width, 0, 1) |
15 | |
16 | signal tease() |
17 | @@ -102,11 +100,18 @@ |
18 | visible: false |
19 | } |
20 | |
21 | + Clock { |
22 | + anchors { |
23 | + top: parent.top |
24 | + topMargin: units.gu(2) |
25 | + horizontalCenter: parent.horizontalCenter |
26 | + } |
27 | + } |
28 | + |
29 | Infographics { |
30 | id: infographics |
31 | objectName: "infographics" |
32 | height: parent.height |
33 | - model: root.infographicModel |
34 | clip: true // clip large data bubbles |
35 | |
36 | anchors { |
37 | |
38 | === modified file 'qml/Greeter/Greeter.qml' |
39 | --- qml/Greeter/Greeter.qml 2017-01-19 15:37:24 +0000 |
40 | +++ qml/Greeter/Greeter.qml 2017-03-22 18:36:14 +0000 |
41 | @@ -36,11 +36,16 @@ |
42 | property url background |
43 | property bool hasCustomBackground |
44 | |
45 | + property bool oskEnabled |
46 | + |
47 | // How far to offset the top greeter layer during a launcher left-drag |
48 | property real launcherOffset |
49 | + property real launcherLockedWidth |
50 | |
51 | readonly property bool active: required || hasLockedApp |
52 | readonly property bool fullyShown: loader.item ? loader.item.fullyShown : false |
53 | + readonly property int supportedOrientations: loader.item ? loader.item.supportedOrientations |
54 | + : Qt.PrimaryOrientation |
55 | |
56 | property bool allowFingerprint: true |
57 | |
58 | @@ -151,7 +156,6 @@ |
59 | QtObject { |
60 | id: d |
61 | |
62 | - readonly property bool multiUser: LightDMService.users.count > 1 |
63 | readonly property int selectUserIndex: d.getUserIndex(LightDMService.greeter.selectUser) |
64 | property int currentIndex: Math.max(selectUserIndex, 0) |
65 | readonly property bool waiting: LightDMService.prompts.count == 0 && !root.forcedUnlock |
66 | @@ -216,7 +220,9 @@ |
67 | } |
68 | |
69 | function startUnlock(toTheRight) { |
70 | - if (loader.item) { |
71 | + // Don't bother trying to unlock if we're animating. Avoids |
72 | + // competing with user or looking frenetic. |
73 | + if (loader.item && !loader.item.animating) { |
74 | return loader.item.tryToUnlock(toTheRight); |
75 | } else { |
76 | return false; |
77 | @@ -350,7 +356,7 @@ |
78 | |
79 | active: root.required |
80 | source: root.viewSource.toString() ? root.viewSource : |
81 | - (d.multiUser || root.tabletMode) ? "WideView.qml" : "NarrowView.qml" |
82 | + root.tabletMode ? "WideView.qml" : "NarrowView.qml" |
83 | |
84 | onLoaded: { |
85 | root.lockedApp = ""; |
86 | @@ -394,6 +400,12 @@ |
87 | |
88 | Binding { |
89 | target: loader.item |
90 | + property: "launcherLockedWidth" |
91 | + value: root.launcherLockedWidth |
92 | + } |
93 | + |
94 | + Binding { |
95 | + target: loader.item |
96 | property: "dragHandleLeftMargin" |
97 | value: root.dragHandleLeftMargin |
98 | } |
99 | @@ -418,6 +430,12 @@ |
100 | |
101 | Binding { |
102 | target: loader.item |
103 | + property: "oskEnabled" |
104 | + value: root.oskEnabled |
105 | + } |
106 | + |
107 | + Binding { |
108 | + target: loader.item |
109 | property: "locked" |
110 | value: root.locked |
111 | } |
112 | @@ -472,7 +490,7 @@ |
113 | // Check if we should initiate a factory reset |
114 | if (maxFailedLogins >= 2) { // require at least a warning |
115 | if (AccountsService.failedLogins === maxFailedLogins - 1) { |
116 | - loader.item.showLastChance(); |
117 | + //loader.item.showLastChance(); // not implemented yet |
118 | } else if (AccountsService.failedLogins >= maxFailedLogins) { |
119 | SystemImage.factoryReset(); // Ouch! |
120 | } |
121 | |
122 | === modified file 'qml/Greeter/LoginAreaContainer.qml' |
123 | --- qml/Greeter/LoginAreaContainer.qml 2016-09-13 12:25:30 +0000 |
124 | +++ qml/Greeter/LoginAreaContainer.qml 2017-03-22 18:36:14 +0000 |
125 | @@ -35,4 +35,8 @@ |
126 | aspect: UbuntuShape.Flat |
127 | backgroundColor: theme.palette.normal.raised |
128 | } |
129 | + |
130 | + MouseArea { |
131 | + anchors.fill: parent // eat events |
132 | + } |
133 | } |
134 | |
135 | === modified file 'qml/Greeter/LoginList.qml' |
136 | --- qml/Greeter/LoginList.qml 2017-01-24 07:40:40 +0000 |
137 | +++ qml/Greeter/LoginList.qml 2017-03-22 18:36:14 +0000 |
138 | @@ -43,7 +43,11 @@ |
139 | signal sessionChooserButtonClicked() |
140 | |
141 | function tryToUnlock() { |
142 | - promptList.forceActiveFocus(); |
143 | + if (!locked && model.count == 1) { |
144 | + responded(""); |
145 | + } else { |
146 | + promptList.forceActiveFocus(); |
147 | + } |
148 | } |
149 | |
150 | function showError() { |
151 | @@ -55,6 +59,8 @@ |
152 | promptList.showFakePassword(); |
153 | } |
154 | |
155 | + Behavior on boxVerticalOffset { UbuntuNumberAnimation {} } |
156 | + |
157 | theme: ThemeSettings { |
158 | name: "Ubuntu.Components.Themes.Ambiance" |
159 | } |
160 | |
161 | === added file 'qml/Greeter/LoginPage.qml' |
162 | --- qml/Greeter/LoginPage.qml 1970-01-01 00:00:00 +0000 |
163 | +++ qml/Greeter/LoginPage.qml 2017-03-22 18:36:14 +0000 |
164 | @@ -0,0 +1,211 @@ |
165 | +/* |
166 | + * Copyright (C) 2015-2016 Canonical, Ltd. |
167 | + * |
168 | + * This program is free software; you can redistribute it and/or modify |
169 | + * it under the terms of the GNU General Public License as published by |
170 | + * the Free Software Foundation; version 3. |
171 | + * |
172 | + * This program is distributed in the hope that it will be useful, |
173 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
174 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
175 | + * GNU General Public License for more details. |
176 | + * |
177 | + * You should have received a copy of the GNU General Public License |
178 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
179 | + */ |
180 | + |
181 | +import QtQuick 2.4 |
182 | +import Ubuntu.Components 1.3 |
183 | +import "../Components" |
184 | +import "." 0.1 |
185 | + |
186 | +Showable { |
187 | + id: root |
188 | + |
189 | + property alias background: wallpaper.source |
190 | + property real backgroundTopMargin |
191 | + property bool hasCustomBackground |
192 | + property alias locked: loginList.locked |
193 | + property alias waiting: loginList.waiting |
194 | + property bool alphanumeric: true |
195 | + property alias delayMinutes: delayedLockscreen.delayMinutes |
196 | + property bool hasCancel |
197 | + property bool covered |
198 | + property alias userModel: loginList.model |
199 | + property alias currentIndex: loginList.currentIndex |
200 | + property real promptHorizontalCenterOffset |
201 | + property real promptVerticalCenterOffset |
202 | + property real dragHandleLeftMargin |
203 | + property alias currentSession: loginList.currentSession |
204 | + readonly property real promptHeight: loginList.highlightedHeight |
205 | + readonly property real promptWidth: loginList.width |
206 | + |
207 | + // so that it can be replaced in tests with a mock object |
208 | + property var inputMethod: Qt.inputMethod |
209 | + |
210 | + signal cancel() |
211 | + signal emergencyCall() |
212 | + signal selected(int index) |
213 | + signal responded(string response) |
214 | + signal clicked() |
215 | + |
216 | + function showMessage(html) { |
217 | + loginList.showMessage(html); |
218 | + } |
219 | + |
220 | + function showPrompt(text, isSecret, isDefaultPrompt) { |
221 | + loginList.showPrompt(text, isSecret, isDefaultPrompt); |
222 | + } |
223 | + |
224 | + function notifyAuthenticationSucceeded(showFakePassword) { |
225 | + if (showFakePassword) { |
226 | + loginList.showFakePassword(); |
227 | + } |
228 | + } |
229 | + |
230 | + function notifyAuthenticationFailed() { |
231 | + loginList.showError(); |
232 | + } |
233 | + |
234 | + function reset() { |
235 | + loginList.reset(); |
236 | + } |
237 | + |
238 | + function tryToUnlock() { |
239 | + loginList.tryToUnlock(); |
240 | + } |
241 | + |
242 | + showAnimation: StandardAnimation { property: "opacity"; to: 1 } |
243 | + hideAnimation: StandardAnimation { property: "opacity"; to: 0 } |
244 | + |
245 | + Wallpaper { |
246 | + id: wallpaper |
247 | + anchors.fill: parent |
248 | + anchors.topMargin: root.backgroundTopMargin |
249 | + } |
250 | + |
251 | + // Darken background when custom background is used to see our overlays |
252 | + Rectangle { |
253 | + objectName: "lockscreenShade" |
254 | + anchors.fill: parent |
255 | + color: "black" |
256 | + opacity: root.hasCustomBackground ? 0.4 : 0 |
257 | + } |
258 | + |
259 | + MouseArea { |
260 | + anchors.fill: parent |
261 | + anchors.leftMargin: root.dragHandleLeftMargin |
262 | + onClicked: root.clicked() |
263 | + } |
264 | + |
265 | + LoginList { |
266 | + id: loginList |
267 | + objectName: "loginList" |
268 | + z: 1 // place above any custom items (like infographics) |
269 | + |
270 | + anchors { |
271 | + horizontalCenter: parent.left |
272 | + horizontalCenterOffset: root.promptHorizontalCenterOffset |
273 | + top: parent.top |
274 | + bottom: parent.bottom |
275 | + } |
276 | + width: units.gu(40) |
277 | + |
278 | + boxVerticalOffset: root.promptVerticalCenterOffset - highlightedHeight/2 |
279 | + |
280 | + enabled: !root.covered && visible |
281 | + visible: !delayedLockscreen.visible |
282 | + alphanumeric: root.alphanumeric |
283 | + |
284 | + onSelected: if (enabled) root.selected(index) |
285 | + onResponded: root.responded(response) |
286 | + onSessionChooserButtonClicked: parent.state = "SessionsList" |
287 | + onCurrentIndexChanged: setCurrentSession() |
288 | + |
289 | + Keys.forwardTo: [sessionChooserLoader.item] |
290 | + |
291 | + Component.onCompleted: setCurrentSession() |
292 | + |
293 | + function setCurrentSession() { |
294 | + currentSession = LightDMService.users.data(currentIndex, LightDMService.userRoles.SessionRole); |
295 | + } |
296 | + } |
297 | + |
298 | + Loader { |
299 | + id: sessionChooserLoader |
300 | + z: 1 |
301 | + |
302 | + height: loginList.height |
303 | + width: loginList.width |
304 | + anchors { |
305 | + left: parent.left |
306 | + leftMargin: Math.min(parent.width * 0.16, units.gu(20)) |
307 | + top: parent.top |
308 | + } |
309 | + |
310 | + active: false |
311 | + |
312 | + onLoaded: sessionChooserLoader.item.forceActiveFocus() |
313 | + Binding { |
314 | + target: sessionChooserLoader.item |
315 | + property: "initiallySelectedSession" |
316 | + value: loginList.currentSession |
317 | + } |
318 | + |
319 | + Connections { |
320 | + target: sessionChooserLoader.item |
321 | + onSessionSelected: loginList.currentSession = sessionKey |
322 | + onShowLoginList: { |
323 | + root.state = "LoginList" |
324 | + loginList.tryToUnlock(); |
325 | + } |
326 | + ignoreUnknownSignals: true |
327 | + } |
328 | + } |
329 | + |
330 | + states: [ |
331 | + State { |
332 | + name: "SessionsList" |
333 | + PropertyChanges { target: loginList; opacity: 0 } |
334 | + PropertyChanges { target: sessionChooserLoader; |
335 | + active: true; |
336 | + opacity: 1 |
337 | + source: "SessionsList.qml" |
338 | + } |
339 | + }, |
340 | + |
341 | + State { |
342 | + name: "LoginList" |
343 | + PropertyChanges { target: loginList; opacity: 1 } |
344 | + PropertyChanges { target: sessionChooserLoader; |
345 | + active: false; |
346 | + opacity: 0 |
347 | + source: ""; |
348 | + } |
349 | + } |
350 | + ] |
351 | + |
352 | + transitions: [ |
353 | + Transition { |
354 | + from: "*" |
355 | + to: "*" |
356 | + UbuntuNumberAnimation { |
357 | + property: "opacity"; |
358 | + } |
359 | + } |
360 | + ] |
361 | + |
362 | + DelayedLockscreen { |
363 | + id: delayedLockscreen |
364 | + objectName: "delayedLockscreen" |
365 | + anchors.fill: parent |
366 | + visible: delayMinutes > 0 |
367 | + alphaNumeric: root.alphanumeric |
368 | + } |
369 | + |
370 | + function maybeShow() { |
371 | + if (root.locked && !shown) { |
372 | + showNow(); |
373 | + } |
374 | + } |
375 | +} |
376 | |
377 | === modified file 'qml/Greeter/NarrowView.qml' |
378 | --- qml/Greeter/NarrowView.qml 2017-01-19 15:37:24 +0000 |
379 | +++ qml/Greeter/NarrowView.qml 2017-03-22 18:36:14 +0000 |
380 | @@ -17,28 +17,30 @@ |
381 | import QtQuick 2.4 |
382 | import QtQuick.Window 2.2 |
383 | import Ubuntu.Components 1.3 |
384 | -import Ubuntu.Telephony 0.1 as Telephony |
385 | -import "../Components" |
386 | |
387 | FocusScope { |
388 | id: root |
389 | |
390 | property alias dragHandleLeftMargin: coverPage.dragHandleLeftMargin |
391 | property alias launcherOffset: coverPage.launcherOffset |
392 | - property alias currentIndex: loginList.currentIndex |
393 | - property alias delayMinutes: delayedLockscreen.delayMinutes |
394 | - property alias backgroundTopMargin: coverPage.backgroundTopMargin |
395 | - property url background |
396 | - property bool hasCustomBackground |
397 | - property bool locked |
398 | - property alias alphanumeric: loginList.alphanumeric |
399 | - property alias userModel: loginList.model |
400 | + property real launcherLockedWidth // unused |
401 | + property alias currentIndex: lockscreen.currentIndex |
402 | + property alias delayMinutes: lockscreen.delayMinutes |
403 | + property alias backgroundTopMargin: lockscreen.backgroundTopMargin |
404 | + property alias background: lockscreen.background |
405 | + property alias hasCustomBackground: lockscreen.hasCustomBackground |
406 | + property alias locked: lockscreen.locked |
407 | + property alias alphanumeric: lockscreen.alphanumeric |
408 | + property alias userModel: lockscreen.userModel |
409 | property alias infographicModel: coverPage.infographicModel |
410 | - property string sessionToStart |
411 | - property bool waiting |
412 | + property alias sessionToStart: lockscreen.currentSession |
413 | + property alias waiting: lockscreen.waiting |
414 | + property bool oskEnabled |
415 | readonly property bool fullyShown: coverPage.showProgress === 1 || lockscreen.shown |
416 | readonly property bool required: coverPage.required || lockscreen.required |
417 | readonly property bool animating: coverPage.showAnimation.running || coverPage.hideAnimation.running |
418 | + readonly property int supportedOrientations: Qt.PortraitOrientation | |
419 | + Qt.InvertedPortraitOrientation |
420 | |
421 | // so that it can be replaced in tests with a mock object |
422 | property var inputMethod: Qt.inputMethod |
423 | @@ -48,34 +50,21 @@ |
424 | signal tease() |
425 | signal emergencyCall() |
426 | |
427 | - function showLastChance() { |
428 | - /* TODO: when we finish support for resetting device after too many |
429 | - failed logins, we should re-add this popup. |
430 | - var title = lockscreen.alphaNumeric ? |
431 | - i18n.tr("Sorry, incorrect passphrase.") : |
432 | - i18n.tr("Sorry, incorrect passcode."); |
433 | - var text = i18n.tr("This will be your last attempt.") + " " + |
434 | - (lockscreen.alphaNumeric ? |
435 | - i18n.tr("If passphrase is entered incorrectly, your phone will conduct a factory reset and all personal data will be deleted.") : |
436 | - i18n.tr("If passcode is entered incorrectly, your phone will conduct a factory reset and all personal data will be deleted.")); |
437 | - lockscreen.showInfoPopup(title, text); |
438 | - */ |
439 | - } |
440 | - |
441 | function hide() { |
442 | lockscreen.hide(); |
443 | coverPage.hide(); |
444 | } |
445 | |
446 | function showFakePassword() { |
447 | - loginList.showFakePassword(); |
448 | + lockscreen.showFakePassword(); |
449 | } |
450 | |
451 | function notifyAuthenticationFailed() { |
452 | - loginList.showError(); |
453 | + lockscreen.notifyAuthenticationFailed(); |
454 | } |
455 | |
456 | function showErrorMessage(msg) { |
457 | + // Only useful when coverPage is covering lockscreen, so only send there |
458 | coverPage.showErrorMessage(msg); |
459 | } |
460 | |
461 | @@ -95,74 +84,32 @@ |
462 | } |
463 | |
464 | onLockedChanged: { |
465 | - if (locked) { |
466 | + if (locked || userModel.count > 1) { |
467 | lockscreen.maybeShow(); |
468 | } else { |
469 | lockscreen.hide(); |
470 | } |
471 | } |
472 | |
473 | - Showable { |
474 | + LoginPage { |
475 | id: lockscreen |
476 | objectName: "lockscreen" |
477 | anchors.fill: parent |
478 | shown: false |
479 | opacity: 0 |
480 | |
481 | - showAnimation: StandardAnimation { property: "opacity"; to: 1 } |
482 | - hideAnimation: StandardAnimation { property: "opacity"; to: 0 } |
483 | - |
484 | - Wallpaper { |
485 | - id: lockscreenBackground |
486 | - objectName: "lockscreenBackground" |
487 | - anchors { |
488 | - fill: parent |
489 | - topMargin: root.backgroundTopMargin |
490 | - } |
491 | - source: root.background |
492 | - } |
493 | - |
494 | - // Darken background to match CoverPage |
495 | - Rectangle { |
496 | - objectName: "lockscreenShade" |
497 | - anchors.fill: parent |
498 | - color: "black" |
499 | - opacity: root.hasCustomBackground ? 0.4 : 0 |
500 | - } |
501 | - |
502 | - LoginList { |
503 | - id: loginList |
504 | - objectName: "loginList" |
505 | - |
506 | - anchors { |
507 | - horizontalCenter: parent.horizontalCenter |
508 | - top: parent.top |
509 | - bottom: parent.bottom |
510 | - } |
511 | - width: units.gu(40) |
512 | - boxVerticalOffset: units.gu(14) |
513 | - enabled: !coverPage.shown && visible |
514 | - visible: !delayedLockscreen.visible |
515 | - |
516 | - locked: root.locked |
517 | - |
518 | - onSelected: if (enabled) root.selected(index) |
519 | - onResponded: root.responded(response) |
520 | - } |
521 | - |
522 | - DelayedLockscreen { |
523 | - id: delayedLockscreen |
524 | - objectName: "delayedLockscreen" |
525 | - anchors.fill: parent |
526 | - visible: delayMinutes > 0 |
527 | - alphaNumeric: loginList.alphanumeric |
528 | - } |
529 | - |
530 | - function maybeShow() { |
531 | - if (root.locked && !shown) { |
532 | - showNow(); |
533 | - } |
534 | - } |
535 | + hasCancel: true |
536 | + covered: coverPage.shown |
537 | + promptHorizontalCenterOffset: width / 2 |
538 | + promptVerticalCenterOffset: Math.min(units.gu(14) + promptHeight / 2, |
539 | + height / 2 - promptHeight / 2 - units.gu(1) - bottomBar.height) |
540 | + inputMethod: root.inputMethod |
541 | + dragHandleLeftMargin: root.dragHandleLeftMargin |
542 | + |
543 | + onCancel: coverPage.show() |
544 | + onEmergencyCall: root.emergencyCall() |
545 | + onSelected: root.selected(index) |
546 | + onResponded: root.responded(response) |
547 | } |
548 | |
549 | Rectangle { |
550 | @@ -176,29 +123,24 @@ |
551 | objectName: "coverPage" |
552 | height: parent.height |
553 | width: parent.width |
554 | + |
555 | background: root.background |
556 | + backgroundTopMargin: root.backgroundTopMargin |
557 | hasCustomBackground: root.hasCustomBackground |
558 | draggable: !root.waiting |
559 | + |
560 | onTease: root.tease() |
561 | onClicked: hide() |
562 | |
563 | onShowProgressChanged: { |
564 | if (showProgress === 0) { |
565 | if (lockscreen.shown) { |
566 | - loginList.tryToUnlock(); |
567 | + lockscreen.tryToUnlock(); |
568 | } else { |
569 | root.responded(""); |
570 | } |
571 | } |
572 | } |
573 | - |
574 | - Clock { |
575 | - anchors { |
576 | - top: parent.top |
577 | - topMargin: units.gu(2) |
578 | - horizontalCenter: parent.horizontalCenter |
579 | - } |
580 | - } |
581 | } |
582 | |
583 | StyledItem { |
584 | |
585 | === modified file 'qml/Greeter/WideView.qml' |
586 | --- qml/Greeter/WideView.qml 2017-01-23 14:28:42 +0000 |
587 | +++ qml/Greeter/WideView.qml 2017-03-22 18:36:14 +0000 |
588 | @@ -22,23 +22,29 @@ |
589 | id: root |
590 | focus: true |
591 | |
592 | - property alias background: coverPage.background |
593 | - property alias backgroundTopMargin: coverPage.backgroundTopMargin |
594 | - property alias hasCustomBackground: coverPage.hasCustomBackground |
595 | - property alias dragHandleLeftMargin: coverPage.dragHandleLeftMargin |
596 | - property alias infographicModel: coverPage.infographicModel |
597 | - property alias launcherOffset: coverPage.launcherOffset |
598 | - property alias currentIndex: loginList.currentIndex |
599 | - property int delayMinutes // TODO |
600 | - property alias alphanumeric: loginList.alphanumeric |
601 | - property alias locked: loginList.locked |
602 | - property alias sessionToStart: loginList.currentSession |
603 | - property alias waiting: loginList.waiting |
604 | - property var userModel // Set from outside |
605 | + property alias background: lockscreen.background |
606 | + property alias backgroundTopMargin: lockscreen.backgroundTopMargin |
607 | + property alias hasCustomBackground: lockscreen.hasCustomBackground |
608 | + property alias dragHandleLeftMargin: lockscreen.dragHandleLeftMargin |
609 | + property alias infographicModel: infographics.model |
610 | + property real launcherOffset // unused |
611 | + property real launcherLockedWidth |
612 | + property alias currentIndex: lockscreen.currentIndex |
613 | + property alias delayMinutes: lockscreen.delayMinutes |
614 | + property alias alphanumeric: lockscreen.alphanumeric |
615 | + property alias locked: lockscreen.locked |
616 | + property alias sessionToStart: lockscreen.currentSession |
617 | + property alias waiting: lockscreen.waiting |
618 | + property alias userModel: lockscreen.userModel |
619 | + property bool oskEnabled |
620 | |
621 | - readonly property bool animating: coverPage.showAnimation.running || coverPage.hideAnimation.running |
622 | - readonly property bool fullyShown: coverPage.showProgress === 1 |
623 | - readonly property bool required: coverPage.required |
624 | + readonly property bool animating: false |
625 | + readonly property bool fullyShown: lockscreen.shown |
626 | + readonly property bool required: lockscreen.required |
627 | + readonly property int supportedOrientations: Qt.PortraitOrientation | |
628 | + Qt.LandscapeOrientation | |
629 | + Qt.InvertedPortraitOrientation | |
630 | + Qt.InvertedLandscapeOrientation |
631 | |
632 | // so that it can be replaced in tests with a mock object |
633 | property var inputMethod: Qt.inputMethod |
634 | @@ -48,8 +54,21 @@ |
635 | signal tease() |
636 | signal emergencyCall() // unused |
637 | |
638 | + function hide() { |
639 | + lockscreen.hide(); |
640 | + } |
641 | + |
642 | + function showFakePassword() { |
643 | + lockscreen.showFakePassword(); |
644 | + } |
645 | + |
646 | function notifyAuthenticationFailed() { |
647 | - loginList.showError(); |
648 | + lockscreen.notifyAuthenticationFailed(); |
649 | + } |
650 | + |
651 | + function showErrorMessage(msg) { |
652 | + // Unused, only for optional coverPage message when prompt is covered, |
653 | + // but we always show prompt, so we don't need this. |
654 | } |
655 | |
656 | function forceShow() { |
657 | @@ -57,153 +76,53 @@ |
658 | } |
659 | |
660 | function tryToUnlock(toTheRight) { |
661 | - if (root.locked) { |
662 | - coverPage.show(); |
663 | - loginList.tryToUnlock(); |
664 | - return false; |
665 | - } else { |
666 | - var coverChanged = coverPage.shown; |
667 | - if (toTheRight) { |
668 | - coverPage.hideRight(); |
669 | - } else { |
670 | - coverPage.hide(); |
671 | - } |
672 | - return coverChanged; |
673 | - } |
674 | - } |
675 | - |
676 | - function hide() { |
677 | - coverPage.hide(); |
678 | - } |
679 | - |
680 | - function showFakePassword() { |
681 | - loginList.showFakePassword(); |
682 | - } |
683 | - |
684 | - function showLastChance() { |
685 | - // TODO |
686 | - } |
687 | - |
688 | - Rectangle { |
689 | + lockscreen.tryToUnlock(); |
690 | + return false; |
691 | + } |
692 | + |
693 | + QtObject { |
694 | + id: d |
695 | + property bool landscape: root.width > root.height |
696 | + } |
697 | + |
698 | + LoginPage { |
699 | + id: lockscreen |
700 | + objectName: "lockscreen" |
701 | anchors.fill: parent |
702 | - color: "black" |
703 | - opacity: coverPage.showProgress * 0.8 |
704 | - } |
705 | - |
706 | - CoverPage { |
707 | - id: coverPage |
708 | - objectName: "coverPage" |
709 | - height: parent.height |
710 | - width: parent.width |
711 | - draggable: !root.locked && !root.waiting |
712 | - state: "LoginList" |
713 | - |
714 | - infographics { |
715 | - height: 0.75 * parent.height |
716 | - anchors.leftMargin: loginList.x + loginList.width |
717 | - } |
718 | - |
719 | - onTease: root.tease() |
720 | - |
721 | - onShowProgressChanged: { |
722 | - if (showProgress === 0 && !root.locked) { |
723 | - root.responded(""); |
724 | - } |
725 | - } |
726 | - |
727 | - LoginList { |
728 | - id: loginList |
729 | - objectName: "loginList" |
730 | - |
731 | - width: units.gu(40) |
732 | - anchors { |
733 | - left: parent.left |
734 | - leftMargin: Math.min(parent.width * 0.16, units.gu(20)) |
735 | - top: parent.top |
736 | - bottom: parent.bottom |
737 | - } |
738 | - |
739 | - boxVerticalOffset: (height - highlightedHeight - |
740 | - (inputMethod && inputMethod.visible ? |
741 | - inputMethod.keyboardRectangle.height : 0)) / 2 |
742 | - Behavior on boxVerticalOffset { UbuntuNumberAnimation {} } |
743 | - |
744 | - model: root.userModel |
745 | - onResponded: root.responded(response) |
746 | - onSelected: root.selected(index) |
747 | - onSessionChooserButtonClicked: parent.state = "SessionsList" |
748 | - onCurrentIndexChanged: setCurrentSession() |
749 | - |
750 | - Keys.forwardTo: [sessionChooserLoader.item] |
751 | - |
752 | - Component.onCompleted: setCurrentSession() |
753 | - |
754 | - function setCurrentSession() { |
755 | - currentSession = LightDMService.users.data(currentIndex, LightDMService.userRoles.SessionRole); |
756 | - } |
757 | - } |
758 | - |
759 | - Loader { |
760 | - id: sessionChooserLoader |
761 | - |
762 | - height: loginList.height |
763 | - width: loginList.width |
764 | - anchors { |
765 | - left: parent.left |
766 | - leftMargin: Math.min(parent.width * 0.16, units.gu(20)) |
767 | - top: parent.top |
768 | - } |
769 | - |
770 | - active: false |
771 | - |
772 | - onLoaded: sessionChooserLoader.item.forceActiveFocus(); |
773 | - Binding { |
774 | - target: sessionChooserLoader.item |
775 | - property: "initiallySelectedSession" |
776 | - value: loginList.currentSession |
777 | - } |
778 | - |
779 | - Connections { |
780 | - target: sessionChooserLoader.item |
781 | - onSessionSelected: loginList.currentSession = sessionKey |
782 | - onShowLoginList: { |
783 | - coverPage.state = "LoginList" |
784 | - loginList.tryToUnlock(); |
785 | - } |
786 | - ignoreUnknownSignals: true |
787 | - } |
788 | - } |
789 | - |
790 | - states: [ |
791 | - State { |
792 | - name: "SessionsList" |
793 | - PropertyChanges { target: loginList; opacity: 0 } |
794 | - PropertyChanges { target: sessionChooserLoader; |
795 | - active: true; |
796 | - opacity: 1 |
797 | - source: "SessionsList.qml" |
798 | - } |
799 | - }, |
800 | - |
801 | - State { |
802 | - name: "LoginList" |
803 | - PropertyChanges { target: loginList; opacity: 1 } |
804 | - PropertyChanges { target: sessionChooserLoader; |
805 | - active: false; |
806 | - opacity: 0 |
807 | - source: ""; |
808 | - } |
809 | - } |
810 | - ] |
811 | - |
812 | - transitions: [ |
813 | - Transition { |
814 | - from: "*" |
815 | - to: "*" |
816 | - UbuntuNumberAnimation { |
817 | - property: "opacity"; |
818 | - } |
819 | - } |
820 | - ] |
821 | + |
822 | + property real layoutWidth: width - root.launcherLockedWidth |
823 | + promptHorizontalCenterOffset: root.launcherLockedWidth + |
824 | + (d.landscape ? layoutWidth / 4 : layoutWidth / 2) |
825 | + promptVerticalCenterOffset: d.landscape && !root.oskEnabled ? |
826 | + height / 2 : |
827 | + Math.min(units.gu(21) + promptHeight / 2, |
828 | + height / 2 - promptHeight / 2 - units.gu(1)) |
829 | + inputMethod: root.inputMethod |
830 | + |
831 | + onEmergencyCall: root.emergencyCall() |
832 | + onSelected: root.selected(index) |
833 | + onResponded: root.responded(response) |
834 | + onClicked: root.tease() |
835 | + |
836 | + Infographics { |
837 | + id: infographics |
838 | + objectName: "infographics" |
839 | + |
840 | + readonly property real promptBottom: lockscreen.promptVerticalCenterOffset + lockscreen.promptHeight / 2 |
841 | + |
842 | + width: Math.min(units.gu(50), |
843 | + d.landscape ? 0.5 * parent.layoutWidth : 0.64 * (lockscreen.height - promptBottom), |
844 | + parent.layoutWidth, |
845 | + parent.height) |
846 | + height: width |
847 | + |
848 | + anchors { |
849 | + horizontalCenter: parent.right |
850 | + horizontalCenterOffset: root.launcherLockedWidth - lockscreen.promptHorizontalCenterOffset |
851 | + |
852 | + verticalCenter: parent.verticalCenter |
853 | + verticalCenterOffset: d.landscape ? 0 : promptBottom / 2 |
854 | + } |
855 | + } |
856 | } |
857 | } |
858 | |
859 | === modified file 'qml/Launcher/Launcher.qml' |
860 | --- qml/Launcher/Launcher.qml 2017-02-24 10:44:53 +0000 |
861 | +++ qml/Launcher/Launcher.qml 2017-03-22 18:36:14 +0000 |
862 | @@ -134,14 +134,14 @@ |
863 | } |
864 | |
865 | function tease() { |
866 | - if (available && !dragArea.dragging) { |
867 | + if (!lockedVisible && available && !dragArea.dragging) { |
868 | teaseTimer.mode = "teasing" |
869 | teaseTimer.start(); |
870 | } |
871 | } |
872 | |
873 | function hint() { |
874 | - if (available && root.state == "") { |
875 | + if (!lockedVisible && available && root.state == "") { |
876 | teaseTimer.mode = "hinting" |
877 | teaseTimer.start(); |
878 | } |
879 | |
880 | === modified file 'qml/Rotation/RotationStates.qml' |
881 | --- qml/Rotation/RotationStates.qml 2016-11-28 16:32:56 +0000 |
882 | +++ qml/Rotation/RotationStates.qml 2017-03-22 18:36:14 +0000 |
883 | @@ -140,8 +140,7 @@ |
884 | // There's no point in animating if the user can't see it (display is off). |
885 | d.animationType = d.noAnimation; |
886 | } else if (root.shell.showingGreeter) { |
887 | - // A rotating greeter looks weird. |
888 | - d.animationType = d.noAnimation; |
889 | + d.animationType = d.fullAnimation; |
890 | } else { |
891 | if (!root.shell.mainApp) { |
892 | // shouldn't happen but, anyway |
893 | |
894 | === modified file 'qml/Shell.qml' |
895 | --- qml/Shell.qml 2017-02-21 16:21:34 +0000 |
896 | +++ qml/Shell.qml 2017-03-22 18:36:14 +0000 |
897 | @@ -87,29 +87,27 @@ |
898 | if (startingUp) { |
899 | // Ensure we don't rotate during start up |
900 | return Qt.PrimaryOrientation; |
901 | - } else if (showingGreeter || notifications.topmostIsFullscreen) { |
902 | + } else if (notifications.topmostIsFullscreen) { |
903 | return Qt.PrimaryOrientation; |
904 | + } else if (showingGreeter) { |
905 | + return shell.orientations.map(greeter.supportedOrientations); |
906 | } else { |
907 | return shell.orientations.map(stage.supportedOrientations); |
908 | } |
909 | } |
910 | |
911 | - readonly property var mainApp: stage.mainApp |
912 | - |
913 | - onMainAppChanged: { |
914 | - if (mainApp) { |
915 | - _onMainAppChanged(mainApp.appId); |
916 | - } |
917 | - } |
918 | Connections { |
919 | target: ApplicationManager |
920 | onFocusRequested: { |
921 | - if (shell.mainApp && shell.mainApp.appId === appId) { |
922 | - _onMainAppChanged(appId); |
923 | + if (ApplicationManager.focusedApplicationId === appId) { |
924 | + _onFocusChanged(ApplicationManager.focusedApplicationId); |
925 | } |
926 | } |
927 | + onFocusedApplicationIdChanged: { |
928 | + _onFocusChanged(ApplicationManager.focusedApplicationId); |
929 | + } |
930 | } |
931 | - function _onMainAppChanged(appId) { |
932 | + function _onFocusChanged(appId) { |
933 | if (wizard.active && appId != "" && appId != "unity8-dash") { |
934 | // If this happens on first boot, we may be in the |
935 | // wizard while receiving a call. But a call is more |
936 | @@ -129,8 +127,9 @@ |
937 | launcher.hide(launcher.ignoreHideIfMouseOverLauncher); |
938 | } |
939 | |
940 | - // For autopilot consumption |
941 | + // For autopilot and test consumption |
942 | readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId |
943 | + readonly property var mainApp: stage.mainApp |
944 | |
945 | // Note when greeter is waiting on PAM, so that we can disable edges until |
946 | // we know which user data to show and whether the session is locked. |
947 | @@ -394,12 +393,14 @@ |
948 | enabled: panel.indicators.fullyClosed // hides OSK when panel is open |
949 | hides: [launcher, panel.indicators, panel.applicationMenus] |
950 | tabletMode: shell.usageScenario != "phone" |
951 | + launcherLockedWidth: launcher.lockedVisible ? launcher.panelWidth : 0 |
952 | forcedUnlock: wizard.active || shell.mode === "full-shell" |
953 | background: wallpaperResolver.cachedBackground |
954 | hasCustomBackground: wallpaperResolver.hasCustomBackground |
955 | allowFingerprint: !dialogs.hasActiveDialog && |
956 | !notifications.topmostIsFullscreen && |
957 | !panel.indicators.shown |
958 | + oskEnabled: shell.oskEnabled |
959 | |
960 | // avoid overlapping with Launcher's edge drag area |
961 | // FIXME: Fix TouchRegistry & friends and remove this workaround |
962 | |
963 | === modified file 'tests/qmltests/Greeter/TestView.qml' |
964 | --- tests/qmltests/Greeter/TestView.qml 2017-01-19 15:37:24 +0000 |
965 | +++ tests/qmltests/Greeter/TestView.qml 2017-03-22 18:36:14 +0000 |
966 | @@ -36,10 +36,12 @@ |
967 | readonly property bool fullyShown: _fullyShown |
968 | readonly property bool required: _required |
969 | readonly property bool animating: _animating |
970 | + readonly property int supportedOrientations: _supportedOrientations |
971 | |
972 | property bool _fullyShown: true |
973 | property bool _required: true |
974 | - property bool _animating: true |
975 | + property bool _animating: false |
976 | + property int _supportedOrientations: Qt.PrimaryOrientation |
977 | |
978 | signal selected(int index) |
979 | signal responded(string response) |
980 | |
981 | === modified file 'tests/qmltests/Greeter/tst_Greeter.qml' |
982 | --- tests/qmltests/Greeter/tst_Greeter.qml 2017-01-19 17:52:57 +0000 |
983 | +++ tests/qmltests/Greeter/tst_Greeter.qml 2017-03-22 18:36:14 +0000 |
984 | @@ -312,6 +312,14 @@ |
985 | verify(view.hasCustomBackground); |
986 | } |
987 | |
988 | + function test_supportedOrientationsPassthrough() { |
989 | + view._supportedOrientations = Qt.InvertedLandscapeOrientation; |
990 | + compare(greeter.supportedOrientations, Qt.InvertedLandscapeOrientation); |
991 | + |
992 | + view._supportedOrientations = Qt.PrimaryOrientation | Qt.PortraitOrientation; |
993 | + compare(greeter.supportedOrientations, Qt.PrimaryOrientation | Qt.PortraitOrientation); |
994 | + } |
995 | + |
996 | function test_notifyAboutToFocusApp() { |
997 | greeter.notifyUserRequestedApp("fake-app"); |
998 | compare(viewTryToUnlockSpy.count, 1); |
999 | |
1000 | === modified file 'tests/qmltests/Greeter/tst_NarrowView.qml' |
1001 | --- tests/qmltests/Greeter/tst_NarrowView.qml 2017-01-19 15:37:24 +0000 |
1002 | +++ tests/qmltests/Greeter/tst_NarrowView.qml 2017-03-22 18:36:14 +0000 |
1003 | @@ -444,9 +444,7 @@ |
1004 | var dataCircle = findChild(view, "dataCircle"); |
1005 | verify(dataCircle); |
1006 | |
1007 | - tap(dataCircle); |
1008 | - wait(1); |
1009 | - tap(dataCircle); |
1010 | + mouseDoubleClick(dataCircle); |
1011 | |
1012 | tryCompare(infographicDataChangedSpy, "count", 1); |
1013 | } |
1014 | |
1015 | === modified file 'tests/qmltests/Greeter/tst_WideView.qml' |
1016 | --- tests/qmltests/Greeter/tst_WideView.qml 2017-02-28 16:49:40 +0000 |
1017 | +++ tests/qmltests/Greeter/tst_WideView.qml 2017-03-22 18:36:14 +0000 |
1018 | @@ -26,7 +26,7 @@ |
1019 | StyledItem { |
1020 | id: root |
1021 | |
1022 | - width: units.gu(120) |
1023 | + width: units.gu(140) |
1024 | height: units.gu(80) |
1025 | focus: true |
1026 | |
1027 | @@ -55,6 +55,7 @@ |
1028 | backgroundTopMargin: parseFloat(backgroundTopMarginField.text) |
1029 | locked: lockedCheckBox.checked |
1030 | inputMethod: fakeInputMethod |
1031 | + sessionToStart: LightDMService.greeter.defaultSession |
1032 | |
1033 | Component.onDestruction: { |
1034 | loader.itemDestroyed = true |
1035 | @@ -386,15 +387,6 @@ |
1036 | return i; |
1037 | } |
1038 | |
1039 | - function swipeAwayCover() { |
1040 | - tryCompare(view, "fullyShown", true); |
1041 | - var touchY = view.height / 2; |
1042 | - touchFlick(view, view.width, touchY, 0, touchY); |
1043 | - var coverPage = findChild(view, "coverPage"); |
1044 | - tryCompare(coverPage, "showProgress", 0); |
1045 | - waitForRendering(view); |
1046 | - } |
1047 | - |
1048 | function test_changingSessionSticksToUser() { |
1049 | var loginList = findChild(view, "loginList"); |
1050 | |
1051 | @@ -410,11 +402,10 @@ |
1052 | |
1053 | function test_tease_data() { |
1054 | return [ |
1055 | - {tag: "locked", x: 0, offset: 0, count: 0, locked: true}, |
1056 | - {tag: "left", x: 0, offset: 0, count: 1, locked: false}, |
1057 | - {tag: "leftWithOffsetPass", x: 10, offset: 10, count: 1, locked: false}, |
1058 | - {tag: "leftWithOffsetFail", x: 9, offset: 10, count: 0, locked: false}, |
1059 | - {tag: "right", x: view.width, offset: 0, count: 1, locked: false}, |
1060 | + {tag: "left", x: 0, offset: 0, count: 1}, |
1061 | + {tag: "leftWithOffsetPass", x: 10, offset: 10, count: 1}, |
1062 | + {tag: "leftWithOffsetFail", x: 9, offset: 10, count: 0}, |
1063 | + {tag: "right", x: view.width, offset: 0, count: 1}, |
1064 | ] |
1065 | } |
1066 | |
1067 | @@ -431,8 +422,8 @@ |
1068 | compare(icon.indexOf(session) > -1, true); |
1069 | |
1070 | // Test the session list icons are valid |
1071 | - var coverPage = findChild(view, "coverPage"); |
1072 | - coverPage.state = "SessionsList" |
1073 | + var lockscreen = findChild(view, "lockscreen"); |
1074 | + lockscreen.state = "SessionsList"; |
1075 | var sessionsList = findChild(view, "sessionsList"); |
1076 | tryCompare(sessionsList, "visible", true); |
1077 | } |
1078 | @@ -495,7 +486,6 @@ |
1079 | } |
1080 | |
1081 | function test_tease(data) { |
1082 | - view.locked = data.locked; |
1083 | view.dragHandleLeftMargin = data.offset; |
1084 | tap(view, data.x, 0); |
1085 | compare(teaseSpy.count, data.count); |
1086 | @@ -510,14 +500,14 @@ |
1087 | } |
1088 | |
1089 | function test_customBackground() { |
1090 | - var coverPage = findChild(view, "coverPage"); |
1091 | - var backgroundShade = findChild(coverPage, "backgroundShade"); |
1092 | + var lockscreen = findChild(view, "lockscreen"); |
1093 | + var lockscreenShade = findChild(lockscreen, "lockscreenShade"); |
1094 | |
1095 | verify(!view.hasCustomBackground); |
1096 | - verify(!backgroundShade.visible); |
1097 | + compare(lockscreenShade.opacity, 0); |
1098 | |
1099 | view.hasCustomBackground = true; |
1100 | - verify(backgroundShade.visible); |
1101 | + compare(lockscreenShade.opacity, 0.4); |
1102 | } |
1103 | |
1104 | function test_respondedWithPassword() { |
1105 | @@ -540,21 +530,9 @@ |
1106 | compare(respondedSpy.signalArguments[0][0], "foo"); |
1107 | } |
1108 | |
1109 | - function test_respondedWithSwipe() { |
1110 | - swipeAwayCover(); |
1111 | - compare(respondedSpy.count, 1); |
1112 | - compare(respondedSpy.signalArguments[0][0], ""); |
1113 | - } |
1114 | - |
1115 | - function test_fullyShown() { |
1116 | - tryCompare(view, "fullyShown", true); |
1117 | - swipeAwayCover(); |
1118 | - tryCompare(view, "fullyShown", false); |
1119 | - } |
1120 | - |
1121 | function test_required() { |
1122 | tryCompare(view, "required", true); |
1123 | - swipeAwayCover(); |
1124 | + view.hide(); |
1125 | tryCompare(view, "required", false); |
1126 | } |
1127 | |
1128 | @@ -647,29 +625,24 @@ |
1129 | compare(respondedSpy.signalArguments[0][0], ""); |
1130 | } |
1131 | |
1132 | - function test_loginListNotCoveredByKeyboard() { |
1133 | - var loginList = findChild(view, "loginList"); |
1134 | - compare(loginList.height, view.height); |
1135 | - |
1136 | - // when the vkb shows up, loginList is moved up to remain fully uncovered |
1137 | - |
1138 | - keyboardVisibleCheckBox.checked = true; |
1139 | - |
1140 | - var halfway = (view.height - loginList.highlightedHeight) / 2; |
1141 | - var halfwayWithOsk = halfway - view.inputMethod.keyboardRectangle.height / 2; |
1142 | - tryCompare(loginList, "boxVerticalOffset", halfwayWithOsk); |
1143 | - |
1144 | - var highlightItem = findChild(loginList, "highlightItem"); |
1145 | - tryCompareFunction( function() { |
1146 | - var highlightRect = highlightItem.mapToItem(view, 0, 0, highlightItem.width, highlightItem.height); |
1147 | - return highlightRect.y + highlightRect.height <= view.inputMethod.keyboardRectangle.y; |
1148 | - }, true); |
1149 | - |
1150 | - // once the vkb goes away, loginList goes back to its full height |
1151 | - |
1152 | - keyboardVisibleCheckBox.checked = false; |
1153 | - |
1154 | - tryCompare(loginList, "boxVerticalOffset", halfway); |
1155 | + function test_loginListNotCoveredByKeyboard_data() { |
1156 | + return [ |
1157 | + {tag: "keyboard", oskEnabled: false}, |
1158 | + {tag: "osk", oskEnabled: true}, |
1159 | + ] |
1160 | + } |
1161 | + function test_loginListNotCoveredByKeyboard(data) { |
1162 | + var lockscreen = findChild(view, "lockscreen"); |
1163 | + view.oskEnabled = data.oskEnabled; |
1164 | + |
1165 | + if (data.oskEnabled) { |
1166 | + // Actual algorithm is a bit complicated, just make sure we're less than halfway |
1167 | + tryCompareFunction( function() { |
1168 | + return lockscreen.promptVerticalCenterOffset < view.height / 2; |
1169 | + }, true); |
1170 | + } else { |
1171 | + tryCompare(lockscreen, "promptVerticalCenterOffset", view.height / 2); |
1172 | + } |
1173 | } |
1174 | |
1175 | function test_passphrase() { |
1176 | |
1177 | === modified file 'tests/qmltests/tst_OrientedShell.qml' |
1178 | --- tests/qmltests/tst_OrientedShell.qml 2017-03-08 09:50:45 +0000 |
1179 | +++ tests/qmltests/tst_OrientedShell.qml 2017-03-22 18:36:14 +0000 |
1180 | @@ -591,11 +591,20 @@ |
1181 | compare(shell.transformRotationAngle, root.primaryOrientationAngle + 180); |
1182 | } |
1183 | |
1184 | + function checkRotationAngle(angle, shellRotates) { |
1185 | + rotateTo(angle); |
1186 | + var expectedAngle = root.primaryOrientationAngle; |
1187 | + if (shellRotates) { |
1188 | + expectedAngle = (expectedAngle + angle) % 360; |
1189 | + } |
1190 | + tryCompare(shell, "transformRotationAngle", expectedAngle); |
1191 | + } |
1192 | + |
1193 | function test_greeterRemainsInPrimaryOrientation_data() { |
1194 | return [ |
1195 | - {tag: "mako", deviceName: "mako"}, |
1196 | - {tag: "manta", deviceName: "manta"}, |
1197 | - {tag: "flo", deviceName: "flo"} |
1198 | + {tag: "mako", deviceName: "mako", rotates: false}, |
1199 | + {tag: "manta", deviceName: "manta", rotates: true}, |
1200 | + {tag: "flo", deviceName: "flo", rotates: true} |
1201 | ]; |
1202 | } |
1203 | function test_greeterRemainsInPrimaryOrientation(data) { |
1204 | @@ -613,18 +622,14 @@ |
1205 | tryCompare(shell, "orientationChangesEnabled", true); |
1206 | |
1207 | compare(shell.transformRotationAngle, root.primaryOrientationAngle); |
1208 | - rotateTo(90); |
1209 | - tryCompare(shell, "transformRotationAngle", root.primaryOrientationAngle + 90); |
1210 | + checkRotationAngle(90, true); |
1211 | |
1212 | showGreeter(); |
1213 | |
1214 | - tryCompare(shell, "transformRotationAngle", root.primaryOrientationAngle); |
1215 | - rotateTo(180); |
1216 | - compare(shell.transformRotationAngle, root.primaryOrientationAngle); |
1217 | - rotateTo(270); |
1218 | - compare(shell.transformRotationAngle, root.primaryOrientationAngle); |
1219 | - rotateTo(0); |
1220 | - compare(shell.transformRotationAngle, root.primaryOrientationAngle); |
1221 | + checkRotationAngle(90, data.rotates); |
1222 | + checkRotationAngle(180, data.rotates); |
1223 | + checkRotationAngle(270, data.rotates); |
1224 | + checkRotationAngle(0, data.rotates); |
1225 | } |
1226 | |
1227 | function test_appRotatesWindowContents_data() { |
1228 | @@ -1437,9 +1442,13 @@ |
1229 | tryCompare(greeter, "fullyShown", true); |
1230 | waitForRendering(greeter) |
1231 | |
1232 | - var touchX = shell.width * .75; |
1233 | - var touchY = shell.height / 2; |
1234 | - touchFlick(shell, touchX, touchY, shell.width * 0.1, touchY); |
1235 | + if (greeter.tabletMode) { |
1236 | + tap(findChild(greeter, "promptButton")); |
1237 | + } else { |
1238 | + var touchX = shell.width * .75; |
1239 | + var touchY = shell.height / 2; |
1240 | + touchFlick(shell, touchX, touchY, shell.width * 0.1, touchY); |
1241 | + } |
1242 | |
1243 | // wait until the animation has finished |
1244 | tryCompare(greeter, "shown", false); |
1245 | @@ -1483,15 +1492,12 @@ |
1246 | |
1247 | function waitForGreeterToStabilize() { |
1248 | var greeter = findChild(shell, "greeter"); |
1249 | - verify(greeter); |
1250 | + tryCompare(greeter, "created", true); |
1251 | + waitForRendering(greeter); |
1252 | |
1253 | var loginList = findChild(greeter, "loginList"); |
1254 | - // Only present in WideView |
1255 | - if (loginList) { |
1256 | - var userList = findChild(loginList, "userList"); |
1257 | - verify(userList); |
1258 | - tryCompare(userList, "movingInternally", false); |
1259 | - } |
1260 | + var userList = findChild(loginList, "userList"); |
1261 | + tryCompare(userList, "movingInternally", false); |
1262 | } |
1263 | |
1264 | // expectedAngle is in orientedShell's coordinate system |
1265 | |
1266 | === modified file 'tests/qmltests/tst_Shell.qml' |
1267 | --- tests/qmltests/tst_Shell.qml 2017-03-08 09:54:00 +0000 |
1268 | +++ tests/qmltests/tst_Shell.qml 2017-03-22 18:36:14 +0000 |
1269 | @@ -45,7 +45,7 @@ |
1270 | id: root |
1271 | color: "grey" |
1272 | width: units.gu(100) + controls.width |
1273 | - height: units.gu(71) |
1274 | + height: units.gu(100) |
1275 | |
1276 | Component.onCompleted: { |
1277 | // must set the mock mode before loading the Shell |
1278 | @@ -109,6 +109,14 @@ |
1279 | } |
1280 | }, |
1281 | State { |
1282 | + name: "tablet-rotated" |
1283 | + PropertyChanges { |
1284 | + target: shellLoader |
1285 | + width: units.gu(71) |
1286 | + height: units.gu(100) |
1287 | + } |
1288 | + }, |
1289 | + State { |
1290 | name: "desktop" |
1291 | PropertyChanges { |
1292 | target: shellLoader |
1293 | @@ -261,7 +269,7 @@ |
1294 | id: sizeSelector |
1295 | anchors { left: parent.left; right: parent.right } |
1296 | activeFocusOnPress: false |
1297 | - model: ["phone", "tablet", "desktop"] |
1298 | + model: ["phone", "tablet", "tablet-rotated", "desktop"] |
1299 | onSelectedIndexChanged: { |
1300 | shellLoader.state = model[selectedIndex]; |
1301 | } |
1302 | @@ -581,6 +589,8 @@ |
1303 | shellLoader.state = formFactor; |
1304 | shellLoader.active = true; |
1305 | tryCompare(shellLoader, "status", Loader.Ready); |
1306 | + shell.usageScenario = formFactor; |
1307 | + |
1308 | removeTimeConstraintsFromSwipeAreas(shellLoader.item); |
1309 | tryCompare(shell, "waitingOnGreeter", false); // reset by greeter when ready |
1310 | |
1311 | @@ -605,13 +615,13 @@ |
1312 | // wait until unity8-dash is fully loaded |
1313 | tryCompare(topLevelSurfaceList, "count", 1); |
1314 | waitUntilAppWindowIsFullyLoaded(topLevelSurfaceList.idAt(0)); |
1315 | + |
1316 | + waitForRendering(shell); |
1317 | } |
1318 | |
1319 | function loadDesktopShellWithApps() { |
1320 | loadShell("desktop"); |
1321 | - waitForRendering(shell) |
1322 | - shell.usageScenario = "desktop" |
1323 | - waitForRendering(shell) |
1324 | + swipeAwayGreeter(); |
1325 | var app1 = ApplicationManager.startApplication("dialer-app") |
1326 | var app2 = ApplicationManager.startApplication("webbrowser-app") |
1327 | var app3 = ApplicationManager.startApplication("camera-app") |
1328 | @@ -626,13 +636,11 @@ |
1329 | |
1330 | function waitForGreeterToStabilize() { |
1331 | var greeter = findChild(shell, "greeter"); |
1332 | - verify(greeter); |
1333 | + waitForRendering(greeter); |
1334 | |
1335 | var loginList = findChild(greeter, "loginList", 0 /* timeout */); |
1336 | - // Only present in WideView |
1337 | if (loginList) { |
1338 | var userList = findChild(loginList, "userList"); |
1339 | - verify(userList); |
1340 | tryCompare(userList, "movingInternally", false); |
1341 | } |
1342 | } |
1343 | @@ -675,6 +683,7 @@ |
1344 | |
1345 | GSettingsController.setLifecycleExemptAppids([]); |
1346 | GSettingsController.setPictureUri(""); |
1347 | + GSettingsController.setAutohideLauncher(false); |
1348 | } |
1349 | |
1350 | function ensureInputMethodSurface() { |
1351 | @@ -800,9 +809,13 @@ |
1352 | waitForGreeterToStabilize(); |
1353 | removeTimeConstraintsFromSwipeAreas(greeter); |
1354 | |
1355 | - var touchX = shell.width - (shell.edgeSize / 2); |
1356 | - var touchY = shell.height / 2; |
1357 | - touchFlick(shell, touchX, touchY, shell.width * 0.1, touchY); |
1358 | + if (greeter.tabletMode) { |
1359 | + tap(findChild(greeter, "promptButton")); |
1360 | + } else { |
1361 | + var touchX = shell.width - (shell.edgeSize / 2); |
1362 | + var touchY = shell.height / 2; |
1363 | + touchFlick(shell, touchX, touchY, shell.width * 0.1, touchY); |
1364 | + } |
1365 | |
1366 | // wait until the animation has finished |
1367 | tryCompare(greeter, "shown", false); |
1368 | @@ -1409,25 +1422,40 @@ |
1369 | |
1370 | function test_appLaunchDuringGreeter_data() { |
1371 | return [ |
1372 | - {tag: "auth error", user: "auth-error", loggedIn: false, passwordFocus: false}, |
1373 | - {tag: "without password", user: "no-password", loggedIn: true, passwordFocus: false}, |
1374 | - {tag: "with password", user: "has-password", loggedIn: false, passwordFocus: true}, |
1375 | + {tag: "full, auth error", mode: "full", shell: "tablet", user: "auth-error", loggedIn: false, passwordFocus: false}, |
1376 | + {tag: "full, no password, tablet", mode: "full", shell: "tablet", user: "no-password", loggedIn: false, passwordFocus: false}, |
1377 | + {tag: "full, no password, phone", mode: "full", shell: "phone", user: "no-password", loggedIn: false, passwordFocus: false}, |
1378 | + {tag: "single, no password, tablet", mode: "single", shell: "tablet", loggedIn: true}, |
1379 | + {tag: "single, no password, phone", mode: "single", shell: "phone", loggedIn: true}, |
1380 | + {tag: "single, with password, phone", mode: "single-passphrase", shell: "phone", loggedIn: false, passwordFocus: true}, |
1381 | ] |
1382 | } |
1383 | |
1384 | function test_appLaunchDuringGreeter(data) { |
1385 | - setLightDMMockMode("full"); |
1386 | - loadShell("tablet"); |
1387 | - |
1388 | - selectUser(data.user) |
1389 | + setLightDMMockMode(data.mode); |
1390 | + loadShell(data.shell); |
1391 | + |
1392 | + if (data.user) { |
1393 | + if (data.shell == "phone") { |
1394 | + var touchX = shell.width - (shell.edgeSize / 2); |
1395 | + var touchY = shell.height / 2; |
1396 | + touchFlick(shell, touchX, touchY, shell.width * 0.1, touchY); |
1397 | + var coverPage = findChild(shell, "coverPage"); |
1398 | + tryCompare(coverPage, "showProgress", 0); |
1399 | + } |
1400 | + selectUser(data.user); |
1401 | + } |
1402 | + |
1403 | + confirmLoggedIn(false); |
1404 | |
1405 | var greeter = findChild(shell, "greeter") |
1406 | - var app = ApplicationManager.startApplication("dialer-app") |
1407 | + ApplicationManager.startApplication("dialer-app"); |
1408 | |
1409 | confirmLoggedIn(data.loggedIn) |
1410 | |
1411 | - if (data.passwordFocus) { |
1412 | - var passwordInput = findChild(greeter, "promptField"); |
1413 | + if (!data.loggedIn) { |
1414 | + var inputName = data.passwordFocus ? "promptField" : "promptButton"; |
1415 | + var passwordInput = findChild(greeter, inputName); |
1416 | tryCompare(passwordInput, "focus", true) |
1417 | } |
1418 | } |
1419 | @@ -1534,8 +1562,7 @@ |
1420 | |
1421 | function test_altTabSwitchesFocus(data) { |
1422 | loadShell(data.shellType); |
1423 | - shell.usageScenario = data.shellType; |
1424 | - waitForRendering(root) |
1425 | + swipeAwayGreeter(); |
1426 | |
1427 | var desktopStage = findChild(shell, "stage"); |
1428 | verify(desktopStage != null) |
1429 | @@ -2143,11 +2170,9 @@ |
1430 | } |
1431 | |
1432 | function test_superTabToCycleLauncher(data) { |
1433 | + GSettingsController.setAutohideLauncher(!data.launcherLocked); |
1434 | loadShell("desktop"); |
1435 | - shell.usageScenario = "desktop"; |
1436 | - waitForRendering(shell); |
1437 | - GSettingsController.setAutohideLauncher(!data.launcherLocked); |
1438 | - waitForRendering(shell); |
1439 | + swipeAwayGreeter(); |
1440 | |
1441 | var stage = findChild(shell, "stage"); |
1442 | var launcher = findChild(shell, "launcher"); |
1443 | @@ -2184,6 +2209,9 @@ |
1444 | var shortcutHint = findChild(findChild(launcher, "launcherDelegate0"), "shortcutHint") |
1445 | var shortcutsOverlay = findChild(shell, "shortcutsOverlay"); |
1446 | |
1447 | + GSettingsController.setAutohideLauncher(true); |
1448 | + waitForRendering(shell); |
1449 | + |
1450 | compare(launcher.state, ""); |
1451 | keyPress(Qt.Key_Super_L, Qt.MetaModifier); |
1452 | waitForRendering(shortcutsOverlay); |
1453 | @@ -2261,7 +2289,7 @@ |
1454 | |
1455 | function test_fullscreenAppHidesLockedOutLauncher() { |
1456 | loadShell("desktop"); |
1457 | - shell.usageScenario = "desktop"; |
1458 | + swipeAwayGreeter(); |
1459 | |
1460 | var launcher = findChild(shell, "launcher"); |
1461 | var launcherPanel = findChild(launcher, "launcherPanel"); |
1462 | @@ -2515,8 +2543,7 @@ |
1463 | |
1464 | function test_dragPanelToRestoreMaximizedWindow() { |
1465 | loadShell("desktop"); |
1466 | - shell.usageScenario = "desktop"; |
1467 | - waitForRendering(shell); |
1468 | + swipeAwayGreeter(); |
1469 | var panel = findChild(shell, "windowControlArea"); |
1470 | verify(panel); |
1471 |
FAILED: Continuous integration, rev:2581 /unity8- jenkins. ubuntu. com/job/ lp-unity8- ci/2721/ /unity8- jenkins. ubuntu. com/job/ build/3575/ console /unity8- jenkins. ubuntu. com/job/ build-0- fetch/3603 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 3449/console /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= zesty/3449/ console /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 3449/console /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= zesty/3449/ console /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 3449/console /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= zesty/3449/ console
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild: /unity8- jenkins. ubuntu. com/job/ lp-unity8- ci/2721/ rebuild
https:/