on 08ee0a6 help sign in
unity8/qml/Shell.qml
855 lines 31 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.Gestures 0.1
23import Unity.Launcher 0.1
24import LightDM 0.1 as LightDM
25import Powerd 0.1
26import SessionBroadcast 0.1
27import "Dash"
28import "Greeter"
29import "Launcher"
30import "Panel"
31import "Hud"
32import "Components"
33import "Bottombar"
34import "SideStage"
35import "Notifications"
36import Unity.Notifications 1.0 as NotificationBackend
38FocusScope {
39 id: shell
40 objectName: "shell"
42 // this is only here to select the width / height of the window if not running fullscreen
43 property bool tablet: false
44 width: tablet ? units.gu(160) : applicationArguments.hasGeometry() ? applicationArguments.width() : units.gu(40)
45 height: tablet ? units.gu(100) : applicationArguments.hasGeometry() ? applicationArguments.height() : units.gu(71)
47 property real edgeSize: units.gu(2)
48 property url defaultBackground: Qt.resolvedUrl(shell.width >= units.gu(60) ? "graphics/tablet_background.jpg" : "graphics/phone_background.jpg")
49 property url background
50 readonly property real panelHeight: panel.panelHeight
52 property bool dashShown: dash.shown
53 property bool stageScreenshotsReady: {
54 if (sideStage.shown) {
55 if (mainStage.applications.count > 0) {
56 return mainStage.usingScreenshots && sideStage.usingScreenshots;
57 } else {
58 return sideStage.usingScreenshots;
59 }
60 } else {
61 return mainStage.usingScreenshots;
62 }
63 }
65 property var applicationManager: ApplicationManagerWrapper {}
67 Binding {
68 target: LauncherModel
69 property: "applicationManager"
70 value: ApplicationManager
71 }
73 Component.onCompleted: {
74 Theme.name = "Ubuntu.Components.Themes.SuruGradient"
76 applicationManager.sideStageEnabled = Qt.binding(function() { return sideStage.enabled })
78 // FIXME: if application focused before shell starts, shell draws on top of it only.
79 // We should detect already running applications on shell start and bring them to the front.
80 applicationManager.unfocusCurrentApplication();
82 applicationManager.setMainStageAppRect(mainStageAppRect);
83 applicationManager.setSideStageAppRect(sideStageAppRect);
84 }
86 // Used for autopilot testing.
87 readonly property string currentFocusedAppId: ApplicationManager.focusedApplicationId
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 function activateApplication(appId, argument) {
102 if (applicationManager) {
103 // For newly started applications, as it takes them time to draw their first frame
104 // we add a delay before we hide the animation screenshots to compensate.
105 var addDelay = !applicationManager.getApplicationFromDesktopFile(appId);
107 var application;
108 application = applicationManager.activateApplication(appId, argument);
109 if (application == null) {
110 return;
111 }
112 if (application.stage == ApplicationInfo.MainStage || !sideStage.enabled) {
113 mainStage.activateApplication(appId, addDelay);
114 } else {
115 sideStage.activateApplication(appId, addDelay);
116 }
117 stages.show();
118 }
119 }
121 Connections {
122 target: applicationManager
123 onFocusRequested: activateApplication(appId)
124 }
126 GSettings {
127 id: backgroundSettings
128 schema.id: "org.gnome.desktop.background"
129 }
130 property url gSettingsPicture: backgroundSettings.pictureUri != undefined && backgroundSettings.pictureUri.length > 0 ? backgroundSettings.pictureUri : shell.defaultBackground
131 onGSettingsPictureChanged: {
132 shell.background = gSettingsPicture
133 }
135 VolumeControl {
136 id: volumeControl
137 }
139 Keys.onVolumeUpPressed: volumeControl.volumeUp()
140 Keys.onVolumeDownPressed: volumeControl.volumeDown()
142 Item {
143 id: underlay
144 objectName: "underlay"
145 anchors.fill: parent
147 // Whether the underlay is fully covered by opaque UI elements.
148 property bool fullyCovered: panel.indicators.fullyOpened && shell.width <= panel.indicatorsMenuWidth
150 readonly property bool mainStageApplicationRunning: mainStage.applications && mainStage.applications.count > 0
151 readonly property bool sideStageApplicationRunning: sideStage.applications && sideStage.applications.count > 0
153 // Whether the user should see the topmost application surface (if there's one at all).
154 readonly property bool mainStageApplicationShown: mainStageApplicationRunning && !stages.fullyHidden
155 && !mainStage.usingScreenshots // but want sideStage animating over app surface
159 // NB! Application surfaces are stacked behing the shell one. So they can only be seen by the user
160 // through the translucent parts of the shell surface.
161 visible: !fullyCovered && !mainStageApplicationShown
163 Item {
164 id: underlayClipper
165 clip: !parent.mainStageApplicationShown && parent.sideStageApplicationRunning && stagesOuterContainer.showProgress > 0
166 width: {
167 if (clip) {
168 var w = parent.width - sideStage.width
169 w += stagesOuterContainer.x + stages.x + (sideStage.x - sideStageRevealer.openedValue)
170 return Math.min(w, parent.width);
171 } else {
172 return parent.width;
173 }
174 }
175 height: parent.height
177 Image {
178 anchors.fill: dash
179 source: shell.width > shell.height ? "Dash/graphics/paper_landscape.png" : "Dash/graphics/paper_portrait.png"
180 fillMode: Image.PreserveAspectCrop
181 horizontalAlignment: Image.AlignRight
182 verticalAlignment: Image.AlignTop
183 }
185 Dash {
186 id: dash
187 objectName: "dash"
189 available: !greeter.shown && !lockscreen.shown
190 hides: [stages, launcher, panel.indicators]
191 shown: disappearingAnimationProgress !== 1.0
192 enabled: disappearingAnimationProgress === 0.0 && edgeDemo.dashEnabled
193 // FIXME: unfocus all applications when going back to the dash
194 onEnabledChanged: {
195 if (enabled) {
196 shell.applicationManager.unfocusCurrentApplication()
197 }
198 }
200 width: underlay.width
201 height: underlay.height - y
202 y: panel.panelHeight
204 contentScale: 1.0 - 0.2 * disappearingAnimationProgress
205 opacity: 1.0 - disappearingAnimationProgress
206 property real disappearingAnimationProgress: {
207 if (greeter.shown) {
208 return greeter.showProgress;
209 } else {
210 if (underlayClipper.clip)
211 return 0;
212 else
213 return stagesOuterContainer.showProgress;
214 }
215 }
217 // FIXME: only necessary because stagesOuterContainer.showProgress and
218 // greeterRevealer.animatedProgress are not animated
219 Behavior on disappearingAnimationProgress { SmoothedAnimation { velocity: 5 }}
220 }
222 Rectangle {
223 width: underlay.width
224 height: underlay.height
225 color: "black"
226 opacity: 0.5 * ((sideStage.x - sideStageRevealer.closedValue) / (sideStageRevealer.openedValue - sideStageRevealer.closedValue))
227 visible: sideStageHideButton.enabled
228 }
230 AbstractButton {
231 id: sideStageHideButton
232 enabled: mainStage.applications.count == 0 && sideStage.shown
233 anchors.fill: parent
234 onClicked: {
235 sideStage.hide();
236 }
237 }
238 }
239 }
241 Item {
242 id: stagesOuterContainer
244 width: parent.width
245 height: parent.height
246 x: mainStage.applications.count > 0 ? launcher.progress : 0
247 Behavior on x {SmoothedAnimation{velocity: 600}}
249 property real showProgress:
250 MathUtils.clamp(1 - (x + stages.x) / shell.width, 0, 1)
252 Showable {
253 id: stages
254 objectName: "stages"
256 x: width
258 function doLauncherHide() {
259 if (mainStage.applications.count > 0) {
260 hide();
261 } else {
262 if (sideStage.shown) {
263 sideStage.hide();
264 }
265 }
266 }
268 property bool fullyShown: shown && x == 0 && parent.x == 0
269 property bool fullyHidden: !shown && x == width
270 available: !greeter.shown
271 hides: [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 }
315 Stage {
316 id: mainStage
318 anchors.fill: parent
319 fullyShown: stages.fullyShown
320 fullyHidden: stages.fullyHidden
321 shouldUseScreenshots: !fullyShown
322 rightEdgeEnabled: !sideStage.enabled
324 applicationManager: shell.applicationManager
325 rightEdgeDraggingAreaWidth: shell.edgeSize
326 normalApplicationY: shell.panelHeight
328 shown: true
329 function show() {
330 stages.show();
331 }
332 function hide() {
333 }
335 // FIXME: workaround the fact that focusing a main stage application
336 // raises its surface on top of all other surfaces including the ones
337 // that belong to side stage applications.
338 onFocusedApplicationChanged: {
339 if (focusedApplication && sideStage.focusedApplication && sideStage.fullyShown) {
340 shell.applicationManager.focusApplication(sideStage.focusedApplication);
341 }
342 }
343 }
345 SideStage {
346 id: sideStage
348 applicationManager: shell.applicationManager
349 rightEdgeDraggingAreaWidth: shell.edgeSize
350 normalApplicationY: shell.panelHeight
352 // FIXME: when hiding the side stage, refocus the main stage
353 // application so that it goes in front of the side stage
354 // application and hides it
355 onFullyShownChanged: {
356 if (!fullyShown && stages.fullyShown && sideStage.focusedApplication != null) {
357 shell.applicationManager.focusApplication(mainStage.focusedApplication);
358 }
359 }
361 enabled: shell.width >= units.gu(60)
362 visible: enabled
363 fullyShown: stages.fullyShown && shown
364 && sideStage[sideStageRevealer.boundProperty] == sideStageRevealer.openedValue
365 shouldUseScreenshots: !fullyShown || mainStage.usingScreenshots || sideStageRevealer.pressed
367 available: !greeter.shown && !lockscreen.shown && enabled
368 hides: [launcher, panel.indicators]
369 shown: false
370 showAnimation: StandardAnimation { property: "x"; duration: 350; to: sideStageRevealer.openedValue; easing.type: Easing.OutQuint }
371 hideAnimation: StandardAnimation { property: "x"; duration: 350; to: sideStageRevealer.closedValue; easing.type: Easing.OutQuint }
373 width: units.gu(40)
374 height: stages.height
375 handleExpanded: sideStageRevealer.pressed
377 Connections {
378 target: sideStage.applications
379 onCountChanged: {
380 if (sideStage.applications.count == 0) {
381 if (sideStage.shown) { // if all SS app closed, hide side stage
382 sideStage.hide();
383 } else {
384 // Sidestage is hidden and there is no main app, make sure the
385 // stages is totally hidden too
386 if (mainStage.applications.count == 0) {
387 stages.hideNow();
388 }
389 }
390 }
391 }
392 }
393 }
395 Revealer {
396 id: sideStageRevealer
398 enabled: sideStage.applications.count > 0
399 && sideStage.available
400 direction: Qt.RightToLeft
401 openedValue: parent.width - sideStage.width
402 hintDisplacement: units.gu(3)
403 /* The size of the sidestage handle needs to be bigger than the
404 typical size used for edge detection otherwise it is really
405 hard to grab.
406 */
407 handleSize: sideStage.shown ? units.gu(4) : shell.edgeSize
408 closedValue: parent.width + sideStage.handleSizeCollapsed
409 target: sideStage
410 x: parent.width - width
411 width: sideStage.width + handleSize * 0.7
412 height: sideStage.height
413 orientation: Qt.Horizontal
414 }
416 // Defines the rectangle occupied by an application on the main or side stage.
417 // Used only to inform the ApplicationManager. Can be removed when the proper
418 // architecture is in place (unity8 as mir compositor).
419 Item {
420 id: mainStageAppRect
421 x: mainStage.x
422 y: mainStage.y + mainStage.normalApplicationY
423 width: mainStage.width
424 height: mainStage.height
425 visible: false; enabled: false
426 }
427 Item {
428 id: sideStageAppRect
429 x: sideStageRevealer.openedValue
430 y: sideStage.y + sideStage.normalApplicationY
431 width: sideStage.width
432 height: sideStage.height
433 visible: false; enabled: false
434 }
436 DragHandle {
437 id: stagesDragHandle
439 anchors.top: parent.top
440 anchors.bottom: parent.bottom
441 anchors.right: parent.left
443 width: shell.edgeSize
444 direction: Direction.Leftwards
445 enabled: greeter.showProgress == 0 && edgeDemo.dashEnabled
446 property bool haveApps: mainStage.applications.count > 0 || sideStage.applications.count > 0
448 maxTotalDragDistance: haveApps ? parent.width : parent.width * 0.7
449 // Make autocompletion impossible when !haveApps
450 edgeDragEvaluator.minDragDistance: haveApps ? maxTotalDragDistance * 0.1 : Number.MAX_VALUE
451 }
452 }
453 }
455 Lockscreen {
456 id: lockscreen
457 objectName: "lockscreen"
459 readonly property int backgroundTopMargin: -panel.panelHeight
461 hides: [launcher, panel.indicators, hud]
462 shown: false
463 enabled: true
464 showAnimation: StandardAnimation { property: "opacity"; to: 1 }
465 hideAnimation: StandardAnimation { property: "opacity"; to: 0 }
466 y: panel.panelHeight
467 x: required ? 0 : - width
468 width: parent.width
469 height: parent.height - panel.panelHeight
470 background: shell.background
471 pinLength: 4
473 onEntered: LightDM.Greeter.respond(passphrase);
474 onCancel: greeter.show()
476 Component.onCompleted: {
477 if (LightDM.Users.count == 1) {
478 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole))
479 }
480 }
481 }
483 Connections {
484 target: LightDM.Greeter
486 onShowPrompt: {
487 if (LightDM.Users.count == 1) {
488 // TODO: There's no better way for now to determine if its a PIN or a passphrase.
489 if (text == "PIN") {
490 lockscreen.alphaNumeric = false
491 } else {
492 lockscreen.alphaNumeric = true
493 }
494 lockscreen.placeholderText = i18n.tr("Please enter %1").arg(text);
495 lockscreen.show();
496 }
497 }
499 onAuthenticationComplete: {
500 if (LightDM.Greeter.promptless) {
501 return;
502 }
503 if (LightDM.Greeter.authenticated) {
504 lockscreen.hide();
505 } else {
506 lockscreen.clear(true);
507 }
508 }
509 }
511 Greeter {
512 id: greeter
513 objectName: "greeter"
515 available: true
516 hides: [launcher, panel.indicators, hud]
517 shown: true
519 defaultBackground: shell.defaultBackground
521 y: panel.panelHeight
522 width: parent.width
523 height: parent.height - panel.panelHeight
525 dragHandleWidth: shell.edgeSize
527 property var previousMainApp: null
528 property var previousSideApp: null
530 function removeApplicationFocus() {
531 greeter.previousMainApp = applicationManager.mainStageFocusedApplication;
532 if (sideStage.fullyShown) { // if side stage hidden, don't focus it on restore
533 greeter.previousSideApp = applicationManager.sideStageFocusedApplication;
534 }
535 applicationManager.unfocusCurrentApplication();
536 }
538 function restoreApplicationFocus() {
539 if (greeter.previousMainApp) {
540 applicationManager.focusApplication(greeter.previousMainApp);
541 greeter.previousMainApp = null;
542 }
543 if (greeter.previousSideApp) {
544 applicationManager.focusApplication(greeter.previousSideApp);
545 greeter.previousSideApp = null;
546 }
547 }
549 onShownChanged: {
550 if (shown) {
551 lockscreen.reset();
552 // If there is only one user, we start authenticating with that one here.
553 // If there are more users, the Greeter will handle that
554 if (LightDM.Users.count == 1) {
555 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole));
556 }
557 greeter.forceActiveFocus();
558 removeApplicationFocus();
559 } else {
560 restoreApplicationFocus();
561 }
562 }
564 onUnlocked: greeter.hide()
565 onSelected: {
566 // Update launcher items for new user
567 var user = LightDM.Users.data(uid, LightDM.UserRoles.NameRole);
568 AccountsService.user = user;
569 LauncherModel.setUser(user);
570 }
572 onLeftTeaserPressedChanged: {
573 if (leftTeaserPressed) {
574 launcher.tease();
575 }
576 }
578 Connections {
579 target: applicationManager
580 ignoreUnknownSignals: true
581 // If any app is focused when greeter is open, it's due to a user action
582 // like a snap decision (say, an incoming call).
583 // TODO: these should be protected to only unlock for certain applications / certain usecases
584 // potentially only in connection with a notification.
585 onMainStageFocusedApplicationChanged: {
586 if (greeter.shown && applicationManager.mainStageFocusedApplication) {
587 greeter.previousMainApp = null // make way for new focused app
588 greeter.previousSideApp = null
589 greeter.hide()
590 }
591 }
592 onSideStageFocusedApplicationChanged: {
593 if (greeter.shown && applicationManager.sideStageFocusedApplication) {
594 greeter.previousMainApp = null // make way for new focused app
595 greeter.previousSideApp = null
596 greeter.hide()
597 }
598 }
599 }
600 }
602 InputFilterArea {
603 width: {
604 if (applicationManager.sideStageFocusedApplication && sideStage.shown)
605 return parent.width - sideStage.width;
606 else
607 return parent.width;
608 }
609 height: parent.height
610 blockInput: !applicationManager.mainStageFocusedApplication || greeter.shown || lockscreen.shown || launcher.shown
611 || panel.indicators.shown || hud.shown
612 }
614 Connections {
615 id: powerConnection
616 target: Powerd
618 onDisplayPowerStateChange: {
619 // We ignore any display-off signals when the proximity sensor
620 // is active. This usually indicates something like a phone call.
621 if (status == Powerd.Off && (flags & Powerd.UseProximity) == 0) {
622 greeter.showNow();
623 }
625 // No reason to chew demo CPU when user isn't watching
626 if (status == Powerd.Off) {
627 edgeDemo.paused = true;
628 } else if (status == Powerd.On) {
629 edgeDemo.paused = false;
630 }
631 }
632 }
634 function showHome() {
635 var animate = !greeter.shown && !stages.shown
636 greeter.hide()
637 dash.setCurrentScope("clickscope", animate, false)
638 stages.hide()
639 }
641 function hideIndicatorMenu(delay) {
642 panel.hideIndicatorMenu(delay);
643 }
645 Item {
646 id: overlay
648 anchors.fill: parent
650 Panel {
651 id: panel
652 anchors.fill: parent //because this draws indicator menus
653 indicatorsMenuWidth: parent.width > units.gu(60) ? units.gu(40) : parent.width
654 indicators {
655 hides: [launcher]
656 available: edgeDemo.panelEnabled
657 contentEnabled: edgeDemo.panelContentEnabled
658 }
659 fullscreenMode: shell.fullscreenMode
660 searchVisible: !greeter.shown && !lockscreen.shown && dash.shown && dash.searchable
662 InputFilterArea {
663 anchors {
664 top: parent.top
665 left: parent.left
666 right: parent.right
667 }
668 height: (panel.fullscreenMode) ? shell.edgeSize : panel.panelHeight
669 blockInput: true
670 }
671 }
673 Hud {
674 id: hud
676 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
677 height: parent.height
679 available: !greeter.shown && !panel.indicators.shown && !lockscreen.shown && edgeDemo.dashEnabled
680 shown: false
681 showAnimation: StandardAnimation { property: "y"; duration: hud.showableAnimationDuration; to: 0; easing.type: Easing.Linear }
682 hideAnimation: StandardAnimation { property: "y"; duration: hud.showableAnimationDuration; to: hudRevealer.closedValue; easing.type: Easing.Linear }
684 Connections {
685 target: shell.applicationManager
686 onMainStageFocusedApplicationChanged: hud.hide()
687 onSideStageFocusedApplicationChanged: hud.hide()
688 }
689 }
691 Revealer {
692 id: hudRevealer
694 enabled: hud.shown
695 width: hud.width
696 anchors.left: hud.left
697 height: parent.height
698 target: hud.revealerTarget
699 closedValue: height
700 openedValue: 0
701 direction: Qt.RightToLeft
702 orientation: Qt.Vertical
703 handleSize: hud.handleHeight
704 onCloseClicked: target.hide()
705 }
707 Bottombar {
708 id: bottombar
709 theHud: hud
710 anchors.fill: parent
711 enabled: hud.available
712 applicationIsOnForeground: (stages.shown && mainStage.applications.count > 0) || (stages.shown && sideStage.shown)
713 }
715 InputFilterArea {
716 blockInput: launcher.shown
717 anchors {
718 top: parent.top
719 bottom: parent.bottom
720 left: parent.left
721 }
722 width: launcher.width
723 }
725 Launcher {
726 id: launcher
728 readonly property bool dashSwipe: progress > 0
730 anchors.top: parent.top
731 anchors.bottom: parent.bottom
732 width: parent.width
733 dragAreaWidth: shell.edgeSize
734 available: !greeter.locked && edgeDemo.launcherEnabled
736 onShowDashHome: {
737 if (edgeDemo.running)
738 return;
740 showHome()
741 }
742 onDash: {
743 if (stages.shown) {
744 stages.doLauncherHide();
745 launcher.hide();
746 }
747 }
748 onDashSwipeChanged: if (dashSwipe && stages.shown) dash.setCurrentScope("clickscope", false, true)
749 onLauncherApplicationSelected:{
750 if (edgeDemo.running)
751 return;
753 greeter.hide()
754 shell.activateApplication(appId)
755 }
756 onShownChanged: {
757 if (shown) {
758 panel.indicators.hide()
759 hud.hide()
760 bottombar.hide()
761 }
762 }
763 }
765 Notifications {
766 id: notifications
768 model: NotificationBackend.Model
769 margin: units.gu(1)
771 anchors {
772 top: parent.top
773 right: parent.right
774 bottom: parent.bottom
775 topMargin: panel.panelHeight
776 }
777 states: [
778 State {
779 name: "narrow"
780 when: overlay.width <= units.gu(60)
781 AnchorChanges { target: notifications; anchors.left: parent.left }
782 },
783 State {
784 name: "wide"
785 when: overlay.width > units.gu(60)
786 AnchorChanges { target: notifications; anchors.left: undefined }
787 PropertyChanges { target: notifications; width: units.gu(38) }
788 }
789 ]
791 InputFilterArea {
792 anchors { left: parent.left; right: parent.right }
793 height: parent.contentHeight
794 blockInput: height > 0
795 }
796 }
797 }
799 focus: true
800 onFocusChanged: if (!focus) forceActiveFocus();
802 InputFilterArea {
803 anchors {
804 top: parent.top
805 bottom: parent.bottom
806 left: parent.left
807 }
808 width: shell.edgeSize
809 blockInput: true
810 }
812 InputFilterArea {
813 anchors {
814 top: parent.top
815 bottom: parent.bottom
816 right: parent.right
817 }
818 width: shell.edgeSize
819 blockInput: true
820 }
822 Binding {
823 target: i18n
824 property: "domain"
825 value: "unity8"
826 }
828 Label {
829 anchors.centerIn: parent
830 visible: applicationManager.fake
831 text: "EARLY ALPHA\nNOT READY FOR USE"
832 color: "lightgrey"
833 opacity: 0.2
834 font.weight: Font.Black
835 horizontalAlignment: Text.AlignHCenter
836 verticalAlignment: Text.AlignVCenter
837 fontSizeMode: Text.Fit
838 rotation: -45
839 scale: Math.min(parent.width, parent.height) / width
840 }
842 EdgeDemo {
843 id: edgeDemo
844 greeter: greeter
845 launcher: launcher
846 dash: dash
847 indicators: panel.indicators
848 underlay: underlay
849 }
851 Connections {
852 target: SessionBroadcast
853 onShowHome: showHome()
854 }