on 43df35a help sign in
unity8/Shell.qml
811 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 Ubuntu.Application 0.1
19import Ubuntu.Components 0.1
20import Ubuntu.Gestures 0.1
21import LightDM 0.1 as LightDM
22import AccountsService 0.1
23import Powerd 0.1
24import "Dash"
25import "Greeter"
26import "Launcher"
27import "Panel"
28import "Hud"
29import "Components"
30import "Components/Math.js" as MathLocal
31import "Bottombar"
32import "SideStage"
33import "Notifications"
34import Unity.Notifications 1.0 as NotificationBackend
36FocusScope {
37 id: shell
39 // this is only here to select the width / height of the window if not running fullscreen
40 property bool tablet: false
41 width: tablet ? units.gu(160) : applicationArguments.hasGeometry() ? applicationArguments.width() : units.gu(40)
42 height: tablet ? units.gu(100) : applicationArguments.hasGeometry() ? applicationArguments.height() : units.gu(71)
44 property real edgeSize: units.gu(2)
45 property url default_background: shell.width >= units.gu(60) ? "graphics/tablet_background.jpg" : "graphics/phone_background.jpg"
46 property url background: default_background
47 readonly property real panelHeight: panel.panelHeight
49 property bool dashShown: dash.shown
50 property bool stageScreenshotsReady: {
51 if (sideStage.shown) {
52 if (mainStage.applications.count > 0) {
53 return mainStage.usingScreenshots && sideStage.usingScreenshots;
54 } else {
55 return sideStage.usingScreenshots;
56 }
57 } else {
58 return mainStage.usingScreenshots;
59 }
60 }
62 property bool showEdgeDemo: true
63 property bool showEdgeDemoInGreeter: showEdgeDemo //AccountsService.getUserProperty("lightdm", "demo-edges")
65 function hideEdgeDemo() {
66 var user = LightDM.Users.data(greeter.currentIndex, LightDM.UserRoles.NameRole);
67 AccountsService.setUserProperty(user, "demo-edges", false);
68 shell.showEdgeDemo = false;
69 }
70 function hideEdgeDemoInGreeter() {
71 //AccountsService.setUserProperty("lightdm", "demo-edges", false);
72 shell.showEdgeDemoInGreeter = false;
73 }
75 property ListModel searchHistory: SearchHistoryModel {}
77 property var applicationManager: ApplicationManagerWrapper {}
79 Component.onCompleted: {
80 Theme.name = "Ubuntu.Components.Themes.SuruGradient"
82 applicationManager.sideStageEnabled = Qt.binding(function() { return sideStage.enabled })
84 // FIXME: if application focused before shell starts, shell draws on top of it only.
85 // We should detect already running applications on shell start and bring them to the front.
86 applicationManager.unfocusCurrentApplication();
87 }
89 readonly property bool fullscreenMode: {
90 if (greeter.shown || lockscreen.shown) {
91 return false;
92 } else if (mainStage.usingScreenshots) { // Window Manager animating so want to re-evaluate fullscreen mode
93 return mainStage.switchingFromFullscreenToFullscreen;
94 } else if (applicationManager.mainStageFocusedApplication) {
95 return applicationManager.mainStageFocusedApplication.fullscreen;
96 } else {
97 return false;
98 }
99 }
101 Connections {
102 target: applicationManager
103 ignoreUnknownSignals: true
104 onFocusRequested: {
105 // TODO: this should be protected to only unlock for certain applications / certain usecases
106 // potentially only in connection with a notification
107 greeter.hide();
108 shell.activateApplication(desktopFile);
109 }
110 }
112 function activateApplication(desktopFile, argument) {
113 if (applicationManager) {
114 // For newly started applications, as it takes them time to draw their first frame
115 // we add a delay before we hide the animation screenshots to compensate.
116 var addDelay = !applicationManager.getApplicationFromDesktopFile(desktopFile);
118 var application;
119 application = applicationManager.activateApplication(desktopFile, argument);
120 if (application == null) {
121 return;
122 }
123 if (application.stage == ApplicationInfo.MainStage || !sideStage.enabled) {
124 mainStage.activateApplication(desktopFile, addDelay);
125 } else {
126 sideStage.activateApplication(desktopFile, addDelay);
127 }
128 stages.show();
129 }
130 }
132 VolumeControl {
133 id: volumeControl
134 }
136 Keys.onVolumeUpPressed: volumeControl.volumeUp()
137 Keys.onVolumeDownPressed: volumeControl.volumeDown()
139 Item {
140 id: underlay
141 objectName: "underlay"
142 anchors.fill: parent
144 // Whether the underlay is fully covered by opaque UI elements.
145 property bool fullyCovered: panel.indicators.fullyOpened && shell.width <= panel.indicatorsMenuWidth
147 // Whether the user should see the topmost application surface (if there's one at all).
148 property bool applicationSurfaceShouldBeSeen:
149 (mainStage.applications && mainStage.applications.count > 0)
150 && (!stages.fullyHidden && !mainStage.usingScreenshots)
152 // NB! Application surfaces are stacked behing the shell one. So they can only be seen by the user
153 // through the translucent parts of the shell surface.
154 visible: !fullyCovered && !applicationSurfaceShouldBeSeen
156 Image {
157 id: backgroundImage
158 source: shell.background
159 sourceSize.width: parent.width
160 sourceSize.height: parent.height
161 anchors.fill: parent
162 }
164 Rectangle {
165 anchors.fill: parent
166 color: "black"
167 opacity: dash.disappearingAnimationProgress
168 }
170 Dash {
171 id: dash
172 objectName: "dash"
174 available: !greeter.shown && !lockscreen.shown
175 hides: [stages, launcher, panel.indicators]
176 shown: disappearingAnimationProgress !== 1.0
177 enabled: disappearingAnimationProgress === 0.0 && !leftEdgeDemo.active && !topEdgeDemo.active && !finalEdgeDemo.active
178 // FIXME: unfocus all applications when going back to the dash
179 onEnabledChanged: {
180 if (enabled) {
181 shell.applicationManager.unfocusCurrentApplication()
182 }
183 }
185 anchors {
186 fill: parent
187 topMargin: panel.panelHeight
188 }
190 contentScale: 1.0 - 0.2 * disappearingAnimationProgress
191 opacity: 1.0 - disappearingAnimationProgress
192 property real disappearingAnimationProgress: {
193 if (greeter.shown) {
194 return greeter.showProgress;
195 } else {
196 return stagesOuterContainer.showProgress;
197 }
198 }
200 // FIXME: only necessary because stagesOuterContainer.showProgress and
201 // greeterRevealer.animatedProgress are not animated
202 Behavior on disappearingAnimationProgress { SmoothedAnimation { velocity: 5 }}
203 }
205 DemoOverlay {
206 id: topEdgeDemo
208 edge: "top"
209 title: i18n.tr("Top edge")
210 text: i18n.tr("Try swiping from the top edge to access the indicators")
211 anchors.fill: dash
212 visible: false
213 enabled: shell.showEdgeDemo
214 onSkip: shell.hideEdgeDemo()
216 Connections {
217 target: greeter
218 onShownChanged: if (!greeter.shown) topEdgeDemo.visible = true
219 }
221 Connections {
222 target: panel.indicators
223 onFullyOpenedChanged: if (panel.indicators.fullyOpened) topEdgeDemo.enabled = false
224 }
225 }
227 DemoOverlay {
228 id: leftEdgeDemo
230 edge: "left"
231 title: i18n.tr("Left edge")
232 text: i18n.tr("Swipe from the left to reveal the launcher for quick access to apps")
233 anchors.fill: dash
234 visible: false
235 enabled: shell.showEdgeDemo
236 onSkip: shell.hideEdgeDemo()
238 Connections {
239 target: bottomEdgeDemo
240 onActiveChanged: if (!bottomEdgeDemo.active) leftEdgeDemo.visible = true
241 }
243 Connections {
244 target: launcher
245 onProgressChanged: if (launcher.progress >= 1.0) leftEdgeDemo.enabled = false
246 }
247 }
248 }
251 Item {
252 id: stagesOuterContainer
254 width: parent.width
255 height: parent.height
256 x: launcher.progress
257 Behavior on x {SmoothedAnimation{velocity: 600}}
259 property real showProgress:
260 MathLocal.clamp(1 - (x + stages.x) / shell.width, 0, 1)
262 Showable {
263 id: stages
264 objectName: "stages"
266 x: width
268 property bool fullyShown: shown && x == 0 && parent.x == 0
269 property bool fullyHidden: !shown && x == width
270 available: !greeter.shown
271 hides: [launcher, panel.indicators]
272 shown: false
273 opacity: 1.0
274 showAnimation: StandardAnimation { property: "x"; duration: 350; to: 0; easing.type: Easing.OutCubic }
275 hideAnimation: StandardAnimation { property: "x"; duration: 350; to: width; easing.type: Easing.OutCubic }
277 width: parent.width
278 height: parent.height
280 // close the stages when no focused application remains
281 Connections {
282 target: shell.applicationManager
283 onMainStageFocusedApplicationChanged: stages.closeIfNoApplications()
284 onSideStageFocusedApplicationChanged: stages.closeIfNoApplications()
285 ignoreUnknownSignals: true
286 }
288 function closeIfNoApplications() {
289 if (!shell.applicationManager.mainStageFocusedApplication
290 && !shell.applicationManager.sideStageFocusedApplication
291 && shell.applicationManager.mainStageApplications.count == 0
292 && shell.applicationManager.sideStageApplications.count == 0) {
293 stages.hide();
294 }
295 }
297 // show the stages when an application gets the focus
298 Connections {
299 target: shell.applicationManager
300 onMainStageFocusedApplicationChanged: {
301 if (shell.applicationManager.mainStageFocusedApplication) {
302 mainStage.show();
303 stages.show();
304 }
305 }
306 onSideStageFocusedApplicationChanged: {
307 if (shell.applicationManager.sideStageFocusedApplication) {
308 sideStage.show();
309 stages.show();
310 }
311 }
312 ignoreUnknownSignals: true
313 }
316 Stage {
317 id: mainStage
319 anchors.fill: parent
320 fullyShown: stages.fullyShown
321 fullyHidden: stages.fullyHidden
322 shouldUseScreenshots: !fullyShown
323 rightEdgeEnabled: !sideStage.enabled
325 applicationManager: shell.applicationManager
326 rightEdgeDraggingAreaWidth: shell.edgeSize
327 normalApplicationY: shell.panelHeight
329 shown: true
330 function show() {
331 stages.show();
332 }
333 function hide() {
334 }
336 // FIXME: workaround the fact that focusing a main stage application
337 // raises its surface on top of all other surfaces including the ones
338 // that belong to side stage applications.
339 onFocusedApplicationChanged: {
340 if (focusedApplication && sideStage.focusedApplication && sideStage.fullyShown) {
341 shell.applicationManager.focusApplication(sideStage.focusedApplication);
342 }
343 }
344 }
346 SideStage {
347 id: sideStage
349 applicationManager: shell.applicationManager
350 rightEdgeDraggingAreaWidth: shell.edgeSize
351 normalApplicationY: shell.panelHeight
353 onShownChanged: {
354 if (!shown && mainStage.applications.count == 0) {
355 stages.hide();
356 }
357 }
358 // FIXME: when hiding the side stage, refocus the main stage
359 // application so that it goes in front of the side stage
360 // application and hides it
361 onFullyShownChanged: {
362 if (!fullyShown && stages.fullyShown && sideStage.focusedApplication != null) {
363 shell.applicationManager.focusApplication(mainStage.focusedApplication);
364 }
365 }
367 enabled: shell.width >= units.gu(60)
368 visible: enabled
369 fullyShown: stages.fullyShown && shown
370 && sideStage[sideStageRevealer.boundProperty] == sideStageRevealer.openedValue
371 shouldUseScreenshots: !fullyShown || mainStage.usingScreenshots || sideStageRevealer.pressed
373 available: !greeter.shown && !lockscreen.shown && enabled
374 hides: [launcher, panel.indicators]
375 shown: false
376 showAnimation: StandardAnimation { property: "x"; duration: 350; to: sideStageRevealer.openedValue; easing.type: Easing.OutQuint }
377 hideAnimation: StandardAnimation { property: "x"; duration: 350; to: sideStageRevealer.closedValue; easing.type: Easing.OutQuint }
379 width: units.gu(40)
380 height: stages.height
381 handleExpanded: sideStageRevealer.pressed
382 }
384 Revealer {
385 id: sideStageRevealer
387 enabled: mainStage.applications.count > 0 && sideStage.applications.count > 0
388 && sideStage.available
389 direction: Qt.RightToLeft
390 openedValue: parent.width - sideStage.width
391 hintDisplacement: units.gu(3)
392 /* The size of the sidestage handle needs to be bigger than the
393 typical size used for edge detection otherwise it is really
394 hard to grab.
395 */
396 handleSize: sideStage.shown ? units.gu(4) : shell.edgeSize
397 closedValue: parent.width + sideStage.handleSizeCollapsed
398 target: sideStage
399 x: parent.width - width
400 width: sideStage.width + handleSize * 0.7
401 height: sideStage.height
402 orientation: Qt.Horizontal
403 }
405 DragHandle {
406 id: stagesDragHandle
408 anchors.top: parent.top
409 anchors.bottom: parent.bottom
410 anchors.right: parent.left
412 width: shell.edgeSize
413 direction: Direction.Leftwards
414 property bool haveApps: mainStage.applications.count > 0 || sideStage.applications.count > 0
416 maxTotalDragDistance: haveApps ? parent.width : parent.width * 0.7
417 // Make autocompletion impossible when !haveApps
418 edgeDragEvaluator.minDragDistance: haveApps ? maxTotalDragDistance * 0.1 : Number.MAX_VALUE
419 }
420 }
421 }
423 Lockscreen {
424 id: lockscreen
425 hides: [launcher, panel.indicators, hud]
426 shown: false
427 enabled: true
428 showAnimation: StandardAnimation { property: "opacity"; to: 1 }
429 hideAnimation: StandardAnimation { property: "opacity"; to: 0 }
430 y: panel.panelHeight
431 x: required ? 0 : - width
432 width: parent.width
433 height: parent.height - panel.panelHeight
434 background: shell.background
436 onUnlocked: lockscreen.hide()
437 onCancel: greeter.show()
439 Component.onCompleted: {
440 if (LightDM.Users.count == 1) {
441 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole))
442 greeter.selected(0)
443 }
444 }
445 }
447 Connections {
448 target: LightDM.Greeter
450 onShowPrompt: {
451 if (LightDM.Users.count == 1) {
452 // TODO: There's no better way for now to determine if its a PIN or a passphrase.
453 if (text == "PIN") {
454 lockscreen.alphaNumeric = false
455 } else {
456 lockscreen.alphaNumeric = true
457 }
458 lockscreen.placeholderText = i18n.tr("Please enter %1").arg(text);
459 lockscreen.show();
460 }
461 }
462 }
464 Greeter {
465 id: greeter
467 available: true
468 hides: [launcher, panel.indicators, hud]
469 shown: true
471 y: panel.panelHeight
472 width: parent.width
473 height: parent.height - panel.panelHeight
475 dragHandleWidth: shell.edgeSize
477 onShownChanged: {
478 if (shown) {
479 lockscreen.reset();
480 // If there is only one user, we start authenticating with that one here.
481 // If there are more users, the Greeter will handle that
482 if (LightDM.Users.count == 1) {
483 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole));
484 greeter.selected(0);
485 }
486 greeter.forceActiveFocus();
487 }
488 }
490 onUnlocked: greeter.hide()
491 onSelected: {
492 // Update background
493 var bgPath = greeter.model.data(uid, LightDM.UserRoles.BackgroundPathRole)
494 shell.background = bgPath ? bgPath : default_background
495 // Update edge demo hint
496 var user = LightDM.Users.data(uid, LightDM.UserRoles.NameRole)
497 shell.showEdgeDemo = true //AccountsService.getUserProperty(user, "demo-edges")
498 }
500 onLeftTeaserPressedChanged: {
501 if (leftTeaserPressed) {
502 launcher.tease();
503 }
504 }
506 DemoOverlay {
507 id: rightEdgeDemo
509 edge: "right"
510 title: i18n.tr("Right edge")
511 text: i18n.tr("Try swiping from the right edge to unlock the phone")
512 skipText: i18n.tr("Finish")
513 anchors.fill: parent
514 visible: shell.showEdgeDemoInGreeter
515 onSkip: {
516 shell.hideEdgeDemoInGreeter()
517 shell.hideEdgeDemo()
518 }
520 Connections {
521 target: greeter
523 function hide() {
524 if (rightEdgeDemo.active) {
525 rightEdgeDemo.enabled = false
526 shell.hideEdgeDemoInGreeter()
527 }
528 }
530 onUnlocked: hide()
531 onShownChanged: if (!greeter.shown) hide()
532 }
533 }
534 }
536 InputFilterArea {
537 anchors.fill: parent
538 blockInput: greeter.shown || lockscreen.shown
539 }
541 Connections {
542 id: powerConnection
543 target: Powerd
545 property var previousMainApp: null
546 property var previousSideApp: null
548 function setFocused(focused) {
549 if (!focused) {
550 // FIXME: *FocusedApplication are not updated when unfocused, hence the need to check whether
551 // the stage was actually shown
552 if (mainStage.fullyShown) powerConnection.previousMainApp = applicationManager.mainStageFocusedApplication;
553 if (sideStage.fullyShown) powerConnection.previousSideApp = applicationManager.sideStageFocusedApplication;
554 applicationManager.unfocusCurrentApplication();
555 } else {
556 if (powerConnection.previousMainApp) {
557 applicationManager.focusApplication(powerConnection.previousMainApp);
558 powerConnection.previousMainApp = null;
559 }
560 if (powerConnection.previousSideApp) {
561 applicationManager.focusApplication(powerConnection.previousSideApp);
562 powerConnection.previousSideApp = null;
563 }
564 }
565 }
567 onPowerStateChange: {
568 if (state == 0) { // suspend
569 powerConnection.setFocused(false);
570 greeter.show();
571 } else if (state == 1) { // active
572 powerConnection.setFocused(true);
573 }
574 }
575 }
577 Item {
578 id: overlay
580 anchors.fill: parent
582 Panel {
583 id: panel
584 anchors.fill: parent //because this draws indicator menus
585 indicatorsMenuWidth: parent.width > units.gu(60) ? units.gu(40) : parent.width
586 indicators {
587 hides: [launcher]
588 available: !rightEdgeDemo.active && !leftEdgeDemo.active && !finalEdgeDemo.active
589 }
590 fullscreenMode: shell.fullscreenMode
591 searchVisible: !greeter.shown && !lockscreen.shown
593 InputFilterArea {
594 anchors.fill: parent
595 blockInput: panel.indicators.shown
596 }
598 DemoOverlay {
599 id: bottomEdgeDemo
601 edge: "bottom"
602 title: i18n.tr("Close")
603 text: i18n.tr("Swipe up again to close the settings screen")
604 anchors.fill: panel.indicators
605 visible: false
606 enabled: shell.showEdgeDemo
607 onSkip: shell.hideEdgeDemo()
609 Connections {
610 target: panel.indicators
611 onFullyOpenedChanged: if (panel.indicators.fullyOpened) bottomEdgeDemo.visible = true
612 onPartiallyOpenedChanged: if (!panel.indicators.partiallyOpened && !panel.indicators.fullyOpened) bottomEdgeDemo.enabled = false
613 }
614 }
615 }
617 Hud {
618 id: hud
620 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
621 height: parent.height
623 available: !greeter.shown && !panel.indicators.shown && !lockscreen.shown && !topEdgeDemo.active
624 shown: false
625 showAnimation: StandardAnimation { property: "y"; duration: hud.showableAnimationDuration; to: 0; easing.type: Easing.Linear }
626 hideAnimation: StandardAnimation { property: "y"; duration: hud.showableAnimationDuration; to: hudRevealer.closedValue; easing.type: Easing.Linear }
628 Connections {
629 target: shell.applicationManager
630 onMainStageFocusedApplicationChanged: hud.hide()
631 onSideStageFocusedApplicationChanged: hud.hide()
632 }
634 InputFilterArea {
635 anchors.fill: parent
636 blockInput: hud.shown
637 }
638 }
640 Revealer {
641 id: hudRevealer
643 enabled: hud.shown
644 width: hud.width
645 anchors.left: hud.left
646 height: parent.height
647 target: hud.revealerTarget
648 closedValue: height
649 openedValue: 0
650 direction: Qt.RightToLeft
651 orientation: Qt.Vertical
652 handleSize: hud.handleHeight
653 onCloseClicked: target.hide()
654 }
656 Bottombar {
657 theHud: hud
658 anchors.fill: parent
659 enabled: !panel.indicators.shown
660 applicationIsOnForeground: applicationManager.mainStageFocusedApplication
661 || applicationManager.sideStageFocusedApplication
662 }
664 InputFilterArea {
665 blockInput: launcher.shown
666 anchors {
667 top: parent.top
668 bottom: parent.bottom
669 left: parent.left
670 }
671 width: launcher.width
672 }
674 Launcher {
675 id: launcher
677 anchors.top: parent.top
678 anchors.bottom: parent.bottom
679 width: parent.width
680 dragAreaWidth: shell.edgeSize
681 available: (!greeter.shown || greeter.narrowMode) && !rightEdgeDemo.active && !topEdgeDemo.active && !bottomEdgeDemo.active && !finalEdgeDemo.active
682 onDashItemSelected: {
683 greeter.hide()
684 // Animate if moving between application and dash
685 if (!stages.shown) {
686 dash.setCurrentScope("home.scope", true, false)
687 } else {
688 dash.setCurrentScope("home.scope", false, false)
689 }
690 stages.hide();
691 }
692 onDash: {
693 if (stages.shown) {
694 dash.setCurrentScope("applications.scope", true, false)
695 stages.hide();
696 launcher.hide();
697 }
698 }
699 onLauncherApplicationSelected:{
700 greeter.hide()
701 shell.activateApplication(desktopFile)
702 }
703 onShownChanged: {
704 if (shown) {
705 panel.indicators.hide()
706 hud.hide()
707 }
708 }
709 }
711 Notifications {
712 id: notifications
714 model: NotificationBackend.Model
715 anchors {
716 top: parent.top
717 right: parent.right
718 bottom: parent.bottom
719 leftMargin: units.gu(1)
720 rightMargin: units.gu(1)
721 topMargin: panel.panelHeight + units.gu(1)
722 }
723 states: [
724 State {
725 name: "narrow"
726 when: overlay.width <= units.gu(60)
727 AnchorChanges { target: notifications; anchors.left: parent.left }
728 },
729 State {
730 name: "wide"
731 when: overlay.width > units.gu(60)
732 AnchorChanges { target: notifications; anchors.left: undefined }
733 PropertyChanges { target: notifications; width: units.gu(38) }
734 }
735 ]
736 }
737 }
739 DemoOverlay {
740 id: finalEdgeDemo
742 edge: "none"
743 title: i18n.tr("Well done")
744 text: i18n.tr("You have now mastered the edge gestures and can start using the phone")
745 skipText: i18n.tr("Finish")
746 anchors.fill: overlay
747 visible: false
748 enabled: shell.showEdgeDemo
749 onSkip: {
750 launcher.hide();
751 shell.hideEdgeDemo();
752 }
754 Connections {
755 target: leftEdgeDemo
756 onActiveChanged: if (!leftEdgeDemo.active) finalEdgeDemo.visible = true
757 }
758 }
760 focus: true
762 InputFilterArea {
763 anchors {
764 top: parent.top
765 bottom: parent.bottom
766 left: parent.left
767 }
768 width: shell.edgeSize
769 blockInput: true
770 }
772 InputFilterArea {
773 anchors {
774 top: parent.top
775 bottom: parent.bottom
776 right: parent.right
777 }
778 width: shell.edgeSize
779 blockInput: true
780 }
782 Binding {
783 target: i18n
784 property: "domain"
785 value: "unity8"
786 }
788 //FIXME: This should be handled in the input stack, keyboard shouldnt propagate
789 MouseArea {
790 anchors.bottom: parent.bottom
791 anchors.left: parent.left
792 anchors.right: parent.right
793 height: shell.applicationManager ? shell.applicationManager.keyboardHeight : 0
795 enabled: shell.applicationManager && shell.applicationManager.keyboardVisible
796 }
798 Label {
799 anchors.fill: parent
800 visible: applicationManager.fake
801 text: "EARLY ALPHA\nNOT READY FOR USE"
802 color: "lightgrey"
803 opacity: 0.2
804 font.weight: Font.Black
805 horizontalAlignment: Text.AlignHCenter
806 verticalAlignment: Text.AlignVCenter
807 fontSizeMode: Text.Fit
808 font.pixelSize: height/2
809 rotation: -45
810 }