2 * Copyright (C) 2013,2014,2015 Canonical, Ltd.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18import AccountsService 0.1
19import Ubuntu.Components 1.1
20import Ubuntu.SystemImage 0.1
21import Unity.Launcher 0.1
26 created: loader.status == Loader.Ready
28 property real dragHandleLeftMargin: 0
30 property url background
32 // How far to offset the top greeter layer during a launcher left-drag
33 property real launcherOffset
35 readonly property bool active: shown || hasLockedApp
36 readonly property bool fullyShown: loader.item ? loader.item.fullyShown : false
38 // True when the greeter is waiting for PAM or other setup process
39 readonly property alias waiting: d.waiting
41 property string lockedApp: ""
42 readonly property bool hasLockedApp: lockedApp !== ""
44 property bool forcedUnlock
45 readonly property bool locked: lightDM.greeter.active && !lightDM.greeter.authenticated && !forcedUnlock
47 property bool tabletMode
48 property url viewSource // only used for testing
50 property int maxFailedLogins: -1 // disabled by default for now, will enable via settings in future
51 property int failedLoginsDelayAttempts: 7 // number of failed logins
52 property real failedLoginsDelayMinutes: 5 // minutes of forced waiting
54 readonly property bool animating: loader.item ? loader.item.animating : false
57 signal sessionStarted()
58 signal emergencyCall()
60 function forceShow() {
65 function notifyAppFocused(appId) {
71 if (appId === lockedApp) {
72 hide(); // show locked app
75 d.startUnlock(false /* toTheRight */);
77 } else if (appId !== "unity8-dash") { // dash isn't started by user
78 d.startUnlock(false /* toTheRight */);
82 function notifyAboutToFocusApp(appId) {
87 // A hint that we're about to focus an app. This way we can look
88 // a little more responsive, rather than waiting for the above
89 // notifyAppFocused call. We also need this in case we have a locked
90 // app, in order to show lockscreen instead of new app.
91 d.startUnlock(false /* toTheRight */);
94 // This is a just a glorified notifyAboutToFocusApp(), but it does one
95 // other thing: it hides any cover pages to the RIGHT, because the user
96 // just came from a launcher drag starting on the left.
97 // It also returns a boolean value, indicating whether there was a visual
98 // change or not (the shell only wants to hide the launcher if there was
100 function notifyShowingDashFromDrag() {
105 return d.startUnlock(true /* toTheRight */);
108 LightDM{id:lightDM} // Provide backend access
112 readonly property bool multiUser: lightDM.users.count > 1
113 property int currentIndex
114 property bool waiting
116 // We want 'launcherOffset' to animate down to zero. But not to animate
117 // while being dragged. So ideally we change this only when the user
118 // lets go and launcherOffset drops to zero. But we need to wait for
119 // the behavior to be enabled first. So we cache the last known good
120 // launcherOffset value to cover us during that brief gap between
121 // release and the behavior turning on.
122 property real lastKnownPositiveOffset // set in a launcherOffsetChanged below
123 property real launcherOffsetProxy: (shown && !launcherOffsetProxyBehavior.enabled) ? lastKnownPositiveOffset : 0
124 Behavior on launcherOffsetProxy {
125 id: launcherOffsetProxyBehavior
126 enabled: launcherOffset === 0
127 UbuntuNumberAnimation {}
130 function selectUser(uid, reset) {
136 var user = lightDM.users.data(uid, lightDM.userRoles.NameRole);
137 AccountsService.user = user;
138 LauncherModel.setUser(user);
139 lightDM.greeter.authenticate(user); // always resets auth state
144 if (lightDM.greeter.startSessionSync()) {
147 loader.item.notifyAuthenticationSucceeded();
149 } else if (loader.item) {
150 loader.item.notifyAuthenticationFailed();
155 function startUnlock(toTheRight) {
157 return loader.item.tryToUnlock(toTheRight);
164 onLauncherOffsetChanged: {
165 if (launcherOffset > 0) {
166 d.lastKnownPositiveOffset = launcherOffset;
170 onForcedUnlockChanged: {
171 if (forcedUnlock && shown) {
172 // pretend we were just authenticated
173 loader.item.notifyAuthenticationSucceeded();
187 // We use a short interval and check against the system wall clock
188 // because we have to consider the case that the system is suspended
189 // for a few minutes. When we wake up, we want to quickly be correct.
192 property var delayTarget;
193 property int delayMinutes;
195 function forceDelay(delay /* in minutes */) {
196 delayTarget = new Date();
197 delayTarget.setTime(delayTarget.getTime() + delay * 60000);
198 delayMinutes = Math.ceil(delay);
203 var diff = delayTarget - new Date();
205 delayMinutes = Math.ceil(diff / 60000);
214 // Nothing should leak to items behind the greeter
215 MouseArea { anchors.fill: parent }
223 active: root.required
224 source: root.viewSource.toString() ? root.viewSource :
225 (d.multiUser || root.tabletMode) ? "WideView.qml" : "NarrowView.qml"
229 root.forceActiveFocus();
230 d.selectUser(d.currentIndex, true);
231 lightDM.infographic.readyForDataChange();
237 d.selectUser(index, true);
241 lightDM.greeter.respond(response);
243 if (lightDM.greeter.active && !lightDM.greeter.authenticated) { // could happen if forcedUnlock
249 onTease: root.tease()
250 onEmergencyCall: root.emergencyCall()
252 if (!loader.item.required) {
260 property: "backgroundTopMargin"
266 property: "launcherOffset"
267 value: d.launcherOffsetProxy
272 property: "dragHandleLeftMargin"
273 value: root.dragHandleLeftMargin
278 property: "delayMinutes"
279 value: forcedDelayTimer.delayMinutes
284 property: "background"
285 value: root.background
296 property: "alphanumeric"
297 value: AccountsService.passwordDisplayHint === AccountsService.Keyboard
302 property: "currentIndex"
303 value: d.currentIndex
308 property: "userModel"
314 property: "infographicModel"
315 value: lightDM.infographic
320 target: lightDM.greeter
322 onShowGreeter: root.forceShow()
330 if (!lightDM.greeter.active) {
331 return; // could happen if hideGreeter() comes in before we prompt
334 // inefficient, but we only rarely deal with messages
335 var html = text.replace(/&/g, "&")
336 .replace(/</g, "<")
337 .replace(/>/g, ">")
338 .replace(/\n/g, "<br>");
340 html = "<font color=\"#df382c\">" + html + "</font>";
343 loader.item.showMessage(html);
349 if (!lightDM.greeter.active) {
350 return; // could happen if hideGreeter() comes in before we prompt
353 loader.item.showPrompt(text, isSecret, isDefaultPrompt);
356 onAuthenticationComplete: {
359 if (lightDM.greeter.authenticated) {
360 AccountsService.failedLogins = 0;
362 if (!lightDM.greeter.promptless) {
366 if (!lightDM.greeter.promptless) {
367 AccountsService.failedLogins++;
370 // Check if we should initiate a factory reset
371 if (maxFailedLogins >= 2) { // require at least a warning
372 if (AccountsService.failedLogins === maxFailedLogins - 1) {
373 loader.item.showLastChance();
374 } else if (AccountsService.failedLogins >= maxFailedLogins) {
375 SystemImage.factoryReset(); // Ouch!
379 // Check if we should initiate a forced login delay
380 if (failedLoginsDelayAttempts > 0
381 && AccountsService.failedLogins > 0
382 && AccountsService.failedLogins % failedLoginsDelayAttempts == 0) {
383 forcedDelayTimer.forceDelay(failedLoginsDelayMinutes);
386 loader.item.notifyAuthenticationFailed();
387 if (!lightDM.greeter.promptless) {
388 d.selectUser(d.currentIndex, false);
393 onRequestAuthenticationUser: {
394 // Find index for requested user, if it exists
395 for (var i = 0; i < lightDM.users.count; i++) {
396 if (user === lightDM.users.data(i, lightDM.userRoles.NameRole)) {
397 d.selectUser(i, true);
405 target: lightDM.greeter
411 target: lightDM.infographic
413 value: AccountsService.statsWelcomeScreen ? lightDM.users.data(d.currentIndex, lightDM.userRoles.NameRole) : ""
418 onLanguageChanged: lightDM.infographic.readyForDataChange()
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list