on a0e87ce help sign in
unity8/qml/Shell.qml
831 lines 29 kB history raw
1/*
2 * Copyright (C) 2013 Canonical, Ltd.
3 *
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.
7 *
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.
12 *
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/>.
15 */
17import QtQuick 2.0
18import QtQuick.Window 2.0
19import AccountsService 0.1
20import GSettings 1.0
21import Unity.Application 0.1
22import Ubuntu.Components 0.1
23import Ubuntu.Components.Popups 1.0
24import Ubuntu.Gestures 0.1
25import Ubuntu.SystemImage 0.1
26import Ubuntu.Telephony 0.1 as Telephony
27import Unity.Connectivity 0.1
28import Unity.Launcher 0.1
29import Utils 0.1
30import LightDM 0.1 as LightDM
31import Powerd 0.1
32import SessionBroadcast 0.1
33import "Greeter"
34import "Launcher"
35import "Panel"
36import "Components"
37import "Notifications"
38import "Stages"
39import "Panel/Indicators"
40import Unity.Notifications 1.0 as NotificationBackend
41import Unity.Session 0.1
42import Unity.DashCommunicator 0.1
44Item {
45 id: shell
47 // this is only here to select the width / height of the window if not running fullscreen
48 property bool tablet: false
49 width: tablet ? units.gu(160) : applicationArguments.hasGeometry() ? applicationArguments.width() : units.gu(40)
50 height: tablet ? units.gu(100) : applicationArguments.hasGeometry() ? applicationArguments.height() : units.gu(71)
52 property real edgeSize: units.gu(2)
53 property url defaultBackground: Qt.resolvedUrl(shell.width >= units.gu(60) ? "graphics/tablet_background.jpg" : "graphics/phone_background.jpg")
54 property url background
55 readonly property real panelHeight: panel.panelHeight
57 readonly property bool locked: LightDM.Greeter.active && !LightDM.Greeter.authenticated && !forcedUnlock
58 readonly property alias hasLockedApp: greeter.hasLockedApp
59 readonly property bool forcedUnlock: edgeDemo.running
60 onForcedUnlockChanged: if (forcedUnlock) lockscreen.hide()
62 property bool sideStageEnabled: shell.width >= units.gu(100)
63 readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId
65 property int maxFailedLogins: -1 // disabled by default for now, will enable via settings in future
66 property int failedLoginsDelayAttempts: 7 // number of failed logins
67 property int failedLoginsDelayMinutes: 5 // minutes of forced waiting
69 property int orientation
70 readonly property int deviceOrientationAngle: Screen.angleBetween(Screen.primaryOrientation, Screen.orientation)
71 onDeviceOrientationAngleChanged: {
72 if (!OrientationLock.enabled) {
73 orientation = Screen.orientation;
74 }
75 }
76 readonly property bool orientationLockEnabled: OrientationLock.enabled
77 onOrientationLockEnabledChanged: {
78 if (orientationLockEnabled) {
79 OrientationLock.savedOrientation = Screen.orientation;
80 } else {
81 orientation = Screen.orientation;
82 }
83 }
85 function activateApplication(appId) {
86 if (ApplicationManager.findApplication(appId)) {
87 ApplicationManager.requestFocusApplication(appId);
88 } else {
89 var execFlags = shell.sideStageEnabled ? ApplicationManager.NoFlag : ApplicationManager.ForceMainStage;
90 ApplicationManager.startApplication(appId, execFlags);
91 }
92 }
94 function startLockedApp(app) {
95 if (shell.locked) {
96 greeter.lockedApp = app;
97 }
98 shell.activateApplication(app);
99 }
101 Binding {
102 target: LauncherModel
103 property: "applicationManager"
104 value: ApplicationManager
105 }
107 Component.onCompleted: {
108 Theme.name = "Ubuntu.Components.Themes.SuruGradient"
109 if (ApplicationManager.count > 0) {
110 ApplicationManager.focusApplication(ApplicationManager.get(0).appId);
111 }
112 if (orientationLockEnabled) {
113 orientation = OrientationLock.savedOrientation;
114 }
115 }
117 GSettings {
118 id: backgroundSettings
119 schema.id: "org.gnome.desktop.background"
120 }
121 property url gSettingsPicture: backgroundSettings.pictureUri != undefined && backgroundSettings.pictureUri.length > 0 ? backgroundSettings.pictureUri : shell.defaultBackground
122 onGSettingsPictureChanged: {
123 shell.background = gSettingsPicture
124 }
126 VolumeControl {
127 id: volumeControl
128 }
130 DashCommunicator {
131 id: dash
132 objectName: "dashCommunicator"
133 }
135 ScreenGrabber {
136 id: screenGrabber
137 z: edgeDemo.z + 10
138 enabled: Powerd.status === Powerd.On
139 }
141 Binding {
142 target: ApplicationManager
143 property: "forceDashActive"
144 value: launcher.shown || launcher.dashSwipe
145 }
147 VolumeKeyFilter {
148 id: volumeKeyFilter
149 onVolumeDownPressed: volumeControl.volumeDown()
150 onVolumeUpPressed: volumeControl.volumeUp()
151 onBothVolumeKeysPressed: screenGrabber.capture()
152 }
154 WindowKeysFilter {
155 Keys.onPressed: {
156 if (event.key == Qt.Key_PowerOff || event.key == Qt.Key_PowerDown) {
157 dialogs.onPowerKeyPressed();
158 event.accepted = true;
159 } else {
160 volumeKeyFilter.onKeyPressed(event.key);
161 event.accepted = false;
162 }
163 }
165 Keys.onReleased: {
166 if (event.key == Qt.Key_PowerOff || event.key == Qt.Key_PowerDown) {
167 dialogs.onPowerKeyReleased();
168 event.accepted = true;
169 } else {
170 volumeKeyFilter.onKeyReleased(event.key);
171 event.accepted = false;
172 }
173 }
174 }
176 Item {
177 id: stages
178 objectName: "stages"
179 width: parent.width
180 height: parent.height
181 visible: !ApplicationManager.empty
183 Connections {
184 target: ApplicationManager
185 onFocusRequested: {
186 if (greeter.narrowMode) {
187 if (appId === "dialer-app" && callManager.hasCalls && shell.locked) {
188 // If we are in the middle of a call, make dialer lockedApp and show it.
189 // This can happen if user backs out of dialer back to greeter, then
190 // launches dialer again.
191 greeter.lockedApp = appId;
192 }
193 if (greeter.hasLockedApp) {
194 if (appId === greeter.lockedApp) {
195 lockscreen.hide() // show locked app
196 } else {
197 greeter.startUnlock() // show lockscreen if necessary
198 }
199 }
200 greeter.hide();
201 } else {
202 if (LightDM.Greeter.active) {
203 greeter.startUnlock()
204 }
205 }
206 }
208 onFocusedApplicationIdChanged: {
209 if (greeter.hasLockedApp && greeter.lockedApp !== ApplicationManager.focusedApplicationId) {
210 greeter.startUnlock()
211 }
212 panel.indicators.hide();
213 }
215 onApplicationAdded: {
216 if (greeter.shown && appId != "unity8-dash") {
217 greeter.startUnlock()
218 }
219 if (greeter.narrowMode && greeter.hasLockedApp && appId === greeter.lockedApp) {
220 lockscreen.hide() // show locked app
221 }
222 launcher.hide();
223 }
224 }
226 Loader {
227 id: applicationsDisplayLoader
228 objectName: "applicationsDisplayLoader"
229 anchors.fill: parent
231 // When we have a locked app, we only want to show that one app.
232 // FIXME: do this in a less traumatic way. We currently only allow
233 // locked apps in phone mode (see FIXME in Lockscreen component in
234 // this same file). When that changes, we need to do something
235 // nicer here. But this code is currently just to prevent a
236 // theoretical attack where user enters lockedApp mode, then makes
237 // the screen larger (maybe connects to monitor) and tries to enter
238 // tablet mode.
239 property bool tabletMode: shell.sideStageEnabled && !greeter.hasLockedApp
240 source: tabletMode ? "Stages/TabletStage.qml" : "Stages/PhoneStage.qml"
242 Binding {
243 target: applicationsDisplayLoader.item
244 property: "objectName"
245 value: "stage"
246 }
247 Binding {
248 target: applicationsDisplayLoader.item
249 property: "dragAreaWidth"
250 value: shell.edgeSize
251 }
252 Binding {
253 target: applicationsDisplayLoader.item
254 property: "maximizedAppTopMargin"
255 // Not just using panel.panelHeight as that changes depending on the focused app.
256 value: panel.indicators.minimizedPanelHeight + units.dp(2) // dp(2) for orange line
257 }
258 Binding {
259 target: applicationsDisplayLoader.item
260 property: "interactive"
261 value: edgeDemo.stagesEnabled && !greeter.shown && !lockscreen.shown && panel.indicators.fullyClosed && launcher.progress == 0 && !notifications.useModal
262 }
263 Binding {
264 target: applicationsDisplayLoader.item
265 property: "spreadEnabled"
266 value: edgeDemo.stagesEnabled && !greeter.hasLockedApp
267 }
268 Binding {
269 target: applicationsDisplayLoader.item
270 property: "inverseProgress"
271 value: launcher.progress
272 }
273 Binding {
274 target: applicationsDisplayLoader.item
275 property: "orientation"
276 value: shell.orientation
277 }
278 }
279 }
281 InputMethod {
282 id: inputMethod
283 objectName: "inputMethod"
284 anchors { fill: parent; topMargin: panel.panelHeight }
285 z: notifications.useModal || panel.indicators.shown ? overlay.z + 1 : overlay.z - 1
286 }
288 Connections {
289 target: SurfaceManager
290 onSurfaceCreated: {
291 if (surface.type == MirSurfaceItem.InputMethod) {
292 inputMethod.surface = surface;
293 }
294 }
296 onSurfaceDestroyed: {
297 if (inputMethod.surface == surface) {
298 inputMethod.surface = null;
299 surface.parent = null;
300 }
301 if (!surface.parent) {
302 // there's no one displaying it. delete it right away
303 surface.release();
304 }
305 }
306 }
307 Connections {
308 target: SessionManager
309 onSessionStopping: {
310 if (!session.parentSession && !session.application) {
311 // nothing is using it. delete it right away
312 session.release();
313 }
314 }
315 }
317 Lockscreen {
318 id: lockscreen
319 objectName: "lockscreen"
321 hides: [launcher, panel.indicators]
322 shown: false
323 enabled: true
324 showAnimation: StandardAnimation { property: "opacity"; to: 1 }
325 hideAnimation: StandardAnimation { property: "opacity"; to: 0 }
326 y: panel.panelHeight
327 visible: required
328 width: parent.width
329 height: parent.height - panel.panelHeight
330 background: shell.background
331 alphaNumeric: AccountsService.passwordDisplayHint === AccountsService.Keyboard
332 minPinLength: 4
333 maxPinLength: 4
335 // FIXME: We *should* show emergency dialer if there is a SIM present,
336 // regardless of whether the side stage is enabled. But right now,
337 // the assumption is that narrow screens are phones which have SIMs
338 // and wider screens are tablets which don't. When we do allow this
339 // on devices with a side stage and a SIM, work should be done to
340 // ensure that the main stage is disabled while the dialer is present
341 // in the side stage. See the FIXME in the stage loader in this file.
342 showEmergencyCallButton: !shell.sideStageEnabled
344 onEntered: LightDM.Greeter.respond(passphrase);
345 onCancel: greeter.show()
346 onEmergencyCall: startLockedApp("dialer-app")
348 onShownChanged: if (shown) greeter.lockedApp = ""
350 function maybeShow() {
351 if (!shell.forcedUnlock) {
352 show()
353 }
354 }
356 Timer {
357 id: forcedDelayTimer
358 interval: 1000 * 60
359 onTriggered: {
360 if (lockscreen.delayMinutes > 0) {
361 lockscreen.delayMinutes -= 1
362 if (lockscreen.delayMinutes > 0) {
363 start() // go again
364 }
365 }
366 }
367 }
369 Component.onCompleted: {
370 if (greeter.narrowMode) {
371 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole))
372 }
373 }
374 }
376 Connections {
377 target: LightDM.Greeter
379 onShowGreeter: greeter.show()
380 onHideGreeter: greeter.login()
382 onShowPrompt: {
383 shell.enabled = true;
384 if (!LightDM.Greeter.active) {
385 return; // could happen if hideGreeter() comes in before we prompt
386 }
387 if (greeter.narrowMode) {
388 if (isDefaultPrompt) {
389 if (lockscreen.alphaNumeric) {
390 lockscreen.infoText = i18n.tr("Enter passphrase")
391 lockscreen.errorText = i18n.tr("Sorry, incorrect passphrase") + "\n" +
392 i18n.tr("Please re-enter")
393 } else {
394 lockscreen.infoText = i18n.tr("Enter passcode")
395 lockscreen.errorText = i18n.tr("Sorry, incorrect passcode")
396 }
397 } else {
398 lockscreen.infoText = i18n.tr("Enter %1").arg(text.toLowerCase())
399 lockscreen.errorText = i18n.tr("Sorry, incorrect %1").arg(text.toLowerCase())
400 }
402 lockscreen.maybeShow();
403 }
404 }
406 onPromptlessChanged: {
407 if (!LightDM.Greeter.active) {
408 return; // could happen if hideGreeter() comes in before we prompt
409 }
410 if (greeter.narrowMode) {
411 if (LightDM.Greeter.promptless && LightDM.Greeter.authenticated) {
412 lockscreen.hide()
413 } else {
414 lockscreen.reset();
415 lockscreen.maybeShow();
416 }
417 }
418 }
420 onAuthenticationComplete: {
421 shell.enabled = true;
422 if (LightDM.Greeter.authenticated) {
423 AccountsService.failedLogins = 0
424 }
425 // Else only penalize user for a failed login if they actually were
426 // prompted for a password. We do this below after the promptless
427 // early exit.
429 if (LightDM.Greeter.promptless) {
430 return;
431 }
433 if (LightDM.Greeter.authenticated) {
434 greeter.login();
435 } else {
436 AccountsService.failedLogins++
437 if (maxFailedLogins >= 2) { // require at least a warning
438 if (AccountsService.failedLogins === maxFailedLogins - 1) {
439 var title = lockscreen.alphaNumeric ?
440 i18n.tr("Sorry, incorrect passphrase.") :
441 i18n.tr("Sorry, incorrect passcode.")
442 var text = i18n.tr("This will be your last attempt.") + " " +
443 (lockscreen.alphaNumeric ?
444 i18n.tr("If passphrase is entered incorrectly, your phone will conduct a factory reset and all personal data will be deleted.") :
445 i18n.tr("If passcode is entered incorrectly, your phone will conduct a factory reset and all personal data will be deleted."))
446 lockscreen.showInfoPopup(title, text)
447 } else if (AccountsService.failedLogins >= maxFailedLogins) {
448 SystemImage.factoryReset() // Ouch!
449 }
450 }
451 if (failedLoginsDelayAttempts > 0 && AccountsService.failedLogins % failedLoginsDelayAttempts == 0) {
452 lockscreen.delayMinutes = failedLoginsDelayMinutes
453 forcedDelayTimer.start()
454 }
456 lockscreen.clear(true);
457 if (greeter.narrowMode) {
458 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole))
459 }
460 }
461 }
462 }
464 Binding {
465 target: LightDM.Greeter
466 property: "active"
467 value: greeter.shown || lockscreen.shown || greeter.hasLockedApp
468 }
470 Rectangle {
471 anchors.fill: parent
472 color: "black"
473 opacity: greeterWrapper.showProgress * 0.8
474 }
476 Item {
477 // Just a tiny wrapper to adjust greeter's x without messing with its own dragging
478 id: greeterWrapper
479 objectName: "greeterWrapper"
480 x: greeter.narrowMode ? launcher.progress : 0
481 y: panel.panelHeight
482 width: parent.width
483 height: parent.height - panel.panelHeight
485 Behavior on x {
486 enabled: !launcher.dashSwipe
487 StandardAnimation {}
488 }
490 property bool fullyShown: showProgress === 1.0
491 onFullyShownChanged: {
492 // Wait until the greeter is completely covering lockscreen before resetting it.
493 if (greeter.narrowMode && fullyShown && !LightDM.Greeter.authenticated) {
494 lockscreen.reset();
495 lockscreen.maybeShow();
496 }
497 }
499 readonly property real showProgress: MathUtils.clamp((1 - x/width) + greeter.showProgress - 1, 0, 1)
500 onShowProgressChanged: {
501 if (showProgress === 0) {
502 if ((LightDM.Greeter.promptless && LightDM.Greeter.authenticated) || shell.forcedUnlock) {
503 greeter.login()
504 } else if (greeter.narrowMode) {
505 lockscreen.clear(false) // to reset focus if necessary
506 }
507 }
508 }
510 Greeter {
511 id: greeter
512 objectName: "greeter"
514 signal sessionStarted() // helpful for tests
516 property string lockedApp: ""
517 property bool hasLockedApp: lockedApp !== ""
519 available: true
520 hides: [launcher, panel.indicators]
521 shown: true
522 loadContent: required || lockscreen.required // keeps content in memory for quick show()
524 locked: shell.locked
526 defaultBackground: shell.background
528 width: parent.width
529 height: parent.height
531 dragHandleWidth: shell.edgeSize
533 function startUnlock() {
534 if (narrowMode) {
535 if (!LightDM.Greeter.authenticated) {
536 lockscreen.maybeShow()
537 }
538 hide()
539 } else {
540 show()
541 tryToUnlock()
542 }
543 }
545 function login() {
546 enabled = false;
547 if (LightDM.Greeter.startSessionSync()) {
548 sessionStarted();
549 greeter.hide();
550 lockscreen.hide();
551 launcher.hide();
552 }
553 enabled = true;
554 }
556 onShownChanged: {
557 if (shown) {
558 // Disable everything so that user can't swipe greeter or
559 // launcher until we get first prompt/authenticate, which
560 // will re-enable the shell.
561 shell.enabled = false;
563 if (greeter.narrowMode) {
564 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole));
565 } else {
566 reset()
567 }
568 greeter.lockedApp = "";
569 greeter.forceActiveFocus();
570 }
571 }
573 Component.onCompleted: {
574 Connectivity.unlockAllModems()
575 }
577 onUnlocked: greeter.hide()
578 onSelected: {
579 // Update launcher items for new user
580 var user = LightDM.Users.data(uid, LightDM.UserRoles.NameRole);
581 AccountsService.user = user;
582 LauncherModel.setUser(user);
583 }
585 onTease: launcher.tease()
587 Binding {
588 target: ApplicationManager
589 property: "suspended"
590 value: greeter.shown && greeterWrapper.showProgress == 1
591 }
592 }
593 }
595 Connections {
596 id: callConnection
597 target: callManager
599 onHasCallsChanged: {
600 if (shell.locked && callManager.hasCalls) {
601 // We just received an incoming call while locked. The
602 // indicator will have already launched dialer-app for us, but
603 // there is a race between "hasCalls" changing and the dialer
604 // starting up. So in case we lose that race, we'll start/
605 // focus the dialer ourselves here too. Even if the indicator
606 // didn't launch the dialer for some reason (or maybe a call
607 // started via some other means), if an active call is
608 // happening, we want to be in the dialer.
609 startLockedApp("dialer-app")
610 }
611 }
612 }
614 Connections {
615 id: powerConnection
616 target: Powerd
618 onStatusChanged: {
619 if (Powerd.status === Powerd.Off && reason !== Powerd.Proximity &&
620 !callManager.hasCalls && !edgeDemo.running) {
621 greeter.showNow()
622 }
623 }
624 }
626 function showHome() {
627 if (edgeDemo.running) {
628 return
629 }
631 if (LightDM.Greeter.active) {
632 greeter.startUnlock()
633 }
635 var animate = !LightDM.Greeter.active && !stages.shown
636 dash.setCurrentScope(0, animate, false)
637 ApplicationManager.requestFocusApplication("unity8-dash")
638 }
640 function showDash() {
641 if (greeter.hasLockedApp || // just in case user gets here
642 (!greeter.narrowMode && shell.locked)) {
643 return
644 }
646 if (greeter.shown) {
647 greeter.hideRight();
648 launcher.fadeOut();
649 }
651 if (ApplicationManager.focusedApplicationId != "unity8-dash") {
652 ApplicationManager.requestFocusApplication("unity8-dash")
653 launcher.fadeOut();
654 }
655 }
657 Item {
658 id: overlay
659 z: 10
661 anchors.fill: parent
663 Panel {
664 id: panel
665 objectName: "panel"
666 anchors.fill: parent //because this draws indicator menus
667 indicators {
668 hides: [launcher]
669 available: edgeDemo.panelEnabled && (!shell.locked || AccountsService.enableIndicatorsWhileLocked) && !greeter.hasLockedApp
670 contentEnabled: edgeDemo.panelContentEnabled
671 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
673 minimizedPanelHeight: units.gu(3)
674 expandedPanelHeight: units.gu(7)
676 indicatorsModel: visibleIndicators.model
677 }
679 VisibleIndicators {
680 id: visibleIndicators
681 // TODO: This should be sourced by device type (eg "desktop", "tablet", "phone"...)
682 Component.onCompleted: initialise(indicatorProfile)
683 }
684 callHint {
685 greeterShown: greeter.shown || lockscreen.shown
686 }
688 property bool topmostApplicationIsFullscreen:
689 ApplicationManager.focusedApplicationId &&
690 ApplicationManager.findApplication(ApplicationManager.focusedApplicationId).fullscreen
692 fullscreenMode: (topmostApplicationIsFullscreen && !LightDM.Greeter.active && launcher.progress == 0)
693 || greeter.hasLockedApp
694 }
696 Launcher {
697 id: launcher
698 objectName: "launcher"
700 readonly property bool dashSwipe: progress > 0
702 anchors.top: parent.top
703 anchors.bottom: parent.bottom
704 width: parent.width
705 dragAreaWidth: shell.edgeSize
706 available: edgeDemo.launcherEnabled && (!shell.locked || AccountsService.enableLauncherWhileLocked) && !greeter.hasLockedApp
708 onShowDashHome: showHome()
709 onDash: showDash()
710 onDashSwipeChanged: {
711 if (dashSwipe) {
712 dash.setCurrentScope(0, false, true)
713 }
714 }
715 onLauncherApplicationSelected: {
716 if (greeter.hasLockedApp) {
717 greeter.startUnlock()
718 }
719 if (!edgeDemo.running)
720 shell.activateApplication(appId)
721 }
722 onShownChanged: {
723 if (shown) {
724 panel.indicators.hide()
725 }
726 }
727 }
729 Rectangle {
730 id: modalNotificationBackground
732 visible: notifications.useModal && (notifications.state == "narrow")
733 color: "#000000"
734 anchors.fill: parent
735 opacity: 0.9
737 MouseArea {
738 anchors.fill: parent
739 }
740 }
742 Notifications {
743 id: notifications
745 model: NotificationBackend.Model
746 margin: units.gu(1)
748 y: topmostIsFullscreen ? 0 : panel.panelHeight
749 width: parent.width
750 height: parent.height - (topmostIsFullscreen ? 0 : panel.panelHeight)
752 states: [
753 State {
754 name: "narrow"
755 when: overlay.width <= units.gu(60)
756 AnchorChanges { target: notifications; anchors.left: parent.left }
757 },
758 State {
759 name: "wide"
760 when: overlay.width > units.gu(60)
761 AnchorChanges { target: notifications; anchors.left: undefined }
762 PropertyChanges { target: notifications; width: units.gu(38) }
763 }
764 ]
765 }
766 }
768 Dialogs {
769 id: dialogs
770 anchors.fill: parent
771 z: overlay.z + 10
772 onPowerOffClicked: {
773 shutdownFadeOutRectangle.enabled = true;
774 shutdownFadeOutRectangle.visible = true;
775 shutdownFadeOut.start();
776 }
777 }
779 Label {
780 id: alphaDisclaimerLabel
781 anchors.centerIn: parent
782 visible: ApplicationManager.fake ? ApplicationManager.fake : false
783 z: dialogs.z + 10
784 text: "EARLY ALPHA\nNOT READY FOR USE"
785 color: "lightgrey"
786 opacity: 0.2
787 font.weight: Font.Black
788 horizontalAlignment: Text.AlignHCenter
789 verticalAlignment: Text.AlignVCenter
790 fontSizeMode: Text.Fit
791 rotation: -45
792 scale: Math.min(parent.width, parent.height) / width
793 }
795 EdgeDemo {
796 id: edgeDemo
797 objectName: "edgeDemo"
798 z: alphaDisclaimerLabel.z + 10
799 paused: Powerd.status === Powerd.Off // Saves power
800 greeter: greeter
801 launcher: launcher
802 panel: panel
803 stages: stages
804 }
806 Connections {
807 target: SessionBroadcast
808 onShowHome: showHome()
809 }
811 Rectangle {
812 id: shutdownFadeOutRectangle
813 z: edgeDemo.z + 10
814 enabled: false
815 visible: false
816 color: "black"
817 anchors.fill: parent
818 opacity: 0.0
819 NumberAnimation on opacity {
820 id: shutdownFadeOut
821 from: 0.0
822 to: 1.0
823 onStopped: {
824 if (shutdownFadeOutRectangle.enabled && shutdownFadeOutRectangle.visible) {
825 DBusUnitySessionService.Shutdown();
826 }
827 }
828 }
829 }