@@ -18,6 +18,9 @@ import QtQuick 2.3
18import AccountsService 0.1
18import AccountsService 0.1
19import LightDM 0.1 as LightDM
19import LightDM 0.1 as LightDM
20import Ubuntu.Components 1.1
20import Ubuntu.Components 1.1
21+import Ubuntu.SystemImage 0.1
22+import Ubuntu.Telephony 0.1 as Telephony
23+import Unity.Launcher 0.1
21import "../Components"
24import "../Components"
@@ -30,11 +33,15 @@ Showable {
30 property real launcherOffset
33 property real launcherOffset
32 // 1 when fully shown and 0 when fully hidden
35 // 1 when fully shown and 0 when fully hidden
33− property real showProgress: MathUtils.clamp((width - Math.abs(greeterContentLoader.x)) / width, 0, 1)
36+ readonly property real showProgress: MathUtils.clamp((width - Math.abs(greeterContentLoader.x)) / width, 0, 1)
37+ readonly property bool fullyShown: showProgress === 1 || lockscreen.shown
35 // True when the greeter is waiting for PAM or other setup process
39 // True when the greeter is waiting for PAM or other setup process
36 property bool waiting: true
40 property bool waiting: true
42+ property string lockedApp: ""
43+ property bool hasLockedApp: lockedApp !== ""
38 showAnimation: StandardAnimation { property: "dragOffset"; to: 0; duration: UbuntuAnimation.FastDuration }
45 showAnimation: StandardAnimation { property: "dragOffset"; to: 0; duration: UbuntuAnimation.FastDuration }
39 hideAnimation: __leftHideAnimation
46 hideAnimation: __leftHideAnimation
@@ -60,21 +67,20 @@ Showable {
60 // back to zero (on a release of the drag). But by defining a Behavior,
67 // back to zero (on a release of the drag). But by defining a Behavior,
61 // we delay the property from reaching zero until it's too late. So we set
68 // we delay the property from reaching zero until it's too late. So we set
62 // a proxy bound to launcherOffset, which lets us see the target value of
69 // a proxy bound to launcherOffset, which lets us see the target value of
63− // zero as we also slowly adjust the value down to zero. But Qml will send
70+ // zero as we also slowly adjust the proxy down to zero. But Qml will send
64 // change notifications in declaration order. So unless we define the
71 // change notifications in declaration order. So unless we define the
65 // proxy first, we need a little "is valid" property defined above the
72 // proxy first, we need a little "is valid" property defined above the
66 // proxy, so we know when to enable the proxy behavior. Phew!
73 // proxy, so we know when to enable the proxy behavior. Phew!
67 readonly property bool launcherOffsetValid: launcherOffset > 0
74 readonly property bool launcherOffsetValid: launcherOffset > 0
68− property real launcherOffsetProxy: launcherOffset
75+ property real launcherOffsetProxy: shown ? launcherOffset : 0
69 Behavior on launcherOffsetProxy {
76 Behavior on launcherOffsetProxy {
70 enabled: !launcherOffsetValid
77 enabled: !launcherOffsetValid
71 StandardAnimation {}
78 StandardAnimation {}
74− signal selected(int uid)
75− signal unlocked(int uid)
76 signal tease()
81 signal tease()
77 signal sessionStarted()
82 signal sessionStarted()
83+ signal emergencyCall()
79 function hideRight() {
85 function hideRight() {
80 if (shown) {
86 if (shown) {
@@ -83,12 +89,6 @@ Showable {
86− function tryToUnlock() {
87− if (greeterContentLoader.item) {
88− greeterContentLoader.item.tryToUnlock()
92 function reset() {
92 function reset() {
93 if (greeterContentLoader.item) {
93 if (greeterContentLoader.item) {
94 greeterContentLoader.item.reset()
94 greeterContentLoader.item.reset()
@@ -99,10 +99,71 @@ Showable {
99 enabled = false;
99 enabled = false;
100 if (LightDM.Greeter.startSessionSync()) {
100 if (LightDM.Greeter.startSessionSync()) {
101 sessionStarted();
101 sessionStarted();
103 enabled = true;
105 enabled = true;
108+ function notifyAppFocused(appId) {
110+ if (appId === "dialer-app" && callManager.hasCalls && locked) {
111+ // If we are in the middle of a call, make dialer lockedApp and show it.
112+ // This can happen if user backs out of dialer back to greeter, then
113+ // launches dialer again.
117+ if (appId === lockedApp) {
118+ lockscreen.hide(); // show locked app
120+ startUnlock(); // show lockscreen if necessary
125+ if (LightDM.Greeter.active) {
131+ // Do we need these next two functions, really?
132+ function notifyFocusChanged(appId) {
133+ if (hasLockedApp && lockedApp !== appId) {
138+ function notifyAppAdded(appId) {
139+ if (shown && appId != "unity8-dash") {
142+ if (narrowMode && hasLockedApp && appId === lockedApp) {
143+ lockscreen.hide(); // show locked app
147+ function notifyAboutToStartApp(appId) {
153+ function startUnlock() {
155+ if (!LightDM.Greeter.authenticated) {
156+ lockscreen.maybeShow();
161+ if (greeterContentLoader.item) {
162+ greeterContentLoader.item.tryToUnlock();
106 onRequiredChanged: {
167 onRequiredChanged: {
107 // Reset hide animation to default once we're finished with it
168 // Reset hide animation to default once we're finished with it
108 if (required) {
169 if (required) {
@@ -125,6 +186,35 @@ Showable {
189+ onFullyShownChanged: {
190+ // Wait until the greeter is completely covering lockscreen before resetting it.
191+ if (narrowMode && fullyShown && !LightDM.Greeter.authenticated) {
193+ lockscreen.maybeShow();
197+ onShowProgressChanged: {
198+ if (showProgress === 0) {
199+ if ((LightDM.Greeter.promptless && LightDM.Greeter.authenticated) || forcedUnlock) {
201+ } else if (narrowMode) {
202+ lockscreen.clear(false); // to reset focus if necessary
210+ function selectUser(uid) {
211+ // Update launcher items for new user
212+ var user = LightDM.Users.data(uid, LightDM.UserRoles.NameRole);
213+ AccountsService.user = user;
214+ LauncherModel.setUser(user);
128 Lockscreen {
218 Lockscreen {
129 id: lockscreen
219 id: lockscreen
130 objectName: "lockscreen"
220 objectName: "lockscreen"
@@ -160,7 +250,7 @@ Showable {
161 onEntered: LightDM.Greeter.respond(passphrase);
251 onEntered: LightDM.Greeter.respond(passphrase);
162 onCancel: greeter.show()
252 onCancel: greeter.show()
163− onEmergencyCall: startLockedApp("dialer-app")
253+ onEmergencyCall: greeter.emergencyCall()
165 onShownChanged: if (shown) greeter.lockedApp = ""
255 onShownChanged: if (shown) greeter.lockedApp = ""
@@ -190,6 +280,43 @@ Showable {
284+ anchors.fill: parent
286+ opacity: greeter.showProgress * 0.8
290+ id: greeterContentLoader
291+ objectName: "greeterContentLoader"
293+ x: launcherOffsetProxy + dragOffset
295+ height: parent.height
297+ property var model: LightDM.Users
298+ property int currentIndex: 0
299+ property var infographicModel: LightDM.Infographic
300+ readonly property int backgroundTopMargin: -greeter.y
302+ source: (greeter.required || lockscreen.required) ? "GreeterContent.qml" : ""
305+ d.selectUser(currentIndex);
309+ target: greeterContentLoader.item
313+ greeterContentLoader.currentIndex = uid;
315+ onUnlocked: greeter.hide()
316+ onTease: greeter.tease()
193 Connections {
320 Connections {
194 target: LightDM.Greeter
321 target: LightDM.Greeter
@@ -272,41 +399,4 @@ Showable {
272 property: "active"
399 property: "active"
273 value: greeter.shown || lockscreen.shown || greeter.hasLockedApp
400 value: greeter.shown || lockscreen.shown || greeter.hasLockedApp
277− anchors.fill: parent
279− opacity: greeter.showProgress * 0.8
283− id: greeterContentLoader
284− objectName: "greeterContentLoader"
286− x: launcherOffsetProxy + dragOffset
288− height: parent.height
290− property var model: LightDM.Users
291− property int currentIndex: 0
292− property var infographicModel: LightDM.Infographic
293− readonly property int backgroundTopMargin: -greeter.y
295− source: (greeter.required || lockscreen.required) ? "GreeterContent.qml" : ""
298− selected(currentIndex);
302− target: greeterContentLoader.item
305− greeter.selected(uid);
306− greeterContentLoader.currentIndex = uid;
308− onUnlocked: greeter.unlocked(uid);
309− onTease: greeter.tease()