on 16d0d22 help sign in
unity8/qml/Shell.qml
933 lines 30 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 AccountsService 0.1
19import GSettings 1.0
20import Unity.Application 0.1
21import Ubuntu.Components 0.1
22import Ubuntu.Components.Popups 0.1
23import Ubuntu.Gestures 0.1
24import Unity.Launcher 0.1
25import LightDM 0.1 as LightDM
26import Powerd 0.1
27import SessionBroadcast 0.1
28import "Dash"
29import "Greeter"
30import "Launcher"
31import "Panel"
32import "Components"
33import "Notifications"
34import Unity.Notifications 1.0 as NotificationBackend
35import Unity.Session 0.1
37FocusScope {
38 id: shell
40 // this is only here to select the width / height of the window if not running fullscreen
41 property bool tablet: false
42 width: tablet ? units.gu(160) : applicationArguments.hasGeometry() ? applicationArguments.width() : units.gu(40)
43 height: tablet ? units.gu(100) : applicationArguments.hasGeometry() ? applicationArguments.height() : units.gu(71)
45 property real edgeSize: units.gu(2)
46 property url defaultBackground: Qt.resolvedUrl(shell.width >= units.gu(60) ? "graphics/tablet_background.jpg" : "graphics/phone_background.jpg")
47 property url background
48 readonly property real panelHeight: panel.panelHeight
50 property bool dashShown: dash.shown
52 property bool sideStageEnabled: shell.width >= units.gu(100)
53 readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId
55 function activateApplication(appId) {
56 if (ApplicationManager.findApplication(appId)) {
57 ApplicationManager.requestFocusApplication(appId);
58 stages.show(true);
59 if (stages.locked && ApplicationManager.focusedApplicationId == appId) {
60 applicationsDisplayLoader.item.select(appId);
61 }
62 } else {
63 var execFlags = shell.sideStageEnabled ? ApplicationManager.NoFlag : ApplicationManager.ForceMainStage;
64 ApplicationManager.startApplication(appId, execFlags);
65 stages.show(false);
66 }
67 }
69 Binding {
70 target: LauncherModel
71 property: "applicationManager"
72 value: ApplicationManager
73 }
75 Component.onCompleted: {
76 Theme.name = "Ubuntu.Components.Themes.SuruGradient"
77 }
79 GSettings {
80 id: backgroundSettings
81 schema.id: "org.gnome.desktop.background"
82 }
83 property url gSettingsPicture: backgroundSettings.pictureUri != undefined && backgroundSettings.pictureUri.length > 0 ? backgroundSettings.pictureUri : shell.defaultBackground
84 onGSettingsPictureChanged: {
85 shell.background = gSettingsPicture
86 }
88 VolumeControl {
89 id: volumeControl
90 }
92 Keys.onVolumeUpPressed: volumeControl.volumeUp()
93 Keys.onVolumeDownPressed: volumeControl.volumeDown()
95 Item {
96 id: underlayClipper
97 anchors.fill: parent
98 anchors.rightMargin: stages.overlayWidth
99 clip: stages.overlayMode && !stages.painting
101 InputFilterArea {
102 anchors.fill: parent
103 blockInput: parent.clip
104 }
106 Item {
107 id: underlay
108 objectName: "underlay"
109 anchors.fill: parent
110 anchors.rightMargin: -parent.anchors.rightMargin
112 // Whether the underlay is fully covered by opaque UI elements.
113 property bool fullyCovered: panel.indicators.fullyOpened && shell.width <= panel.indicators.width
115 // Whether the user should see the topmost application surface (if there's one at all).
116 readonly property bool applicationSurfaceShouldBeSeen: stages.shown && !stages.painting && !stages.overlayMode
118 // NB! Application surfaces are stacked behind the shell one. So they can only be seen by the user
119 // through the translucent parts of the shell surface.
120 visible: !fullyCovered && !applicationSurfaceShouldBeSeen
122 Rectangle {
123 anchors.fill: parent
124 color: "black"
125 opacity: dash.disappearingAnimationProgress
126 }
128 Image {
129 anchors.fill: dash
130 source: shell.width > shell.height ? "Dash/graphics/paper_landscape.png" : "Dash/graphics/paper_portrait.png"
131 fillMode: Image.PreserveAspectCrop
132 horizontalAlignment: Image.AlignRight
133 verticalAlignment: Image.AlignTop
134 }
136 Dash {
137 id: dash
138 objectName: "dash"
140 available: !LightDM.Greeter.active
141 hides: [stages, launcher, panel.indicators]
142 shown: disappearingAnimationProgress !== 1.0 && greeterWrapper.showProgress !== 1.0
143 enabled: disappearingAnimationProgress === 0.0 && greeterWrapper.showProgress === 0.0 && edgeDemo.dashEnabled
145 anchors {
146 fill: parent
147 topMargin: panel.panelHeight
148 }
150 contentScale: 1.0 - 0.2 * disappearingAnimationProgress
151 opacity: 1.0 - disappearingAnimationProgress
152 property real disappearingAnimationProgress: {
153 if (stages.overlayMode) {
154 return 0;
155 } else {
156 return stages.showProgress
157 }
158 }
160 // FIXME: only necessary because stages.showProgress is not animated
161 Behavior on disappearingAnimationProgress { SmoothedAnimation { velocity: 5 }}
162 }
163 }
164 }
166 EdgeDragArea {
167 id: stagesDragHandle
168 direction: Direction.Leftwards
170 anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
171 width: shell.edgeSize
173 property real progress: stages.width
175 onTouchXChanged: {
176 if (status == DirectionalDragArea.Recognized) {
177 if (ApplicationManager.count == 0) {
178 progress = Math.max(stages.width - stagesDragHandle.width + touchX, stages.width * .3)
179 } else {
180 progress = stages.width - stagesDragHandle.width + touchX
181 }
182 }
183 }
185 onDraggingChanged: {
186 if (!dragging) {
187 if (ApplicationManager.count > 0 && progress < stages.width - units.gu(10)) {
188 stages.show(true)
189 }
190 stagesDragHandle.progress = stages.width;
191 }
192 }
193 }
195 Item {
196 id: stages
197 objectName: "stages"
198 width: parent.width
199 height: parent.height
201 x: {
202 if (shown) {
203 if (overlayMode || locked || greeter.fakeActiveForApp !== "") {
204 return 0;
205 }
206 return launcher.progress
207 } else {
208 return stagesDragHandle.progress
209 }
210 }
212 Behavior on x { SmoothedAnimation { velocity: 600; duration: UbuntuAnimation.FastDuration } }
214 property bool shown: false
216 property real showProgress: overlayMode ? 0 : MathUtils.clamp(1 - x / shell.width, 0, 1)
218 property bool fullyShown: x == 0
219 property bool fullyHidden: x == width
221 property bool painting: applicationsDisplayLoader.item ? applicationsDisplayLoader.item.painting : false
222 property bool fullscreen: applicationsDisplayLoader.item ? applicationsDisplayLoader.item.fullscreen : false
223 property bool overlayMode: applicationsDisplayLoader.item ? applicationsDisplayLoader.item.overlayMode : false
224 property int overlayWidth: applicationsDisplayLoader.item ? applicationsDisplayLoader.item.overlayWidth : false
225 property bool locked: applicationsDisplayLoader.item ? applicationsDisplayLoader.item.locked : false
227 function show(focusApp) {
228 shown = true;
229 panel.indicators.hide();
230 edgeDemo.stopDemo();
231 greeter.hide();
232 if (!ApplicationManager.focusedApplicationId && ApplicationManager.count > 0 && focusApp) {
233 ApplicationManager.focusApplication(ApplicationManager.get(0).appId);
234 }
235 }
237 function hide() {
238 shown = false;
239 if (ApplicationManager.focusedApplicationId) {
240 ApplicationManager.unfocusCurrentApplication();
241 }
242 }
244 Connections {
245 target: ApplicationManager
247 onFocusRequested: {
248 if (greeter.fakeActiveForApp !== "" && greeter.fakeActiveForApp !== appId) {
249 lockscreen.show();
250 }
251 greeter.hide();
252 stages.show(true);
253 }
255 onFocusedApplicationIdChanged: {
256 if (greeter.fakeActiveForApp !== "" && greeter.fakeActiveForApp !== ApplicationManager.focusedApplicationId) {
257 lockscreen.show();
258 }
259 if (ApplicationManager.focusedApplicationId.length > 0) {
260 stages.show(false);
261 } else {
262 if (!stages.overlayMode) {
263 stages.hide();
264 }
265 }
266 }
268 onApplicationAdded: {
269 stages.show(false);
270 }
272 onApplicationRemoved: {
273 if (ApplicationManager.focusedApplicationId.length == 0) {
274 stages.hide();
275 }
276 }
277 }
279 property bool dialogShown: false
281 Component {
282 id: logoutDialog
283 Dialog {
284 id: dialogueLogout
285 title: "Logout"
286 text: "Are you sure that you want to logout?"
287 Button {
288 text: "Cancel"
289 onClicked: {
290 PopupUtils.close(dialogueLogout);
291 stages.dialogShown = false;
292 }
293 }
294 Button {
295 text: "Yes"
296 onClicked: {
297 DBusUnitySessionService.Logout();
298 PopupUtils.close(dialogueLogout);
299 stages.dialogShown = false;
300 }
301 }
302 }
303 }
305 Component {
306 id: shutdownDialog
307 Dialog {
308 id: dialogueShutdown
309 title: "Shutdown"
310 text: "Are you sure that you want to shutdown?"
311 Button {
312 text: "Cancel"
313 onClicked: {
314 PopupUtils.close(dialogueShutdown);
315 stages.dialogShown = false;
316 }
317 }
318 Button {
319 text: "Yes"
320 onClicked: {
321 dBusUnitySessionServiceConnection.closeAllApps();
322 DBusUnitySessionService.Shutdown();
323 PopupUtils.close(dialogueShutdown);
324 stages.dialogShown = false;
325 }
326 }
327 }
328 }
330 Component {
331 id: rebootDialog
332 Dialog {
333 id: dialogueReboot
334 title: "Reboot"
335 text: "Are you sure that you want to reboot?"
336 Button {
337 text: "Cancel"
338 onClicked: {
339 PopupUtils.close(dialogueReboot)
340 stages.dialogShown = false;
341 }
342 }
343 Button {
344 text: "Yes"
345 onClicked: {
346 dBusUnitySessionServiceConnection.closeAllApps();
347 DBusUnitySessionService.Reboot();
348 PopupUtils.close(dialogueReboot);
349 stages.dialogShown = false;
350 }
351 }
352 }
353 }
355 Component {
356 id: powerDialog
357 Dialog {
358 id: dialoguePower
359 title: "Power"
360 text: i18n.tr("Are you sure you would like to turn power off?")
361 Button {
362 text: i18n.tr("Power off")
363 onClicked: {
364 dBusUnitySessionServiceConnection.closeAllApps();
365 PopupUtils.close(dialoguePower);
366 stages.dialogShown = false;
367 shutdownFadeOutRectangle.enabled = true;
368 shutdownFadeOutRectangle.visible = true;
369 shutdownFadeOut.start();
370 }
371 }
372 Button {
373 text: i18n.tr("Restart")
374 onClicked: {
375 dBusUnitySessionServiceConnection.closeAllApps();
376 DBusUnitySessionService.Reboot();
377 PopupUtils.close(dialoguePower);
378 stages.dialogShown = false;
379 }
380 }
381 Button {
382 text: i18n.tr("Cancel")
383 onClicked: {
384 PopupUtils.close(dialoguePower);
385 stages.dialogShown = false;
386 }
387 }
388 }
389 }
391 function showPowerDialog() {
392 if (!stages.dialogShown) {
393 stages.dialogShown = true;
394 PopupUtils.open(powerDialog);
395 }
396 }
398 Connections {
399 id: dBusUnitySessionServiceConnection
400 objectName: "dBusUnitySessionServiceConnection"
401 target: DBusUnitySessionService
403 function closeAllApps() {
404 while (true) {
405 var app = ApplicationManager.get(0);
406 if (app === null) {
407 break;
408 }
409 ApplicationManager.stopApplication(app.appId);
410 }
411 }
413 onLogoutRequested: {
414 // Display a dialog to ask the user to confirm.
415 if (!stages.dialogShown) {
416 stages.dialogShown = true;
417 PopupUtils.open(logoutDialog);
418 }
419 }
421 onShutdownRequested: {
422 // Display a dialog to ask the user to confirm.
423 if (!stages.dialogShown) {
424 stages.dialogShown = true;
425 PopupUtils.open(shutdownDialog);
426 }
427 }
429 onRebootRequested: {
430 // Display a dialog to ask the user to confirm.
431 if (!stages.dialogShown) {
432 stages.dialogShown = true;
433 PopupUtils.open(rebootDialog);
434 }
435 }
437 onLogoutReady: {
438 closeAllApps();
439 Qt.quit();
440 }
441 }
443 Loader {
444 id: applicationsDisplayLoader
445 anchors.fill: parent
447 source: shell.sideStageEnabled ? "Stages/StageWithSideStage.qml" : "Stages/PhoneStage.qml"
449 Binding {
450 target: applicationsDisplayLoader.item
451 property: "objectName"
452 value: "stage"
453 }
454 Binding {
455 target: applicationsDisplayLoader.item
456 property: "moving"
457 value: !stages.fullyShown
458 }
459 Binding {
460 target: applicationsDisplayLoader.item
461 property: "shown"
462 value: stages.shown
463 }
464 Binding {
465 target: applicationsDisplayLoader.item
466 property: "dragAreaWidth"
467 value: shell.edgeSize
468 }
469 Binding {
470 target: applicationsDisplayLoader.item
471 property: "spreadEnabled"
472 value: greeter.fakeActiveForApp === "" // to support emergency dialer hack
473 }
474 }
475 }
477 Lockscreen {
478 id: lockscreen
479 objectName: "lockscreen"
481 readonly property int backgroundTopMargin: -panel.panelHeight
483 hides: [launcher, panel.indicators]
484 shown: false
485 enabled: true
486 showAnimation: StandardAnimation { property: "opacity"; to: 1 }
487 hideAnimation: StandardAnimation { property: "opacity"; to: 0 }
488 y: panel.panelHeight
489 x: required ? 0 : - width
490 width: parent.width
491 height: parent.height - panel.panelHeight
492 background: shell.background
493 minPinLength: 4
494 maxPinLength: 4
496 onEntered: LightDM.Greeter.respond(passphrase);
497 onCancel: greeter.show()
498 onEmergencyCall: {
499 greeter.fakeActiveForApp = "dialer-app"
500 shell.activateApplication("dialer-app")
501 lockscreen.hide()
502 }
504 onShownChanged: if (shown) greeter.fakeActiveForApp = ""
506 Component.onCompleted: {
507 if (LightDM.Users.count == 1) {
508 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole))
509 }
510 }
511 }
513 Connections {
514 target: LightDM.Greeter
516 onShowGreeter: greeter.show()
518 onShowPrompt: {
519 if (LightDM.Users.count == 1) {
520 // TODO: There's no better way for now to determine if its a PIN or a passphrase.
521 if (text == "PIN") {
522 lockscreen.alphaNumeric = false
523 } else {
524 lockscreen.alphaNumeric = true
525 }
526 lockscreen.placeholderText = i18n.tr("Please enter %1").arg(text);
527 lockscreen.show();
528 }
529 }
531 onAuthenticationComplete: {
532 if (LightDM.Greeter.promptless) {
533 return;
534 }
535 if (LightDM.Greeter.authenticated) {
536 lockscreen.hide();
537 greeter.login();
538 } else {
539 lockscreen.clear(true);
540 }
541 }
542 }
544 Binding {
545 target: LightDM.Greeter
546 property: "active"
547 value: greeter.shown || lockscreen.shown || greeter.fakeActiveForApp != ""
548 }
550 Rectangle {
551 anchors.fill: parent
552 color: "black"
553 opacity: greeterWrapper.showProgress * 0.8
554 }
556 Item {
557 // Just a tiny wrapper to adjust greeter's x without messing with its own dragging
558 id: greeterWrapper
559 x: launcher.progress
560 y: panel.panelHeight
561 width: parent.width
562 height: parent.height - panel.panelHeight
564 Behavior on x {
565 enabled: !launcher.dashSwipe
566 StandardAnimation {}
567 }
569 readonly property real showProgress: MathUtils.clamp((1 - x/width) + greeter.showProgress - 1, 0, 1)
570 onShowProgressChanged: if (LightDM.Greeter.promptless && showProgress === 0) greeter.login()
572 Greeter {
573 id: greeter
574 objectName: "greeter"
576 signal sessionStarted() // helpful for tests
578 property string fakeActiveForApp: ""
580 available: true
581 hides: [launcher, panel.indicators]
582 shown: true
584 defaultBackground: shell.background
586 width: parent.width
587 height: parent.height
589 dragHandleWidth: shell.edgeSize
591 function login() {
592 enabled = false;
593 LightDM.Greeter.startSessionSync();
594 sessionStarted();
595 greeter.hide();
596 lockscreen.hide();
597 launcher.hide();
598 enabled = true;
599 }
601 onShownChanged: {
602 if (shown) {
603 lockscreen.reset();
604 if (!LightDM.Greeter.promptless) {
605 lockscreen.show();
606 }
607 // If there is only one user, we start authenticating with that one here.
608 // If there are more users, the Greeter will handle that
609 if (LightDM.Users.count == 1) {
610 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole));
611 }
612 greeter.fakeActiveForApp = "";
613 greeter.forceActiveFocus();
614 }
615 }
617 onUnlocked: greeter.hide()
618 onSelected: {
619 // Update launcher items for new user
620 var user = LightDM.Users.data(uid, LightDM.UserRoles.NameRole);
621 AccountsService.user = user;
622 LauncherModel.setUser(user);
623 }
625 onTease: launcher.tease()
627 Binding {
628 target: ApplicationManager
629 property: "suspended"
630 value: greeter.shown && greeterWrapper.showProgress == 1
631 }
632 }
633 }
635 InputFilterArea {
636 anchors.fill: parent
637 blockInput: ApplicationManager.focusedApplicationId.length === 0 || greeter.shown || lockscreen.shown || launcher.shown
638 || panel.indicators.shown
639 }
641 Connections {
642 id: powerConnection
643 target: Powerd
645 onDisplayPowerStateChange: {
646 // We ignore any display-off signals when the proximity sensor
647 // is active. This usually indicates something like a phone call.
648 if (status == Powerd.Off && reason != Powerd.Proximity) {
649 greeter.showNow();
650 }
652 // No reason to chew demo CPU when user isn't watching
653 if (status == Powerd.Off) {
654 edgeDemo.paused = true;
655 } else if (status == Powerd.On) {
656 edgeDemo.paused = false;
657 }
658 }
659 }
661 function showHome() {
662 if (edgeDemo.running) {
663 return
664 }
666 if (LightDM.Greeter.active) {
667 if (!LightDM.Greeter.promptless) {
668 lockscreen.show()
669 }
670 greeter.hide()
671 }
673 var animate = !LightDM.Greeter.active && !stages.shown
674 dash.setCurrentScope("clickscope", animate, false)
675 stages.hide()
676 }
678 function showDash() {
679 if (LightDM.Greeter.active && !LightDM.Greeter.promptless) {
680 return;
681 }
683 if (stages.shown && !stages.overlayMode && !stages.locked) {
684 stages.hide();
685 launcher.fadeOut();
686 } else {
687 launcher.switchToNextState("visible");
688 }
690 if (greeter.shown) {
691 greeter.hideRight();
692 launcher.fadeOut();
693 }
694 }
696 Item {
697 id: overlay
699 anchors.fill: parent
701 Panel {
702 id: panel
703 objectName: "panel"
704 anchors.fill: parent //because this draws indicator menus
705 indicators {
706 hides: [launcher]
707 available: edgeDemo.panelEnabled && greeter.fakeActiveForApp === ""
708 contentEnabled: edgeDemo.panelContentEnabled
709 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
710 panelHeight: units.gu(3)
711 }
712 property string focusedAppId: ApplicationManager.focusedApplicationId
713 property var focusedApplication: ApplicationManager.findApplication(focusedAppId)
714 fullscreenMode: (focusedApplication && stages.fullscreen && !LightDM.Greeter.active) || greeter.fakeActiveForApp !== ""
716 InputFilterArea {
717 anchors {
718 top: parent.top
719 left: parent.left
720 right: parent.right
721 }
722 height: (panel.fullscreenMode) ? shell.edgeSize : panel.panelHeight
723 blockInput: true
724 }
725 }
727 InputFilterArea {
728 blockInput: launcher.shown
729 anchors {
730 top: parent.top
731 bottom: parent.bottom
732 left: parent.left
733 }
734 width: launcher.width
735 }
737 Launcher {
738 id: launcher
739 objectName: "launcher"
741 readonly property bool dashSwipe: progress > 0
743 anchors.top: parent.top
744 anchors.bottom: parent.bottom
745 width: parent.width
746 dragAreaWidth: shell.edgeSize
747 available: edgeDemo.launcherEnabled && greeter.fakeActiveForApp === ""
749 onShowDashHome: showHome()
750 onDash: showDash()
751 onDashSwipeChanged: if (dashSwipe && stages.shown) dash.setCurrentScope("clickscope", false, true)
752 onLauncherApplicationSelected: {
753 if (greeter.fakeActiveForApp !== "") {
754 lockscreen.show()
755 }
756 if (!edgeDemo.running)
757 shell.activateApplication(appId)
758 }
759 onShownChanged: {
760 if (shown) {
761 panel.indicators.hide()
762 }
763 }
764 }
766 Rectangle {
767 id: modalNotificationBackground
769 visible: notifications.useModal && !greeter.shown && (notifications.state == "narrow")
770 color: "#000000"
771 anchors.fill: parent
772 opacity: 0.5
774 MouseArea {
775 anchors.fill: parent
776 }
778 InputFilterArea {
779 anchors.fill: parent
780 blockInput: modalNotificationBackground.visible
781 }
782 }
784 Notifications {
785 id: notifications
787 model: NotificationBackend.Model
788 margin: units.gu(1)
790 y: panel.panelHeight
791 width: parent.width
792 height: parent.height - panel.panelHeight
794 states: [
795 State {
796 name: "narrow"
797 when: overlay.width <= units.gu(60)
798 AnchorChanges { target: notifications; anchors.left: parent.left }
799 },
800 State {
801 name: "wide"
802 when: overlay.width > units.gu(60)
803 AnchorChanges { target: notifications; anchors.left: undefined }
804 PropertyChanges { target: notifications; width: units.gu(38) }
805 }
806 ]
808 InputFilterArea {
809 anchors { left: parent.left; right: parent.right }
810 height: parent.contentHeight
811 blockInput: height > 0
812 }
813 }
814 }
816 focus: true
817 onFocusChanged: if (!focus) forceActiveFocus();
819 InputFilterArea {
820 anchors {
821 top: parent.top
822 bottom: parent.bottom
823 left: parent.left
824 }
825 width: shell.edgeSize
826 blockInput: true
827 }
829 InputFilterArea {
830 anchors {
831 top: parent.top
832 bottom: parent.bottom
833 right: parent.right
834 }
835 width: shell.edgeSize
836 blockInput: true
837 }
839 Binding {
840 target: i18n
841 property: "domain"
842 value: "unity8"
843 }
845 OSKController {
846 anchors.topMargin: panel.panelHeight
847 anchors.fill: parent // as needs to know the geometry of the shell
848 }
850 //FIXME: This should be handled in the input stack, keyboard shouldnt propagate
851 MouseArea {
852 anchors.bottom: parent.bottom
853 anchors.left: parent.left
854 anchors.right: parent.right
855 height: ApplicationManager.keyboardVisible ? ApplicationManager.keyboardHeight : 0
857 enabled: ApplicationManager.keyboardVisible
858 }
860 Label {
861 anchors.centerIn: parent
862 visible: ApplicationManager.fake ? ApplicationManager.fake : false
863 text: "EARLY ALPHA\nNOT READY FOR USE"
864 color: "lightgrey"
865 opacity: 0.2
866 font.weight: Font.Black
867 horizontalAlignment: Text.AlignHCenter
868 verticalAlignment: Text.AlignVCenter
869 fontSizeMode: Text.Fit
870 rotation: -45
871 scale: Math.min(parent.width, parent.height) / width
872 }
874 EdgeDemo {
875 id: edgeDemo
876 greeter: greeter
877 launcher: launcher
878 dash: dash
879 indicators: panel.indicators
880 underlay: underlay
881 }
883 Connections {
884 target: SessionBroadcast
885 onShowHome: showHome()
886 }
888 Keys.onPressed: {
889 if (event.key == Qt.Key_PowerOff || event.key == Qt.Key_PowerDown) {
890 if (!powerKeyTimer.running) {
891 powerKeyTimer.start();
892 }
893 event.accepted = true;
894 }
895 }
897 Keys.onReleased: {
898 if (event.key == Qt.Key_PowerOff || event.key == Qt.Key_PowerDown) {
899 powerKeyTimer.stop();
900 event.accepted = true;
901 }
902 }
904 Timer {
905 id: powerKeyTimer
906 interval: 2000
907 repeat: false
908 triggeredOnStart: false
910 onTriggered: {
911 stages.showPowerDialog();
912 }
913 }
915 Rectangle {
916 id: shutdownFadeOutRectangle
917 enabled: false
918 visible: false
919 color: "black"
920 anchors.fill: parent
921 opacity: 0.0
922 NumberAnimation on opacity {
923 id: shutdownFadeOut
924 from: 0.0
925 to: 1.0
926 onStopped: {
927 if (shutdownFadeOutRectangle.enabled && shutdownFadeOutRectangle.visible) {
928 DBusUnitySessionService.Shutdown();
929 }
930 }
931 }
932 }