@@ -21,6 +21,7 @@ import Unity.Application 0.1
2121import Ubuntu.Components 0.1
2222import Ubuntu.Gestures 0.1
2323import Unity.Launcher 0.1
24+import Utils 0.1
2425import LightDM 0.1 as LightDM
2526import Powerd 0.1
2627import SessionBroadcast 0.1
@@ -30,10 +31,11 @@ import "Launcher"
3031import "Panel"
3132import "Components"
3233import "Notifications"
34+import "Stages"
3335import Unity.Notifications 1.0 as NotificationBackend
3436import Unity.Session 0.1
3537
36−FocusScope {
38+Item {
3739 id: shell
3840
3941 // this is only here to select the width / height of the window if not running fullscreen
@@ -46,7 +48,7 @@ FocusScope {
4648 property url background
4749 readonly property real panelHeight: panel.panelHeight
4850
49− property bool dashShown: dash.shown
51+ property bool dashShown: dash.shown && dash.available && underlay.visible
5052
5153 property bool sideStageEnabled: shell.width >= units.gu(100)
5254 readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId
@@ -54,14 +56,10 @@ FocusScope {
5456 function activateApplication(appId) {
5557 if (ApplicationManager.findApplication(appId)) {
5658 ApplicationManager.requestFocusApplication(appId);
57− stages.show(true);
58− if (stages.locked && ApplicationManager.focusedApplicationId == appId) {
59− applicationsDisplayLoader.item.select(appId);
60− }
6159 } else {
6260 var execFlags = shell.sideStageEnabled ? ApplicationManager.NoFlag : ApplicationManager.ForceMainStage;
6361 ApplicationManager.startApplication(appId, execFlags);
64− stages.show(false);
62+ stages.show();
6563 }
6664 }
6765
@@ -88,82 +86,74 @@ FocusScope {
8886 id: volumeControl
8987 }
9088
91− Keys.onVolumeUpPressed: volumeControl.volumeUp()
92− Keys.onVolumeDownPressed: volumeControl.volumeDown()
89+ WindowKeysFilter {
90+ // Handle but do not filter out volume keys
91+ Keys.onVolumeUpPressed: { volumeControl.volumeUp(); event.accepted = false; }
92+ Keys.onVolumeDownPressed: { volumeControl.volumeDown(); event.accepted = false; }
9393
94− Item {
95− id: underlayClipper
96− anchors.fill: parent
97− anchors.rightMargin: stages.overlayWidth
98− clip: stages.overlayMode && !stages.painting
99−
100− InputFilterArea {
101− anchors.fill: parent
102− blockInput: parent.clip
94+ Keys.onPressed: {
95+ if (event.key == Qt.Key_PowerOff || event.key == Qt.Key_PowerDown) {
96+ dialogs.onPowerKeyPressed();
97+ event.accepted = true;
98+ } else {
99+ event.accepted = false;
100+ }
103101 }
104102
105− Item {
106− id: underlay
107− objectName: "underlay"
108− anchors.fill: parent
109− anchors.rightMargin: -parent.anchors.rightMargin
103+ Keys.onReleased: {
104+ if (event.key == Qt.Key_PowerOff || event.key == Qt.Key_PowerDown) {
105+ dialogs.onPowerKeyReleased();
106+ event.accepted = true;
107+ } else {
108+ event.accepted = false;
109+ }
110+ }
111+ }
110112
111− // Whether the underlay is fully covered by opaque UI elements.
112− property bool fullyCovered: panel.indicators.fullyOpened && shell.width <= panel.indicatorsMenuWidth
113+ Item {
114+ id: underlay
115+ objectName: "underlay"
116+ anchors.fill: parent
113117
114− // Whether the user should see the topmost application surface (if there's one at all).
115− readonly property bool applicationSurfaceShouldBeSeen: stages.shown && !stages.painting && !stages.overlayMode
118+ // Whether the underlay is fully covered by opaque UI elements.
119+ property bool fullyCovered: (panel.indicators.fullyOpened && shell.width <= panel.indicatorsMenuWidth)
120+ || stages.fullyShown || greeterWrapper.fullyShown
121+ visible: !fullyCovered
122+
123+ Image {
124+ anchors.fill: dash
125+ source: shell.width > shell.height ? "Dash/graphics/paper_landscape.png" : "Dash/graphics/paper_portrait.png"
126+ fillMode: Image.PreserveAspectCrop
127+ horizontalAlignment: Image.AlignRight
128+ verticalAlignment: Image.AlignTop
129+ }
116130
117− // NB! Application surfaces are stacked behind the shell one. So they can only be seen by the user
118− // through the translucent parts of the shell surface.
119− visible: !fullyCovered && !applicationSurfaceShouldBeSeen
131+ Dash {
132+ id: dash
133+ objectName: "dash"
120134
121− Rectangle {
122− anchors.fill: parent
123− color: "black"
124− opacity: dash.disappearingAnimationProgress
125− }
135+ available: !LightDM.Greeter.active
136+ hides: [stages, launcher, panel.indicators]
137+ shown: disappearingAnimationProgress !== 1.0 && greeterWrapper.showProgress !== 1.0 &&
138+ !(panel.indicators.fullyOpened && !sideStageEnabled)
139+ enabled: disappearingAnimationProgress === 0.0 && greeterWrapper.showProgress === 0.0 && edgeDemo.dashEnabled
126140
127− Image {
128− anchors.fill: dash
129− source: shell.width > shell.height ? "Dash/graphics/paper_landscape.png" : "Dash/graphics/paper_portrait.png"
130− fillMode: Image.PreserveAspectCrop
131− horizontalAlignment: Image.AlignRight
132− verticalAlignment: Image.AlignTop
141+ anchors {
142+ fill: parent
143+ topMargin: panel.panelHeight
133144 }
134145
135− Dash {
136− id: dash
137− objectName: "dash"
146+ contentScale: 1.0 - 0.2 * disappearingAnimationProgress
147+ opacity: 1.0 - disappearingAnimationProgress
148+ property real disappearingAnimationProgress: stages.showProgress
138149
139− available: !greeter.shown && !lockscreen.shown
140− hides: [stages, launcher, panel.indicators]
141− shown: disappearingAnimationProgress !== 1.0 && greeterWrapper.showProgress !== 1.0
142− enabled: disappearingAnimationProgress === 0.0 && greeterWrapper.showProgress === 0.0 && edgeDemo.dashEnabled
143−
144− anchors {
145− fill: parent
146− topMargin: panel.panelHeight
147− }
148−
149− contentScale: 1.0 - 0.2 * disappearingAnimationProgress
150− opacity: 1.0 - disappearingAnimationProgress
151− property real disappearingAnimationProgress: {
152− if (stages.overlayMode) {
153− return 0;
154− } else {
155− return stages.showProgress
156− }
157− }
158−
159− // FIXME: only necessary because stages.showProgress is not animated
160− Behavior on disappearingAnimationProgress { SmoothedAnimation { velocity: 5 }}
161− }
150+ // FIXME: only necessary because stages.showProgress is not animated
151+ Behavior on disappearingAnimationProgress { SmoothedAnimation { velocity: 5 }}
162152 }
163153 }
164154
165155 EdgeDragArea {
166− id: stagesDragHandle
156+ id: stagesDragArea
167157 direction: Direction.Leftwards
168158
169159 anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
@@ -173,20 +163,20 @@ FocusScope {
173163
174164 onTouchXChanged: {
175165 if (status == DirectionalDragArea.Recognized) {
176− if (ApplicationManager.count == 0) {
177− progress = Math.max(stages.width - stagesDragHandle.width + touchX, stages.width * .3)
166+ if (ApplicationManager.empty) {
167+ progress = Math.max(stages.width - stagesDragArea.width + touchX, stages.width * .3);
178168 } else {
179− progress = stages.width - stagesDragHandle.width + touchX
169+ progress = stages.width - stagesDragArea.width + touchX;
180170 }
181171 }
182172 }
183173
184174 onDraggingChanged: {
185175 if (!dragging) {
186− if (ApplicationManager.count > 0 && progress < stages.width - units.gu(10)) {
187− stages.show(true)
176+ if (!ApplicationManager.empty && progress < stages.width - units.gu(10)) {
177+ stages.show();
188178 }
189− stagesDragHandle.progress = stages.width;
179+ stagesDragArea.progress = Qt.binding(function () { return stages.width; });
190180 }
191181 }
192182 }
@@ -197,98 +187,85 @@ FocusScope {
197187 width: parent.width
198188 height: parent.height
199189
190+ visible: !fullyHidden && !ApplicationManager.empty
191+
200192 x: {
201193 if (shown) {
202− if (overlayMode || locked) {
194+ if (locked || greeter.fakeActiveForApp !== "") {
203195 return 0;
204196 }
205− return launcher.progress
197+ return launcher.progress;
206198 } else {
207− return stagesDragHandle.progress
199+ return stagesDragArea.progress
208200 }
209201 }
210−
211202 Behavior on x { SmoothedAnimation { velocity: 600; duration: UbuntuAnimation.FastDuration } }
212203
213204 property bool shown: false
205+ onShownChanged: {
206+ if (shown) {
207+ if (ApplicationManager.count > 0) {
208+ ApplicationManager.focusApplication(ApplicationManager.get(0).appId);
209+ }
210+ } else {
211+ if (ApplicationManager.focusedApplicationId) {
212+ ApplicationManager.updateScreenshot(ApplicationManager.focusedApplicationId);
213+ ApplicationManager.unfocusCurrentApplication();
214+ }
215+ }
216+ }
214217
215− property real showProgress: overlayMode ? 0 : MathUtils.clamp(1 - x / shell.width, 0, 1)
218+ // Avoid a silent "divide by zero -> NaN" situation during init as shell.width will be
219+ // zero. That breaks the property binding and the function won't be reevaluated once
220+ // shell.width is set, with the NaN result staying there for good.
221+ property real showProgress: shell.width ? MathUtils.clamp(1 - x / shell.width, 0, 1) : 0
216222
217223 property bool fullyShown: x == 0
218224 property bool fullyHidden: x == width
219225
220− property bool painting: applicationsDisplayLoader.item ? applicationsDisplayLoader.item.painting : false
221− property bool fullscreen: applicationsDisplayLoader.item ? applicationsDisplayLoader.item.fullscreen : false
222− property bool overlayMode: applicationsDisplayLoader.item ? applicationsDisplayLoader.item.overlayMode : false
223− property int overlayWidth: applicationsDisplayLoader.item ? applicationsDisplayLoader.item.overlayWidth : false
224226 property bool locked: applicationsDisplayLoader.item ? applicationsDisplayLoader.item.locked : false
225227
226− function show(focusApp) {
228+ // It might technically not be fullyShown but visually it just looks so.
229+ property bool roughlyFullyShown: x >= 0 && x <= units.gu(1)
230+
231+ function show() {
227232 shown = true;
228− panel.indicators.hide();
229− edgeDemo.stopDemo();
230− greeter.hide();
231− if (!ApplicationManager.focusedApplicationId && ApplicationManager.count > 0 && focusApp) {
232− ApplicationManager.focusApplication(ApplicationManager.get(0).appId);
233− }
234233 }
235234
236235 function hide() {
237236 shown = false;
238− if (ApplicationManager.focusedApplicationId) {
239− ApplicationManager.unfocusCurrentApplication();
240− }
241237 }
242238
243239 Connections {
244240 target: ApplicationManager
245−
246241 onFocusRequested: {
247− stages.show(true);
242+ if (greeter.fakeActiveForApp !== "" && greeter.fakeActiveForApp !== appId) {
243+ lockscreen.show();
244+ }
245+ greeter.hide();
246+ stages.show();
248247 }
249248
250249 onFocusedApplicationIdChanged: {
251− if (ApplicationManager.focusedApplicationId.length > 0) {
252− stages.show(false);
253− } else {
254− if (!stages.overlayMode) {
255− stages.hide();
256− }
250+ if (greeter.fakeActiveForApp !== "" && greeter.fakeActiveForApp !== ApplicationManager.focusedApplicationId) {
251+ lockscreen.show();
257252 }
253+ panel.indicators.hide();
258254 }
259255
260256 onApplicationAdded: {
261− stages.show(false);
262− }
263−
264− onApplicationRemoved: {
265− if (ApplicationManager.focusedApplicationId.length == 0) {
266− stages.hide();
257+ if (greeter.shown) {
258+ greeter.hide();
267259 }
268− }
269− }
270−
271− Connections {
272− target: DBusUnitySessionService
273−
274− function closeAllApps() {
275− while (true) {
276− var app = ApplicationManager.get(0);
277− if (app === null) {
278− break;
279− }
280− ApplicationManager.stopApplication(app.appId);
260+ if (!stages.shown) {
261+ stages.show();
281262 }
282263 }
283264
284− onLogoutRequested: {
285− // TODO: Display a dialog to ask the user to confirm.
286− DBusUnitySessionService.Logout();
287− }
288−
289− onLogoutReady: {
290− closeAllApps();
291− Qt.quit();
265+ onEmptyChanged: {
266+ if (ApplicationManager.empty) {
267+ stages.hide();
268+ }
292269 }
293270 }
294271
@@ -296,22 +273,61 @@ FocusScope {
296273 id: applicationsDisplayLoader
297274 anchors.fill: parent
298275
299− source: shell.sideStageEnabled ? "Stages/StageWithSideStage.qml" : "Stages/PhoneStage.qml"
276+ source: shell.sideStageEnabled ? "Stages/TabletStage.qml" : "Stages/PhoneStage.qml"
300277
301278 Binding {
302279 target: applicationsDisplayLoader.item
303− property: "moving"
304− value: !stages.fullyShown
280+ property: "objectName"
281+ value: "stage"
305282 }
306283 Binding {
307284 target: applicationsDisplayLoader.item
308− property: "shown"
309− value: stages.shown
285+ property: "dragAreaWidth"
286+ value: shell.edgeSize
310287 }
311288 Binding {
312289 target: applicationsDisplayLoader.item
313− property: "dragAreaWidth"
314− value: shell.edgeSize
290+ property: "maximizedAppTopMargin"
291+ // Not just using panel.panelHeight as that changes depending on the focused app.
292+ value: panel.indicators.panelHeight
293+ }
294+ Binding {
295+ target: applicationsDisplayLoader.item
296+ property: "interactive"
297+ value: stages.roughlyFullyShown && !greeter.shown && !lockscreen.shown
298+ && panel.indicators.fullyClosed
299+ }
300+ Binding {
301+ target: applicationsDisplayLoader.item
302+ property: "spreadEnabled"
303+ value: greeter.fakeActiveForApp === "" // to support emergency dialer hack
304+ }
305+ }
306+ }
307+
308+ InputMethod {
309+ id: inputMethod
310+ objectName: "inputMethod"
311+ anchors { fill: parent; topMargin: panel.panelHeight }
312+ z: notifications.useModal || panel.indicators.shown ? overlay.z + 1 : overlay.z - 1
313+ }
314+
315+ Connections {
316+ target: SurfaceManager
317+ onSurfaceCreated: {
318+ if (surface.type == MirSurfaceItem.InputMethod) {
319+ inputMethod.surface = surface;
320+ }
321+ }
322+
323+ onSurfaceDestroyed: {
324+ if (inputMethod.surface == surface) {
325+ inputMethod.surface = null;
326+ surface.parent = null;
327+ }
328+ if (!surface.parent) {
329+ // there's no one displaying it. delete it right away
330+ surface.release();
315331 }
316332 }
317333 }
@@ -328,7 +344,7 @@ FocusScope {
328344 showAnimation: StandardAnimation { property: "opacity"; to: 1 }
329345 hideAnimation: StandardAnimation { property: "opacity"; to: 0 }
330346 y: panel.panelHeight
331− x: required ? 0 : - width
347+ visible: required
332348 width: parent.width
333349 height: parent.height - panel.panelHeight
334350 background: shell.background
@@ -337,6 +353,13 @@ FocusScope {
337353
338354 onEntered: LightDM.Greeter.respond(passphrase);
339355 onCancel: greeter.show()
356+ onEmergencyCall: {
357+ greeter.fakeActiveForApp = "dialer-app"
358+ shell.activateApplication("dialer-app")
359+ lockscreen.hide()
360+ }
361+
362+ onShownChanged: if (shown) greeter.fakeActiveForApp = ""
340363
341364 Component.onCompleted: {
342365 if (LightDM.Users.count == 1) {
@@ -348,6 +371,8 @@ FocusScope {
348371 Connections {
349372 target: LightDM.Greeter
350373
374+ onShowGreeter: greeter.show()
375+
351376 onShowPrompt: {
352377 if (LightDM.Users.count == 1) {
353378 // TODO: There's no better way for now to determine if its a PIN or a passphrase.
@@ -367,12 +392,19 @@ FocusScope {
367392 }
368393 if (LightDM.Greeter.authenticated) {
369394 lockscreen.hide();
395+ greeter.login();
370396 } else {
371397 lockscreen.clear(true);
372398 }
373399 }
374400 }
375401
402+ Binding {
403+ target: LightDM.Greeter
404+ property: "active"
405+ value: greeter.shown || lockscreen.shown || greeter.fakeActiveForApp != ""
406+ }
407+
376408 Rectangle {
377409 anchors.fill: parent
378410 color: "black"
@@ -392,12 +424,18 @@ FocusScope {
392424 StandardAnimation {}
393425 }
394426
427+ property bool fullyShown: showProgress === 1.0
395428 readonly property real showProgress: MathUtils.clamp((1 - x/width) + greeter.showProgress - 1, 0, 1)
429+ onShowProgressChanged: if (LightDM.Greeter.promptless && showProgress === 0) greeter.login()
396430
397431 Greeter {
398432 id: greeter
399433 objectName: "greeter"
400434
435+ signal sessionStarted() // helpful for tests
436+
437+ property string fakeActiveForApp: ""
438+
401439 available: true
402440 hides: [launcher, panel.indicators]
403441 shown: true
@@ -409,14 +447,28 @@ FocusScope {
409447
410448 dragHandleWidth: shell.edgeSize
411449
450+ function login() {
451+ enabled = false;
452+ LightDM.Greeter.startSessionSync();
453+ sessionStarted();
454+ greeter.hide();
455+ lockscreen.hide();
456+ launcher.hide();
457+ enabled = true;
458+ }
459+
412460 onShownChanged: {
413461 if (shown) {
414462 lockscreen.reset();
463+ if (!LightDM.Greeter.promptless) {
464+ lockscreen.show();
465+ }
415466 // If there is only one user, we start authenticating with that one here.
416467 // If there are more users, the Greeter will handle that
417468 if (LightDM.Users.count == 1) {
418469 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole));
419470 }
471+ greeter.fakeActiveForApp = "";
420472 greeter.forceActiveFocus();
421473 }
422474 }
@@ -439,12 +491,6 @@ FocusScope {
439491 }
440492 }
441493
442− InputFilterArea {
443− anchors.fill: parent
444− blockInput: ApplicationManager.focusedApplicationId.length === 0 || greeter.shown || lockscreen.shown || launcher.shown
445− || panel.indicators.shown
446− }
447−
448494 Connections {
449495 id: powerConnection
450496 target: Powerd
@@ -466,58 +512,69 @@ FocusScope {
466512 }
467513
468514 function showHome() {
469− var animate = !greeter.shown && !stages.shown
470− greeter.hide()
515+ if (edgeDemo.running) {
516+ return
517+ }
518+
519+ if (LightDM.Greeter.active) {
520+ if (!LightDM.Greeter.promptless) {
521+ lockscreen.show()
522+ }
523+ greeter.hide()
524+ }
525+
526+ var animate = !LightDM.Greeter.active && !stages.shown
471527 dash.setCurrentScope("clickscope", animate, false)
472528 stages.hide()
473529 }
474530
475− function hideIndicatorMenu(delay) {
476− panel.hideIndicatorMenu(delay);
531+ function showDash() {
532+ if (LightDM.Greeter.active && !LightDM.Greeter.promptless) {
533+ return;
534+ }
535+
536+ if (!stages.locked) {
537+ stages.hide();
538+ launcher.fadeOut();
539+ } else {
540+ launcher.switchToNextState("visible");
541+ }
542+
543+ if (greeter.shown) {
544+ greeter.hideRight();
545+ launcher.fadeOut();
546+ }
477547 }
478548
479549 Item {
480550 id: overlay
551+ z: 10
481552
482553 anchors.fill: parent
483554
484555 Panel {
485556 id: panel
557+ objectName: "panel"
486558 anchors.fill: parent //because this draws indicator menus
487− indicatorsMenuWidth: parent.width > units.gu(60) ? units.gu(40) : parent.width
488559 indicators {
489560 hides: [launcher]
490− available: edgeDemo.panelEnabled
561+ available: edgeDemo.panelEnabled && greeter.fakeActiveForApp === ""
491562 contentEnabled: edgeDemo.panelContentEnabled
563+ width: parent.width > units.gu(60) ? units.gu(40) : parent.width
564+ panelHeight: units.gu(3)
492565 }
493− property string focusedAppId: ApplicationManager.focusedApplicationId
494− property var focusedApplication: ApplicationManager.findApplication(focusedAppId)
495− fullscreenMode: focusedApplication && stages.fullscreen && !greeter.shown && !lockscreen.shown
496− searchVisible: !greeter.shown && !lockscreen.shown && dash.shown && dash.searchable
497566
498− InputFilterArea {
499− anchors {
500− top: parent.top
501− left: parent.left
502− right: parent.right
503− }
504− height: (panel.fullscreenMode) ? shell.edgeSize : panel.panelHeight
505− blockInput: true
506− }
507− }
567+ property bool topmostApplicationIsFullscreen:
568+ ApplicationManager.focusedApplicationId &&
569+ ApplicationManager.findApplication(ApplicationManager.focusedApplicationId).fullscreen
508570
509− InputFilterArea {
510− blockInput: launcher.shown
511− anchors {
512− top: parent.top
513− bottom: parent.bottom
514− left: parent.left
515− }
516− width: launcher.width
571+ fullscreenMode: (stages.roughlyFullyShown && topmostApplicationIsFullscreen
572+ && !LightDM.Greeter.active) || greeter.fakeActiveForApp !== ""
517573 }
518574
519575 Launcher {
520576 id: launcher
577+ objectName: "launcher"
521578
522579 readonly property bool dashSwipe: progress > 0
523580
@@ -525,28 +582,15 @@ FocusScope {
525582 anchors.bottom: parent.bottom
526583 width: parent.width
527584 dragAreaWidth: shell.edgeSize
528− available: edgeDemo.launcherEnabled
585+ available: edgeDemo.launcherEnabled && greeter.fakeActiveForApp === ""
529586
530− onShowDashHome: {
531− if (edgeDemo.running)
532− return;
533−
534− showHome()
535− }
536− onDash: {
537− if (stages.shown && !stages.overlayMode) {
538− if (!stages.locked) {
539− stages.hide();
540− launcher.hide();
541− }
542− }
543− if (greeter.shown) {
544− greeter.hideRight();
545− launcher.hide();
546− }
547− }
587+ onShowDashHome: showHome()
588+ onDash: showDash()
548589 onDashSwipeChanged: if (dashSwipe && stages.shown) dash.setCurrentScope("clickscope", false, true)
549590 onLauncherApplicationSelected: {
591+ if (greeter.fakeActiveForApp !== "") {
592+ lockscreen.show()
593+ }
550594 if (!edgeDemo.running)
551595 shell.activateApplication(appId)
552596 }
@@ -568,11 +612,6 @@ FocusScope {
568612 MouseArea {
569613 anchors.fill: parent
570614 }
571−
572− InputFilterArea {
573− anchors.fill: parent
574− blockInput: modalNotificationBackground.visible
575− }
576615 }
577616
578617 Notifications {
@@ -581,12 +620,10 @@ FocusScope {
581620 model: NotificationBackend.Model
582621 margin: units.gu(1)
583622
584− anchors {
585− top: parent.top
586− right: parent.right
587− bottom: parent.bottom
588− topMargin: panel.panelHeight
589− }
623+ y: panel.panelHeight
624+ width: parent.width
625+ height: parent.height - panel.panelHeight
626+
590627 states: [
591628 State {
592629 name: "narrow"
@@ -600,62 +637,31 @@ FocusScope {
600637 PropertyChanges { target: notifications; width: units.gu(38) }
601638 }
602639 ]
603−
604− InputFilterArea {
605− anchors { left: parent.left; right: parent.right }
606− height: parent.contentHeight
607− blockInput: height > 0
608− }
609640 }
610641 }
611642
612− focus: true
613− onFocusChanged: if (!focus) forceActiveFocus();
614−
615− InputFilterArea {
616− anchors {
617− top: parent.top
618− bottom: parent.bottom
619− left: parent.left
620− }
621− width: shell.edgeSize
622− blockInput: true
623− }
624−
625− InputFilterArea {
626− anchors {
627− top: parent.top
628− bottom: parent.bottom
629− right: parent.right
630− }
631− width: shell.edgeSize
632− blockInput: true
633− }
634−
635643 Binding {
636644 target: i18n
637645 property: "domain"
638646 value: "unity8"
639647 }
640648
641− OSKController {
642− anchors.topMargin: panel.panelHeight
643− anchors.fill: parent // as needs to know the geometry of the shell
644− }
645−
646− //FIXME: This should be handled in the input stack, keyboard shouldnt propagate
647− MouseArea {
648− anchors.bottom: parent.bottom
649− anchors.left: parent.left
650− anchors.right: parent.right
651− height: ApplicationManager.keyboardVisible ? ApplicationManager.keyboardHeight : 0
652−
653− enabled: ApplicationManager.keyboardVisible
649+ Dialogs {
650+ id: dialogs
651+ anchors.fill: parent
652+ z: overlay.z + 10
653+ onPowerOffClicked: {
654+ shutdownFadeOutRectangle.enabled = true;
655+ shutdownFadeOutRectangle.visible = true;
656+ shutdownFadeOut.start();
657+ }
654658 }
655659
656660 Label {
661+ id: alphaDisclaimerLabel
657662 anchors.centerIn: parent
658663 visible: ApplicationManager.fake ? ApplicationManager.fake : false
664+ z: dialogs.z + 10
659665 text: "EARLY ALPHA\nNOT READY FOR USE"
660666 color: "lightgrey"
661667 opacity: 0.2
@@ -669,6 +675,7 @@ FocusScope {
669675
670676 EdgeDemo {
671677 id: edgeDemo
678+ z: alphaDisclaimerLabel.z + 10
672679 greeter: greeter
673680 launcher: launcher
674681 dash: dash
@@ -680,4 +687,25 @@ FocusScope {
680687 target: SessionBroadcast
681688 onShowHome: showHome()
682689 }
690+
691+ Rectangle {
692+ id: shutdownFadeOutRectangle
693+ z: edgeDemo.z + 10
694+ enabled: false
695+ visible: false
696+ color: "black"
697+ anchors.fill: parent
698+ opacity: 0.0
699+ NumberAnimation on opacity {
700+ id: shutdownFadeOut
701+ from: 0.0
702+ to: 1.0
703+ onStopped: {
704+ if (shutdownFadeOutRectangle.enabled && shutdownFadeOutRectangle.visible) {
705+ DBusUnitySessionService.Shutdown();
706+ }
707+ }
708+ }
709+ }
710+
683711}