on cac9b59 help sign in
unity8/Shell.qml
839 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 GSettings 1.0
19import Ubuntu.Application 0.1
20import Ubuntu.Components 0.1
21import Ubuntu.Gestures 0.1
22import LightDM 0.1 as LightDM
23import AccountsService 0.1
24import Powerd 0.1
25import "Dash"
26import "Greeter"
27import "Launcher"
28import "Panel"
29import "Hud"
30import "Components"
31import "Components/Math.js" as MathLocal
32import "Bottombar"
33import "SideStage"
34import "Notifications"
35import Unity.Notifications 1.0 as NotificationBackend
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: 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
51 property bool stageScreenshotsReady: {
52 if (sideStage.shown) {
53 if (mainStage.applications.count > 0) {
54 return mainStage.usingScreenshots && sideStage.usingScreenshots;
55 } else {
56 return sideStage.usingScreenshots;
57 }
58 } else {
59 return mainStage.usingScreenshots;
60 }
61 }
63 property bool showEdgeDemo: false
64 property bool showEdgeDemoInGreeter: showEdgeDemo //AccountsService.getUserProperty("lightdm", "demo-edges")
66 function hideEdgeDemo() {
67 var user = LightDM.Users.data(greeter.currentIndex, LightDM.UserRoles.NameRole);
68 AccountsService.setUserProperty(user, "demo-edges", false);
69 shell.showEdgeDemo = false;
70 }
71 function hideEdgeDemoInGreeter() {
72 //AccountsService.setUserProperty("lightdm", "demo-edges", false);
73 shell.showEdgeDemoInGreeter = false;
74 }
76 property ListModel searchHistory: SearchHistoryModel {}
78 property var applicationManager: ApplicationManagerWrapper {}
80 Component.onCompleted: {
81 Theme.name = "Ubuntu.Components.Themes.SuruGradient"
83 applicationManager.sideStageEnabled = Qt.binding(function() { return sideStage.enabled })
85 // FIXME: if application focused before shell starts, shell draws on top of it only.
86 // We should detect already running applications on shell start and bring them to the front.
87 applicationManager.unfocusCurrentApplication();
88 }
90 readonly property bool fullscreenMode: {
91 if (greeter.shown || lockscreen.shown) {
92 return false;
93 } else if (mainStage.usingScreenshots) { // Window Manager animating so want to re-evaluate fullscreen mode
94 return mainStage.switchingFromFullscreenToFullscreen;
95 } else if (applicationManager.mainStageFocusedApplication) {
96 return applicationManager.mainStageFocusedApplication.fullscreen;
97 } else {
98 return false;
99 }
100 }
102 Connections {
103 target: applicationManager
104 ignoreUnknownSignals: true
105 onFocusRequested: {
106 // TODO: this should be protected to only unlock for certain applications / certain usecases
107 // potentially only in connection with a notification
108 greeter.hide();
109 shell.activateApplication(desktopFile);
110 }
111 }
113 function activateApplication(desktopFile, argument) {
114 if (applicationManager) {
115 // For newly started applications, as it takes them time to draw their first frame
116 // we add a delay before we hide the animation screenshots to compensate.
117 var addDelay = !applicationManager.getApplicationFromDesktopFile(desktopFile);
119 var application;
120 application = applicationManager.activateApplication(desktopFile, argument);
121 if (application == null) {
122 return;
123 }
124 if (application.stage == ApplicationInfo.MainStage || !sideStage.enabled) {
125 mainStage.activateApplication(desktopFile, addDelay);
126 } else {
127 sideStage.activateApplication(desktopFile, addDelay);
128 }
129 stages.show();
130 }
131 }
133 GSettings {
134 id: backgroundSettings
135 schema.id: "org.gnome.desktop.background"
136 }
137 property url gSettingsPicture: backgroundSettings.pictureUri != undefined && backgroundSettings.pictureUri.length > 0 ? backgroundSettings.pictureUri : shell.defaultBackground
138 onGSettingsPictureChanged: {
139 shell.background = gSettingsPicture
140 }
142 // This is a dummy image that is needed to determine if the picture url
143 // in backgroundSettings points to a valid picture file.
144 // We can't do this with the real background image because setting a
145 // new source in onStatusChanged triggers a binding loop detection
146 // inside Image, which causes it not to render even though a valid source
147 // would be set. We don't mind about this image staying black and just
148 // use it for verification to populate the source for the real
149 // background image.
150 Image {
151 source: shell.background
152 height: 0
153 width: 0
154 sourceSize.height: 0
155 sourceSize.width: 0
156 onStatusChanged: {
157 if (status == Image.Error && source != shell.defaultBackground) {
158 shell.background = defaultBackground
159 }
160 }
161 }
163 VolumeControl {
164 id: volumeControl
165 }
167 Keys.onVolumeUpPressed: volumeControl.volumeUp()
168 Keys.onVolumeDownPressed: volumeControl.volumeDown()
170 Item {
171 id: underlay
172 objectName: "underlay"
173 anchors.fill: parent
175 // Whether the underlay is fully covered by opaque UI elements.
176 property bool fullyCovered: panel.indicators.fullyOpened && shell.width <= panel.indicatorsMenuWidth
178 // Whether the user should see the topmost application surface (if there's one at all).
179 property bool applicationSurfaceShouldBeSeen:
180 (mainStage.applications && mainStage.applications.count > 0)
181 && (!stages.fullyHidden && !mainStage.usingScreenshots)
183 // NB! Application surfaces are stacked behing the shell one. So they can only be seen by the user
184 // through the translucent parts of the shell surface.
185 visible: !fullyCovered && !applicationSurfaceShouldBeSeen
187 CrossFadeImage {
188 id: backgroundImage
189 objectName: "backgroundImage"
191 anchors.fill: parent
192 source: shell.background
193 }
195 Rectangle {
196 anchors.fill: parent
197 color: "black"
198 opacity: dash.disappearingAnimationProgress
199 }
201 Dash {
202 id: dash
203 objectName: "dash"
205 available: !greeter.shown && !lockscreen.shown
206 hides: [stages, launcher, panel.indicators]
207 shown: disappearingAnimationProgress !== 1.0
208 enabled: disappearingAnimationProgress === 0.0 && !leftEdgeDemo.active && !topEdgeDemo.active && !finalEdgeDemo.active
209 // FIXME: unfocus all applications when going back to the dash
210 onEnabledChanged: {
211 if (enabled) {
212 shell.applicationManager.unfocusCurrentApplication()
213 }
214 }
216 anchors {
217 fill: parent
218 topMargin: panel.panelHeight
219 }
221 contentScale: 1.0 - 0.2 * disappearingAnimationProgress
222 opacity: 1.0 - disappearingAnimationProgress
223 property real disappearingAnimationProgress: {
224 if (greeter.shown) {
225 return greeter.showProgress;
226 } else {
227 return stagesOuterContainer.showProgress;
228 }
229 }
231 // FIXME: only necessary because stagesOuterContainer.showProgress and
232 // greeterRevealer.animatedProgress are not animated
233 Behavior on disappearingAnimationProgress { SmoothedAnimation { velocity: 5 }}
234 }
236 DemoOverlay {
237 id: topEdgeDemo
239 edge: "top"
240 title: i18n.tr("Top edge")
241 text: i18n.tr("Try swiping from the top edge to access the indicators")
242 anchors.fill: dash
243 visible: false
244 available: shell.showEdgeDemo
245 onSkip: shell.hideEdgeDemo()
247 Connections {
248 target: greeter
249 onShownChanged: if (!greeter.shown) topEdgeDemo.show()
250 }
252 Connections {
253 target: panel.indicators
254 onFullyOpenedChanged: if (panel.indicators.fullyOpened) topEdgeDemo.hideNow()
255 }
256 }
258 DemoOverlay {
259 id: leftEdgeDemo
261 edge: "left"
262 title: i18n.tr("Left edge")
263 text: i18n.tr("Swipe from the left to reveal the launcher for quick access to apps")
264 anchors.fill: dash
265 visible: false
266 available: shell.showEdgeDemo
267 onSkip: shell.hideEdgeDemo()
269 Connections {
270 target: bottomEdgeDemo
271 onActiveChanged: if (!bottomEdgeDemo.active) leftEdgeDemo.show()
272 }
274 Connections {
275 target: launcher
276 onStateChanged: if (launcher.state == "visible") leftEdgeDemo.hide()
277 }
278 }
279 }
281 Item {
282 id: stagesOuterContainer
284 width: parent.width
285 height: parent.height
286 x: launcher.progress
287 Behavior on x {SmoothedAnimation{velocity: 600}}
289 property real showProgress:
290 MathLocal.clamp(1 - (x + stages.x) / shell.width, 0, 1)
292 Showable {
293 id: stages
294 objectName: "stages"
296 x: width
298 property bool fullyShown: shown && x == 0 && parent.x == 0
299 property bool fullyHidden: !shown && x == width
300 available: !greeter.shown
301 hides: [launcher, panel.indicators]
302 shown: false
303 opacity: 1.0
304 showAnimation: StandardAnimation { property: "x"; duration: 350; to: 0; easing.type: Easing.OutCubic }
305 hideAnimation: StandardAnimation { property: "x"; duration: 350; to: width; easing.type: Easing.OutCubic }
307 width: parent.width
308 height: parent.height
310 // close the stages when no focused application remains
311 Connections {
312 target: shell.applicationManager
313 onMainStageFocusedApplicationChanged: stages.closeIfNoApplications()
314 onSideStageFocusedApplicationChanged: stages.closeIfNoApplications()
315 ignoreUnknownSignals: true
316 }
318 function closeIfNoApplications() {
319 if (!shell.applicationManager.mainStageFocusedApplication
320 && !shell.applicationManager.sideStageFocusedApplication
321 && shell.applicationManager.mainStageApplications.count == 0
322 && shell.applicationManager.sideStageApplications.count == 0) {
323 stages.hide();
324 }
325 }
327 // show the stages when an application gets the focus
328 Connections {
329 target: shell.applicationManager
330 onMainStageFocusedApplicationChanged: {
331 if (shell.applicationManager.mainStageFocusedApplication) {
332 mainStage.show();
333 stages.show();
334 }
335 }
336 onSideStageFocusedApplicationChanged: {
337 if (shell.applicationManager.sideStageFocusedApplication) {
338 sideStage.show();
339 stages.show();
340 }
341 }
342 ignoreUnknownSignals: true
343 }
345 Stage {
346 id: mainStage
348 anchors.fill: parent
349 fullyShown: stages.fullyShown
350 fullyHidden: stages.fullyHidden
351 shouldUseScreenshots: !fullyShown
352 rightEdgeEnabled: !sideStage.enabled
354 applicationManager: shell.applicationManager
355 rightEdgeDraggingAreaWidth: shell.edgeSize
356 normalApplicationY: shell.panelHeight
358 shown: true
359 function show() {
360 stages.show();
361 }
362 function hide() {
363 }
365 // FIXME: workaround the fact that focusing a main stage application
366 // raises its surface on top of all other surfaces including the ones
367 // that belong to side stage applications.
368 onFocusedApplicationChanged: {
369 if (focusedApplication && sideStage.focusedApplication && sideStage.fullyShown) {
370 shell.applicationManager.focusApplication(sideStage.focusedApplication);
371 }
372 }
373 }
375 SideStage {
376 id: sideStage
378 applicationManager: shell.applicationManager
379 rightEdgeDraggingAreaWidth: shell.edgeSize
380 normalApplicationY: shell.panelHeight
382 onShownChanged: {
383 if (!shown && mainStage.applications.count == 0) {
384 stages.hide();
385 }
386 }
387 // FIXME: when hiding the side stage, refocus the main stage
388 // application so that it goes in front of the side stage
389 // application and hides it
390 onFullyShownChanged: {
391 if (!fullyShown && stages.fullyShown && sideStage.focusedApplication != null) {
392 shell.applicationManager.focusApplication(mainStage.focusedApplication);
393 }
394 }
396 enabled: shell.width >= units.gu(60)
397 visible: enabled
398 fullyShown: stages.fullyShown && shown
399 && sideStage[sideStageRevealer.boundProperty] == sideStageRevealer.openedValue
400 shouldUseScreenshots: !fullyShown || mainStage.usingScreenshots || sideStageRevealer.pressed
402 available: !greeter.shown && !lockscreen.shown && enabled
403 hides: [launcher, panel.indicators]
404 shown: false
405 showAnimation: StandardAnimation { property: "x"; duration: 350; to: sideStageRevealer.openedValue; easing.type: Easing.OutQuint }
406 hideAnimation: StandardAnimation { property: "x"; duration: 350; to: sideStageRevealer.closedValue; easing.type: Easing.OutQuint }
408 width: units.gu(40)
409 height: stages.height
410 handleExpanded: sideStageRevealer.pressed
411 }
413 Revealer {
414 id: sideStageRevealer
416 enabled: mainStage.applications.count > 0 && sideStage.applications.count > 0
417 && sideStage.available
418 direction: Qt.RightToLeft
419 openedValue: parent.width - sideStage.width
420 hintDisplacement: units.gu(3)
421 /* The size of the sidestage handle needs to be bigger than the
422 typical size used for edge detection otherwise it is really
423 hard to grab.
424 */
425 handleSize: sideStage.shown ? units.gu(4) : shell.edgeSize
426 closedValue: parent.width + sideStage.handleSizeCollapsed
427 target: sideStage
428 x: parent.width - width
429 width: sideStage.width + handleSize * 0.7
430 height: sideStage.height
431 orientation: Qt.Horizontal
432 }
434 DragHandle {
435 id: stagesDragHandle
437 anchors.top: parent.top
438 anchors.bottom: parent.bottom
439 anchors.right: parent.left
441 width: shell.edgeSize
442 direction: Direction.Leftwards
443 property bool haveApps: mainStage.applications.count > 0 || sideStage.applications.count > 0
445 maxTotalDragDistance: haveApps ? parent.width : parent.width * 0.7
446 // Make autocompletion impossible when !haveApps
447 edgeDragEvaluator.minDragDistance: haveApps ? maxTotalDragDistance * 0.1 : Number.MAX_VALUE
448 }
449 }
450 }
452 Lockscreen {
453 id: lockscreen
454 hides: [launcher, panel.indicators, hud]
455 shown: false
456 enabled: true
457 showAnimation: StandardAnimation { property: "opacity"; to: 1 }
458 hideAnimation: StandardAnimation { property: "opacity"; to: 0 }
459 y: panel.panelHeight
460 x: required ? 0 : - width
461 width: parent.width
462 height: parent.height - panel.panelHeight
463 background: shell.background
465 onUnlocked: lockscreen.hide()
466 onCancel: greeter.show()
468 Component.onCompleted: {
469 if (LightDM.Users.count == 1) {
470 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole))
471 greeter.selected(0)
472 }
473 }
474 }
476 Connections {
477 target: LightDM.Greeter
479 onShowPrompt: {
480 if (LightDM.Users.count == 1) {
481 // TODO: There's no better way for now to determine if its a PIN or a passphrase.
482 if (text == "PIN") {
483 lockscreen.alphaNumeric = false
484 } else {
485 lockscreen.alphaNumeric = true
486 }
487 lockscreen.placeholderText = i18n.tr("Please enter %1").arg(text);
488 lockscreen.show();
489 }
490 }
491 }
493 Greeter {
494 id: greeter
495 objectName: "greeter"
497 available: true
498 hides: [launcher, panel.indicators, hud]
499 shown: true
501 y: panel.panelHeight
502 width: parent.width
503 height: parent.height - panel.panelHeight
505 dragHandleWidth: shell.edgeSize
507 onShownChanged: {
508 if (shown) {
509 lockscreen.reset();
510 // If there is only one user, we start authenticating with that one here.
511 // If there are more users, the Greeter will handle that
512 if (LightDM.Users.count == 1) {
513 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole));
514 greeter.selected(0);
515 }
516 greeter.forceActiveFocus();
517 }
518 }
520 onUnlocked: greeter.hide()
521 onSelected: {
522 // Update edge demo hint
523 var user = LightDM.Users.data(uid, LightDM.UserRoles.NameRole)
524 shell.showEdgeDemo = AccountsService.getUserProperty(user, "demo-edges")
525 }
527 onLeftTeaserPressedChanged: {
528 if (leftTeaserPressed) {
529 launcher.tease();
530 }
531 }
533 DemoOverlay {
534 id: rightEdgeDemo
536 edge: "right"
537 title: i18n.tr("Right edge")
538 text: i18n.tr("Try swiping from the right edge to unlock the phone")
539 anchors.fill: parent
540 visible: shell.showEdgeDemoInGreeter
541 onSkip: {
542 shell.hideEdgeDemoInGreeter()
543 shell.hideEdgeDemo()
544 }
546 Connections {
547 target: greeter
549 function hide() {
550 if (rightEdgeDemo.active) {
551 rightEdgeDemo.hide()
552 shell.hideEdgeDemoInGreeter()
553 }
554 }
556 onUnlocked: hide()
557 onShownChanged: if (!greeter.shown) hide()
558 }
559 }
560 }
562 InputFilterArea {
563 anchors.fill: parent
564 blockInput: greeter.shown || lockscreen.shown
565 }
567 Connections {
568 id: powerConnection
569 target: Powerd
571 property var previousMainApp: null
572 property var previousSideApp: null
574 function setFocused(focused) {
575 if (!focused) {
576 // FIXME: *FocusedApplication are not updated when unfocused, hence the need to check whether
577 // the stage was actually shown
578 if (mainStage.fullyShown) powerConnection.previousMainApp = applicationManager.mainStageFocusedApplication;
579 if (sideStage.fullyShown) powerConnection.previousSideApp = applicationManager.sideStageFocusedApplication;
580 applicationManager.unfocusCurrentApplication();
581 } else {
582 if (powerConnection.previousMainApp) {
583 applicationManager.focusApplication(powerConnection.previousMainApp);
584 powerConnection.previousMainApp = null;
585 }
586 if (powerConnection.previousSideApp) {
587 applicationManager.focusApplication(powerConnection.previousSideApp);
588 powerConnection.previousSideApp = null;
589 }
590 }
591 }
593 onPowerStateChange: {
594 if (state == 0) { // suspend
595 powerConnection.setFocused(false);
596 greeter.show();
597 } else if (state == 1) { // active
598 powerConnection.setFocused(true);
599 }
600 }
601 }
603 Item {
604 id: overlay
606 anchors.fill: parent
608 Panel {
609 id: panel
610 anchors.fill: parent //because this draws indicator menus
611 indicatorsMenuWidth: parent.width > units.gu(60) ? units.gu(40) : parent.width
612 indicators {
613 hides: [launcher]
614 available: !rightEdgeDemo.active && !leftEdgeDemo.active && !finalEdgeDemo.active
615 }
616 fullscreenMode: shell.fullscreenMode
617 searchVisible: !greeter.shown && !lockscreen.shown
619 InputFilterArea {
620 anchors.fill: parent
621 blockInput: panel.indicators.shown
622 }
624 DemoOverlay {
625 id: bottomEdgeDemo
627 edge: "bottom"
628 title: i18n.tr("Close")
629 text: i18n.tr("Swipe up again to close the settings screen")
630 anchors.fill: panel.indicators
631 visible: false
632 available: shell.showEdgeDemo
633 onSkip: shell.hideEdgeDemo()
635 Connections {
636 target: panel.indicators
637 onFullyOpenedChanged: if (panel.indicators.fullyOpened) bottomEdgeDemo.show()
638 onPartiallyOpenedChanged: if (!panel.indicators.partiallyOpened && !panel.indicators.fullyOpened) bottomEdgeDemo.hideNow()
639 }
640 }
641 }
643 Hud {
644 id: hud
646 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
647 height: parent.height
649 available: !greeter.shown && !panel.indicators.shown && !lockscreen.shown && !topEdgeDemo.active
650 shown: false
651 showAnimation: StandardAnimation { property: "y"; duration: hud.showableAnimationDuration; to: 0; easing.type: Easing.Linear }
652 hideAnimation: StandardAnimation { property: "y"; duration: hud.showableAnimationDuration; to: hudRevealer.closedValue; easing.type: Easing.Linear }
654 Connections {
655 target: shell.applicationManager
656 onMainStageFocusedApplicationChanged: hud.hide()
657 onSideStageFocusedApplicationChanged: hud.hide()
658 }
660 InputFilterArea {
661 anchors.fill: parent
662 blockInput: hud.shown
663 }
664 }
666 Revealer {
667 id: hudRevealer
669 enabled: hud.shown
670 width: hud.width
671 anchors.left: hud.left
672 height: parent.height
673 target: hud.revealerTarget
674 closedValue: height
675 openedValue: 0
676 direction: Qt.RightToLeft
677 orientation: Qt.Vertical
678 handleSize: hud.handleHeight
679 onCloseClicked: target.hide()
680 }
682 Bottombar {
683 theHud: hud
684 anchors.fill: parent
685 enabled: !panel.indicators.shown
686 applicationIsOnForeground: applicationManager.mainStageFocusedApplication
687 || applicationManager.sideStageFocusedApplication
688 }
690 InputFilterArea {
691 blockInput: launcher.shown
692 anchors {
693 top: parent.top
694 bottom: parent.bottom
695 left: parent.left
696 }
697 width: launcher.width
698 }
700 Launcher {
701 id: launcher
703 anchors.top: parent.top
704 anchors.bottom: parent.bottom
705 width: parent.width
706 dragAreaWidth: shell.edgeSize
707 available: (!greeter.shown || greeter.narrowMode) && !rightEdgeDemo.active && !topEdgeDemo.active && !bottomEdgeDemo.active && !finalEdgeDemo.active
708 onDashItemSelected: {
709 greeter.hide()
710 // Animate if moving between application and dash
711 if (!stages.shown) {
712 dash.setCurrentScope("home.scope", true, false)
713 } else {
714 dash.setCurrentScope("home.scope", false, false)
715 }
716 stages.hide();
717 }
718 onDash: {
719 if (stages.shown) {
720 dash.setCurrentScope("applications.scope", true, false)
721 stages.hide();
722 launcher.hide();
723 }
724 }
725 onLauncherApplicationSelected:{
726 greeter.hide()
727 shell.activateApplication(desktopFile)
728 }
729 onShownChanged: {
730 if (shown) {
731 panel.indicators.hide()
732 hud.hide()
733 }
734 }
735 }
737 Notifications {
738 id: notifications
740 model: NotificationBackend.Model
741 anchors {
742 top: parent.top
743 right: parent.right
744 bottom: parent.bottom
745 leftMargin: units.gu(1)
746 rightMargin: units.gu(1)
747 topMargin: panel.panelHeight + units.gu(1)
748 }
749 states: [
750 State {
751 name: "narrow"
752 when: overlay.width <= units.gu(60)
753 AnchorChanges { target: notifications; anchors.left: parent.left }
754 },
755 State {
756 name: "wide"
757 when: overlay.width > units.gu(60)
758 AnchorChanges { target: notifications; anchors.left: undefined }
759 PropertyChanges { target: notifications; width: units.gu(38) }
760 }
761 ]
762 }
763 }
765 DemoOverlay {
766 id: finalEdgeDemo
768 edge: "none"
769 title: i18n.tr("Well done")
770 text: i18n.tr("You have now mastered the edge gestures and can start using the phone")
771 skipText: i18n.tr("Finish")
772 anchors.fill: overlay
773 visible: false
774 available: shell.showEdgeDemo
775 onSkip: shell.hideEdgeDemo()
777 Connections {
778 target: leftEdgeDemo
779 onActiveChanged: {
780 if (!leftEdgeDemo.active) {
781 finalEdgeDemo.show();
782 launcher.hide();
783 }
784 }
785 }
786 }
788 focus: true
790 InputFilterArea {
791 anchors {
792 top: parent.top
793 bottom: parent.bottom
794 left: parent.left
795 }
796 width: shell.edgeSize
797 blockInput: true
798 }
800 InputFilterArea {
801 anchors {
802 top: parent.top
803 bottom: parent.bottom
804 right: parent.right
805 }
806 width: shell.edgeSize
807 blockInput: true
808 }
810 Binding {
811 target: i18n
812 property: "domain"
813 value: "unity8"
814 }
816 //FIXME: This should be handled in the input stack, keyboard shouldnt propagate
817 MouseArea {
818 anchors.bottom: parent.bottom
819 anchors.left: parent.left
820 anchors.right: parent.right
821 height: shell.applicationManager ? shell.applicationManager.keyboardHeight : 0
823 enabled: shell.applicationManager && shell.applicationManager.keyboardVisible
824 }
826 Label {
827 anchors.centerIn: parent
828 visible: applicationManager.fake
829 text: "EARLY ALPHA\nNOT READY FOR USE"
830 color: "lightgrey"
831 opacity: 0.2
832 font.weight: Font.Black
833 horizontalAlignment: Text.AlignHCenter
834 verticalAlignment: Text.AlignVCenter
835 fontSizeMode: Text.Fit
836 rotation: -45
837 scale: Math.min(parent.width, parent.height) / width
838 }