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
355 onEntered: LightDM.Greeter.respond(passphrase);
356 onCancel: greeter.show()
358 greeter.fakeActiveForApp = "dialer-app"
359 shell.activateApplication("dialer-app")
363 onShownChanged: if (shown) greeter.fakeActiveForApp = ""
365 Component.onCompleted: {
366 if (LightDM.Users.count == 1) {
367 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole))
373 target: LightDM.Greeter
375 onShowGreeter: greeter.show()
378 if (LightDM.Users.count == 1) {
379 // TODO: There's no better way for now to determine if its a PIN or a passphrase.
381 lockscreen.alphaNumeric = false
383 lockscreen.alphaNumeric = true
385 lockscreen.placeholderText = i18n.tr("Please enter %1").arg(text);
390 onAuthenticationComplete: {
391 if (LightDM.Greeter.promptless) {
394 if (LightDM.Greeter.authenticated) {
398 lockscreen.clear(true);
404 target: LightDM.Greeter
406 value: greeter.shown || lockscreen.shown || greeter.fakeActiveForApp != ""
412 opacity: greeterWrapper.showProgress * 0.8
416 // Just a tiny wrapper to adjust greeter's x without messing with its own dragging
421 height: parent.height - panel.panelHeight
424 enabled: !launcher.dashSwipe
428 property bool fullyShown: showProgress === 1.0
429 readonly property real showProgress: MathUtils.clamp((1 - x/width) + greeter.showProgress - 1, 0, 1)
430 onShowProgressChanged: if (LightDM.Greeter.promptless && showProgress === 0) greeter.login()
434 objectName: "greeter"
436 signal sessionStarted() // helpful for tests
438 property string fakeActiveForApp: ""
441 hides: [launcher, panel.indicators]
444 defaultBackground: shell.background
447 height: parent.height
449 dragHandleWidth: shell.edgeSize
453 LightDM.Greeter.startSessionSync();
464 if (!LightDM.Greeter.promptless) {
467 // If there is only one user, we start authenticating with that one here.
468 // If there are more users, the Greeter will handle that
469 if (LightDM.Users.count == 1) {
470 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole));
472 greeter.fakeActiveForApp = "";
473 greeter.forceActiveFocus();
477 onUnlocked: greeter.hide()
479 // Update launcher items for new user
480 var user = LightDM.Users.data(uid, LightDM.UserRoles.NameRole);
481 AccountsService.user = user;
482 LauncherModel.setUser(user);
485 onTease: launcher.tease()
488 target: ApplicationManager
489 property: "suspended"
490 value: greeter.shown && greeterWrapper.showProgress == 1
495 function showGreeterIfScreenIsOff() {
496 if (Powerd.status === Powerd.Off && !callManager.hasCalls && !edgeDemo.running) {
504 onHasCallsChanged: showGreeterIfScreenIsOff()
512 showGreeterIfScreenIsOff()
514 // No reason to chew demo CPU when user isn't watching
515 if (Powerd.status === Powerd.Off) {
516 edgeDemo.paused = true;
517 } else if (Powerd.status === Powerd.On) {
518 edgeDemo.paused = false;
523 function showHome() {
524 if (edgeDemo.running) {
528 if (LightDM.Greeter.active) {
529 if (!LightDM.Greeter.promptless) {
535 var animate = !LightDM.Greeter.active && !stages.shown
536 dash.setCurrentScope("clickscope", animate, false)
540 function showDash() {
541 if (LightDM.Greeter.active && !LightDM.Greeter.promptless) {
545 if (!stages.locked) {
549 launcher.switchToNextState("visible");
567 anchors.fill: parent //because this draws indicator menus
570 available: edgeDemo.panelEnabled && greeter.fakeActiveForApp === ""
571 contentEnabled: edgeDemo.panelContentEnabled
572 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
573 panelHeight: units.gu(3)
576 property bool topmostApplicationIsFullscreen:
577 ApplicationManager.focusedApplicationId &&
578 ApplicationManager.findApplication(ApplicationManager.focusedApplicationId).fullscreen
580 fullscreenMode: (stages.roughlyFullyShown && topmostApplicationIsFullscreen
581 && !LightDM.Greeter.active) || greeter.fakeActiveForApp !== ""
586 objectName: "launcher"
588 readonly property bool dashSwipe: progress > 0
590 anchors.top: parent.top
591 anchors.bottom: parent.bottom
593 dragAreaWidth: shell.edgeSize
594 available: edgeDemo.launcherEnabled && greeter.fakeActiveForApp === ""
596 onShowDashHome: showHome()
598 onDashSwipeChanged: if (dashSwipe && stages.shown) dash.setCurrentScope("clickscope", false, true)
599 onLauncherApplicationSelected: {
600 if (greeter.fakeActiveForApp !== "") {
603 if (!edgeDemo.running)
604 shell.activateApplication(appId)
608 panel.indicators.hide()
614 id: modalNotificationBackground
616 visible: notifications.useModal && !greeter.shown && (notifications.state == "narrow")
629 model: NotificationBackend.Model
634 height: parent.height - panel.panelHeight
639 when: overlay.width <= units.gu(60)
640 AnchorChanges { target: notifications; anchors.left: parent.left }
644 when: overlay.width > units.gu(60)
645 AnchorChanges { target: notifications; anchors.left: undefined }
646 PropertyChanges { target: notifications; width: units.gu(38) }
663 shutdownFadeOutRectangle.enabled = true;
664 shutdownFadeOutRectangle.visible = true;
665 shutdownFadeOut.start();
670 id: alphaDisclaimerLabel
671 anchors.centerIn: parent
672 visible: ApplicationManager.fake ? ApplicationManager.fake : false
674 text: "EARLY ALPHA\nNOT READY FOR USE"
677 font.weight: Font.Black
678 horizontalAlignment: Text.AlignHCenter
679 verticalAlignment: Text.AlignVCenter
680 fontSizeMode: Text.Fit
682 scale: Math.min(parent.width, parent.height) / width
687 z: alphaDisclaimerLabel.z + 10
691 indicators: panel.indicators
696 target: SessionBroadcast
697 onShowHome: showHome()
701 id: shutdownFadeOutRectangle
708 NumberAnimation on opacity {
713 if (shutdownFadeOutRectangle.enabled && shutdownFadeOutRectangle.visible) {
714 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