@@ -18,6 +18,9 @@ import QtQuick 2.3
1818import AccountsService 0.1
1919import LightDM 0.1 as LightDM
2020import Ubuntu.Components 1.1
21+import Ubuntu.SystemImage 0.1
22+import Ubuntu.Telephony 0.1 as Telephony
23+import Unity.Launcher 0.1
2124import "../Components"
2225
2326Showable {
@@ -30,11 +33,15 @@ Showable {
3033 property real launcherOffset
3134
3235 // 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
3438
3539 // True when the greeter is waiting for PAM or other setup process
3640 property bool waiting: true
3741
42+ property string lockedApp: ""
43+ property bool hasLockedApp: lockedApp !== ""
44+
3845 showAnimation: StandardAnimation { property: "dragOffset"; to: 0; duration: UbuntuAnimation.FastDuration }
3946 hideAnimation: __leftHideAnimation
4047
@@ -60,21 +67,20 @@ Showable {
6067 // back to zero (on a release of the drag). But by defining a Behavior,
6168 // we delay the property from reaching zero until it's too late. So we set
6269 // 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
6471 // change notifications in declaration order. So unless we define the
6572 // proxy first, we need a little "is valid" property defined above the
6673 // proxy, so we know when to enable the proxy behavior. Phew!
6774 readonly property bool launcherOffsetValid: launcherOffset > 0
68− property real launcherOffsetProxy: launcherOffset
75+ property real launcherOffsetProxy: shown ? launcherOffset : 0
6976 Behavior on launcherOffsetProxy {
7077 enabled: !launcherOffsetValid
7178 StandardAnimation {}
7279 }
7380
74− signal selected(int uid)
75− signal unlocked(int uid)
7681 signal tease()
7782 signal sessionStarted()
83+ signal emergencyCall()
7884
7985 function hideRight() {
8086 if (shown) {
@@ -83,12 +89,6 @@ Showable {
8389 }
8490 }
8591
86− function tryToUnlock() {
87− if (greeterContentLoader.item) {
88− greeterContentLoader.item.tryToUnlock()
89− }
90− }
91−
9292 function reset() {
9393 if (greeterContentLoader.item) {
9494 greeterContentLoader.item.reset()
@@ -99,10 +99,71 @@ Showable {
9999 enabled = false;
100100 if (LightDM.Greeter.startSessionSync()) {
101101 sessionStarted();
102+ hide();
103+ lockscreen.hide();
102104 }
103105 enabled = true;
104106 }
105107
108+ function notifyAppFocused(appId) {
109+ if (narrowMode) {
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.
114+ lockedApp = appId;
115+ }
116+ if (hasLockedApp) {
117+ if (appId === lockedApp) {
118+ lockscreen.hide(); // show locked app
119+ } else {
120+ startUnlock(); // show lockscreen if necessary
121+ }
122+ }
123+ hide();
124+ } else {
125+ if (LightDM.Greeter.active) {
126+ startUnlock();
127+ }
128+ }
129+ }
130+
131+ // Do we need these next two functions, really?
132+ function notifyFocusChanged(appId) {
133+ if (hasLockedApp && lockedApp !== appId) {
134+ startUnlock();
135+ }
136+ }
137+
138+ function notifyAppAdded(appId) {
139+ if (shown && appId != "unity8-dash") {
140+ startUnlock();
141+ }
142+ if (narrowMode && hasLockedApp && appId === lockedApp) {
143+ lockscreen.hide(); // show locked app
144+ }
145+ }
146+
147+ function notifyAboutToStartApp(appId) {
148+ if (hasLockedApp) {
149+ startUnlock();
150+ }
151+ }
152+
153+ function startUnlock() {
154+ if (narrowMode) {
155+ if (!LightDM.Greeter.authenticated) {
156+ lockscreen.maybeShow();
157+ }
158+ hide();
159+ } else {
160+ show();
161+ if (greeterContentLoader.item) {
162+ greeterContentLoader.item.tryToUnlock();
163+ }
164+ }
165+ }
166+
106167 onRequiredChanged: {
107168 // Reset hide animation to default once we're finished with it
108169 if (required) {
@@ -125,6 +186,35 @@ Showable {
125186 }
126187 }
127188
189+ onFullyShownChanged: {
190+ // Wait until the greeter is completely covering lockscreen before resetting it.
191+ if (narrowMode && fullyShown && !LightDM.Greeter.authenticated) {
192+ lockscreen.reset();
193+ lockscreen.maybeShow();
194+ }
195+ }
196+
197+ onShowProgressChanged: {
198+ if (showProgress === 0) {
199+ if ((LightDM.Greeter.promptless && LightDM.Greeter.authenticated) || forcedUnlock) {
200+ greeter.login();
201+ } else if (narrowMode) {
202+ lockscreen.clear(false); // to reset focus if necessary
203+ }
204+ }
205+ }
206+
207+ QtObject {
208+ id: d
209+
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);
215+ }
216+ }
217+
128218 Lockscreen {
129219 id: lockscreen
130220 objectName: "lockscreen"
@@ -160,7 +250,7 @@ Showable {
160250
161251 onEntered: LightDM.Greeter.respond(passphrase);
162252 onCancel: greeter.show()
163− onEmergencyCall: startLockedApp("dialer-app")
253+ onEmergencyCall: greeter.emergencyCall()
164254
165255 onShownChanged: if (shown) greeter.lockedApp = ""
166256
@@ -190,6 +280,43 @@ Showable {
190280 }
191281 }
192282
283+ Rectangle {
284+ anchors.fill: parent
285+ color: "black"
286+ opacity: greeter.showProgress * 0.8
287+ }
288+
289+ Loader {
290+ id: greeterContentLoader
291+ objectName: "greeterContentLoader"
292+
293+ x: launcherOffsetProxy + dragOffset
294+ width: parent.width
295+ height: parent.height
296+
297+ property var model: LightDM.Users
298+ property int currentIndex: 0
299+ property var infographicModel: LightDM.Infographic
300+ readonly property int backgroundTopMargin: -greeter.y
301+
302+ source: (greeter.required || lockscreen.required) ? "GreeterContent.qml" : ""
303+
304+ onLoaded: {
305+ d.selectUser(currentIndex);
306+ }
307+
308+ Connections {
309+ target: greeterContentLoader.item
310+
311+ onSelected: {
312+ d.selectUser(uid);
313+ greeterContentLoader.currentIndex = uid;
314+ }
315+ onUnlocked: greeter.hide()
316+ onTease: greeter.tease()
317+ }
318+ }
319+
193320 Connections {
194321 target: LightDM.Greeter
195322
@@ -272,41 +399,4 @@ Showable {
272399 property: "active"
273400 value: greeter.shown || lockscreen.shown || greeter.hasLockedApp
274401 }
275−
276− Rectangle {
277− anchors.fill: parent
278− color: "black"
279− opacity: greeter.showProgress * 0.8
280− }
281−
282− Loader {
283− id: greeterContentLoader
284− objectName: "greeterContentLoader"
285−
286− x: launcherOffsetProxy + dragOffset
287− width: parent.width
288− height: parent.height
289−
290− property var model: LightDM.Users
291− property int currentIndex: 0
292− property var infographicModel: LightDM.Infographic
293− readonly property int backgroundTopMargin: -greeter.y
294−
295− source: (greeter.required || lockscreen.required) ? "GreeterContent.qml" : ""
296−
297− onLoaded: {
298− selected(currentIndex);
299− }
300−
301− Connections {
302− target: greeterContentLoader.item
303−
304− onSelected: {
305− greeter.selected(uid);
306− greeterContentLoader.currentIndex = uid;
307− }
308− onUnlocked: greeter.unlocked(uid);
309− onTease: greeter.tease()
310− }
311− }
312402}