2 * Copyright (C) 2013 Canonical, Ltd.
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.
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.
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/>.
18import AccountsService 0.1
20import Unity.Application 0.1
21import Ubuntu.Components 0.1
22import Ubuntu.Gestures 0.1
23import Ubuntu.Telephony 0.1 as Telephony
24import Unity.Launcher 0.1
26import LightDM 0.1 as LightDM
28import SessionBroadcast 0.1
36import Unity.Notifications 1.0 as NotificationBackend
37import Unity.Session 0.1
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 && dash.available && underlay.visible
54 property bool sideStageEnabled: shell.width >= units.gu(100)
55 readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId
57 function activateApplication(appId) {
58 if (ApplicationManager.findApplication(appId)) {
59 ApplicationManager.requestFocusApplication(appId);
61 var execFlags = shell.sideStageEnabled ? ApplicationManager.NoFlag : ApplicationManager.ForceMainStage;
62 ApplicationManager.startApplication(appId, execFlags);
69 property: "applicationManager"
70 value: ApplicationManager
73 Component.onCompleted: {
74 Theme.name = "Ubuntu.Components.Themes.SuruGradient"
78 id: backgroundSettings
79 schema.id: "org.gnome.desktop.background"
81 property url gSettingsPicture: backgroundSettings.pictureUri != undefined && backgroundSettings.pictureUri.length > 0 ? backgroundSettings.pictureUri : shell.defaultBackground
82 onGSettingsPictureChanged: {
83 shell.background = gSettingsPicture
91 // Handle but do not filter out volume keys
92 Keys.onVolumeUpPressed: { volumeControl.volumeUp(); event.accepted = false; }
93 Keys.onVolumeDownPressed: { volumeControl.volumeDown(); event.accepted = false; }
96 if (event.key == Qt.Key_PowerOff || event.key == Qt.Key_PowerDown) {
97 dialogs.onPowerKeyPressed();
98 event.accepted = true;
100 event.accepted = false;
105 if (event.key == Qt.Key_PowerOff || event.key == Qt.Key_PowerDown) {
106 dialogs.onPowerKeyReleased();
107 event.accepted = true;
109 event.accepted = false;
116 objectName: "underlay"
119 // Whether the underlay is fully covered by opaque UI elements.
120 property bool fullyCovered: (panel.indicators.fullyOpened && shell.width <= panel.indicatorsMenuWidth)
121 || stages.fullyShown || greeterWrapper.fullyShown
122 visible: !fullyCovered
126 source: shell.width > shell.height ? "Dash/graphics/paper_landscape.png" : "Dash/graphics/paper_portrait.png"
127 fillMode: Image.PreserveAspectCrop
128 horizontalAlignment: Image.AlignRight
129 verticalAlignment: Image.AlignTop
136 available: !LightDM.Greeter.active
137 hides: [stages, launcher, panel.indicators]
138 shown: disappearingAnimationProgress !== 1.0 && greeterWrapper.showProgress !== 1.0 &&
139 !(panel.indicators.fullyOpened && !sideStageEnabled)
140 enabled: disappearingAnimationProgress === 0.0 && greeterWrapper.showProgress === 0.0 && edgeDemo.dashEnabled
144 topMargin: panel.panelHeight
147 contentScale: 1.0 - 0.2 * disappearingAnimationProgress
148 opacity: 1.0 - disappearingAnimationProgress
149 property real disappearingAnimationProgress: stages.showProgress
151 // FIXME: only necessary because stages.showProgress is not animated
152 Behavior on disappearingAnimationProgress { SmoothedAnimation { velocity: 5 }}
158 direction: Direction.Leftwards
160 anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
161 width: shell.edgeSize
163 property real progress: stages.width
166 if (status == DirectionalDragArea.Recognized) {
167 if (ApplicationManager.empty) {
168 progress = Math.max(stages.width - stagesDragArea.width + touchX, stages.width * .3);
170 progress = stages.width - stagesDragArea.width + touchX;
177 if (!ApplicationManager.empty && progress < stages.width - units.gu(10)) {
180 stagesDragArea.progress = Qt.binding(function () { return stages.width; });
189 height: parent.height
191 visible: !fullyHidden && !ApplicationManager.empty
195 if (locked || greeter.fakeActiveForApp !== "") {
198 return launcher.progress;
200 return stagesDragArea.progress
203 Behavior on x { SmoothedAnimation { velocity: 600; duration: UbuntuAnimation.FastDuration } }
205 property bool shown: false
208 if (ApplicationManager.count > 0) {
209 ApplicationManager.focusApplication(ApplicationManager.get(0).appId);
212 if (ApplicationManager.focusedApplicationId) {
213 ApplicationManager.updateScreenshot(ApplicationManager.focusedApplicationId);
214 ApplicationManager.unfocusCurrentApplication();
219 // Avoid a silent "divide by zero -> NaN" situation during init as shell.width will be
220 // zero. That breaks the property binding and the function won't be reevaluated once
221 // shell.width is set, with the NaN result staying there for good.
222 property real showProgress: shell.width ? MathUtils.clamp(1 - x / shell.width, 0, 1) : 0
224 property bool fullyShown: x == 0
225 property bool fullyHidden: x == width
227 property bool locked: applicationsDisplayLoader.item ? applicationsDisplayLoader.item.locked : false
229 // It might technically not be fullyShown but visually it just looks so.
230 property bool roughlyFullyShown: x >= 0 && x <= units.gu(1)
241 target: ApplicationManager
243 if (greeter.fakeActiveForApp !== "" && greeter.fakeActiveForApp !== appId) {
250 onFocusedApplicationIdChanged: {
251 if (greeter.fakeActiveForApp !== "" && greeter.fakeActiveForApp !== ApplicationManager.focusedApplicationId) {
254 panel.indicators.hide();
257 onApplicationAdded: {
267 if (ApplicationManager.empty) {
274 id: applicationsDisplayLoader
277 source: shell.sideStageEnabled ? "Stages/TabletStage.qml" : "Stages/PhoneStage.qml"
280 target: applicationsDisplayLoader.item
281 property: "objectName"
285 target: applicationsDisplayLoader.item
286 property: "dragAreaWidth"
287 value: shell.edgeSize
290 target: applicationsDisplayLoader.item
291 property: "maximizedAppTopMargin"
292 // Not just using panel.panelHeight as that changes depending on the focused app.
293 value: panel.indicators.panelHeight
296 target: applicationsDisplayLoader.item
297 property: "interactive"
298 value: stages.roughlyFullyShown && !greeter.shown && !lockscreen.shown
299 && panel.indicators.fullyClosed
302 target: applicationsDisplayLoader.item
303 property: "spreadEnabled"
304 value: greeter.fakeActiveForApp === "" // to support emergency dialer hack
311 objectName: "inputMethod"
312 anchors { fill: parent; topMargin: panel.panelHeight }
313 z: notifications.useModal || panel.indicators.shown ? overlay.z + 1 : overlay.z - 1
317 target: SurfaceManager
319 if (surface.type == MirSurfaceItem.InputMethod) {
320 inputMethod.surface = surface;
324 onSurfaceDestroyed: {
325 if (inputMethod.surface == surface) {
326 inputMethod.surface = null;
327 surface.parent = null;
329 if (!surface.parent) {
330 // there's no one displaying it. delete it right away
338 objectName: "lockscreen"
340 readonly property int backgroundTopMargin: -panel.panelHeight
342 hides: [launcher, panel.indicators]
345 showAnimation: StandardAnimation { property: "opacity"; to: 1 }
346 hideAnimation: StandardAnimation { property: "opacity"; to: 0 }
350 height: parent.height - panel.panelHeight
351 background: shell.background
352 alphaNumeric: AccountsService.passwordDisplayHint === AccountsService.Keyboard
356 onEntered: LightDM.Greeter.respond(passphrase);
357 onCancel: greeter.show()
359 greeter.fakeActiveForApp = "dialer-app"
360 shell.activateApplication("dialer-app")
364 onShownChanged: if (shown) greeter.fakeActiveForApp = ""
366 Component.onCompleted: {
367 if (greeter.narrowMode) {
368 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole))
374 target: LightDM.Greeter
376 onShowGreeter: greeter.show()
379 if (greeter.narrowMode) {
380 lockscreen.placeholderText = i18n.tr("Please enter %1").arg(text.toLowerCase());
385 onPromptlessChanged: {
386 if (LightDM.Greeter.promptless) {
394 onAuthenticationComplete: {
395 if (LightDM.Greeter.promptless) {
398 if (LightDM.Greeter.authenticated) {
402 lockscreen.clear(true);
403 if (greeter.narrowMode) {
404 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole))
411 target: LightDM.Greeter
413 value: greeter.shown || lockscreen.shown || greeter.fakeActiveForApp != ""
419 opacity: greeterWrapper.showProgress * 0.8
423 // Just a tiny wrapper to adjust greeter's x without messing with its own dragging
428 height: parent.height - panel.panelHeight
431 enabled: !launcher.dashSwipe
435 property bool fullyShown: showProgress === 1.0
436 readonly property real showProgress: MathUtils.clamp((1 - x/width) + greeter.showProgress - 1, 0, 1)
437 onShowProgressChanged: if (LightDM.Greeter.promptless && showProgress === 0) greeter.login()
441 objectName: "greeter"
443 signal sessionStarted() // helpful for tests
445 property string fakeActiveForApp: ""
448 hides: [launcher, panel.indicators]
451 defaultBackground: shell.background
454 height: parent.height
456 dragHandleWidth: shell.edgeSize
460 if (LightDM.Greeter.startSessionSync()) {
471 if (greeter.narrowMode) {
472 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole));
474 if (!LightDM.Greeter.promptless) {
478 greeter.fakeActiveForApp = "";
479 greeter.forceActiveFocus();
483 onUnlocked: greeter.hide()
485 // Update launcher items for new user
486 var user = LightDM.Users.data(uid, LightDM.UserRoles.NameRole);
487 AccountsService.user = user;
488 LauncherModel.setUser(user);
491 onTease: launcher.tease()
494 target: ApplicationManager
495 property: "suspended"
496 value: greeter.shown && greeterWrapper.showProgress == 1
501 function showGreeterIfScreenIsOff() {
502 if (Powerd.status === Powerd.Off && !callManager.hasCalls && !edgeDemo.running) {
510 onHasCallsChanged: showGreeterIfScreenIsOff()
518 showGreeterIfScreenIsOff()
520 // No reason to chew demo CPU when user isn't watching
521 if (Powerd.status === Powerd.Off) {
522 edgeDemo.paused = true;
523 } else if (Powerd.status === Powerd.On) {
524 edgeDemo.paused = false;
529 function showHome() {
530 if (edgeDemo.running) {
534 if (LightDM.Greeter.active) {
535 if (!LightDM.Greeter.promptless) {
541 var animate = !LightDM.Greeter.active && !stages.shown
542 dash.setCurrentScope("clickscope", animate, false)
546 function showDash() {
547 if (LightDM.Greeter.active && !LightDM.Greeter.promptless) {
551 if (!stages.locked) {
555 launcher.switchToNextState("visible");
573 anchors.fill: parent //because this draws indicator menus
576 available: edgeDemo.panelEnabled && greeter.fakeActiveForApp === ""
577 contentEnabled: edgeDemo.panelContentEnabled
578 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
579 panelHeight: units.gu(3)
582 property bool topmostApplicationIsFullscreen:
583 ApplicationManager.focusedApplicationId &&
584 ApplicationManager.findApplication(ApplicationManager.focusedApplicationId).fullscreen
586 fullscreenMode: (stages.roughlyFullyShown && topmostApplicationIsFullscreen
587 && !LightDM.Greeter.active) || greeter.fakeActiveForApp !== ""
592 objectName: "launcher"
594 readonly property bool dashSwipe: progress > 0
596 anchors.top: parent.top
597 anchors.bottom: parent.bottom
599 dragAreaWidth: shell.edgeSize
600 available: edgeDemo.launcherEnabled && greeter.fakeActiveForApp === ""
602 onShowDashHome: showHome()
604 onDashSwipeChanged: if (dashSwipe && stages.shown) dash.setCurrentScope("clickscope", false, true)
605 onLauncherApplicationSelected: {
606 if (greeter.fakeActiveForApp !== "") {
609 if (!edgeDemo.running)
610 shell.activateApplication(appId)
614 panel.indicators.hide()
620 id: modalNotificationBackground
622 visible: notifications.useModal && !greeter.shown && (notifications.state == "narrow")
635 model: NotificationBackend.Model
640 height: parent.height - panel.panelHeight
645 when: overlay.width <= units.gu(60)
646 AnchorChanges { target: notifications; anchors.left: parent.left }
650 when: overlay.width > units.gu(60)
651 AnchorChanges { target: notifications; anchors.left: undefined }
652 PropertyChanges { target: notifications; width: units.gu(38) }
669 shutdownFadeOutRectangle.enabled = true;
670 shutdownFadeOutRectangle.visible = true;
671 shutdownFadeOut.start();
676 id: alphaDisclaimerLabel
677 anchors.centerIn: parent
678 visible: ApplicationManager.fake ? ApplicationManager.fake : false
680 text: "EARLY ALPHA\nNOT READY FOR USE"
683 font.weight: Font.Black
684 horizontalAlignment: Text.AlignHCenter
685 verticalAlignment: Text.AlignVCenter
686 fontSizeMode: Text.Fit
688 scale: Math.min(parent.width, parent.height) / width
693 z: alphaDisclaimerLabel.z + 10
697 indicators: panel.indicators
702 target: SessionBroadcast
703 onShowHome: showHome()
707 id: shutdownFadeOutRectangle
714 NumberAnimation on opacity {
719 if (shutdownFadeOutRectangle.enabled && shutdownFadeOutRectangle.visible) {
720 DBusUnitySessionService.Shutdown();
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list