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 QtQuick.Window 2.0
19import AccountsService 0.1
21import Unity.Application 0.1
22import Ubuntu.Components 0.1
23import Ubuntu.Components.Popups 1.0
24import Ubuntu.Gestures 0.1
25import Ubuntu.Telephony 0.1 as Telephony
26import Unity.Connectivity 0.1
27import Unity.Launcher 0.1
29import LightDM 0.1 as LightDM
31import SessionBroadcast 0.1
40import Unity.Notifications 1.0 as NotificationBackend
41import Unity.Session 0.1
42import Unity.DashCommunicator 0.1
43import Unity.Indicators 0.1 as Indicators
48 // Disable everything while greeter is waiting, so that the user can't swipe
49 // the greeter or launcher until we know whether the session is locked.
50 enabled: !greeter.waiting
52 // this is only here to select the width / height of the window if not running fullscreen
53 property bool tablet: false
54 width: tablet ? units.gu(160) : applicationArguments.hasGeometry() ? applicationArguments.width() : units.gu(40)
55 height: tablet ? units.gu(100) : applicationArguments.hasGeometry() ? applicationArguments.height() : units.gu(71)
57 property real edgeSize: units.gu(2)
58 property url defaultBackground: Qt.resolvedUrl(shell.width >= units.gu(60) ? "graphics/tablet_background.jpg" : "graphics/phone_background.jpg")
59 property url background: asImageTester.status == Image.Ready ? asImageTester.source
60 : gsImageTester.status == Image.Ready ? gsImageTester.source : defaultBackground
62 property bool sideStageEnabled: shell.width >= units.gu(100)
63 readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId
65 property int orientation
66 readonly property int deviceOrientationAngle: Screen.angleBetween(Screen.primaryOrientation, Screen.orientation)
67 onDeviceOrientationAngleChanged: {
68 if (!OrientationLock.enabled) {
69 orientation = Screen.orientation;
72 readonly property bool orientationLockEnabled: OrientationLock.enabled
73 onOrientationLockEnabledChanged: {
74 if (orientationLockEnabled) {
75 OrientationLock.savedOrientation = Screen.orientation;
77 orientation = Screen.orientation;
81 // This is _only_ used to expose the property to autopilot tests
82 readonly property string testShellMode: shellMode
84 function activateApplication(appId) {
85 if (ApplicationManager.findApplication(appId)) {
86 ApplicationManager.requestFocusApplication(appId);
88 var execFlags = shell.sideStageEnabled ? ApplicationManager.NoFlag : ApplicationManager.ForceMainStage;
89 ApplicationManager.startApplication(appId, execFlags);
93 function startLockedApp(app) {
95 greeter.lockedApp = app;
97 shell.activateApplication(app);
100 // This is a dummy image to detect if the custom AS set wallpaper loads successfully.
103 source: AccountsService.backgroundFile != undefined && AccountsService.backgroundFile.length > 0 ? AccountsService.backgroundFile : ""
111 id: backgroundSettings
112 objectName: "backgroundSettings"
113 schema.id: "org.gnome.desktop.background"
116 // This is a dummy image to detect if the custom GSettings set wallpaper loads successfully.
119 source: backgroundSettings.pictureUri != undefined && backgroundSettings.pictureUri.length > 0 ? backgroundSettings.pictureUri : ""
127 id: usageModeSettings
128 schema.id: "com.canonical.Unity8"
132 target: LauncherModel
133 property: "applicationManager"
134 value: ApplicationManager
137 Component.onCompleted: {
138 Theme.name = "Ubuntu.Components.Themes.SuruGradient"
139 if (ApplicationManager.count > 0) {
140 ApplicationManager.focusApplication(ApplicationManager.get(0).appId);
142 if (orientationLockEnabled) {
143 orientation = OrientationLock.savedOrientation;
153 objectName: "dashCommunicator"
157 id: physicalKeysMapper
159 onPowerKeyLongPressed: dialogs.showPowerDialog()
160 onVolumeDownTriggered: volumeControl.volumeDown();
161 onVolumeUpTriggered: volumeControl.volumeUp();
162 onScreenshotTriggered: screenGrabber.capture();
168 enabled: Powerd.status === Powerd.On
172 target: ApplicationManager
173 property: "forceDashActive"
174 value: launcher.shown || launcher.dashSwipe
178 Keys.onPressed: physicalKeysMapper.onKeyPressed(event);
179 Keys.onReleased: physicalKeysMapper.onKeyReleased(event);
183 onActivated: { launcher.fadeOut(); shell.showHome(); }
190 height: parent.height
193 target: ApplicationManager
195 // This signal is also fired when we try to focus the current app
196 // again. We rely on this!
197 onFocusedApplicationIdChanged: {
198 var appId = ApplicationManager.focusedApplicationId;
200 if (tutorial.running && appId != "" && appId != "unity8-dash") {
201 // If this happens on first boot, we may be in edge
202 // tutorial or wizard while receiving a call. But a call
203 // is more important than wizard so just bail out of those.
208 if (appId === "dialer-app" && callManager.hasCalls && greeter.locked) {
209 // If we are in the middle of a call, make dialer lockedApp and show it.
210 // This can happen if user backs out of dialer back to greeter, then
211 // launches dialer again.
212 greeter.lockedApp = appId;
214 greeter.notifyAppFocused(appId);
216 panel.indicators.hide();
219 onApplicationAdded: {
225 id: applicationsDisplayLoader
226 objectName: "applicationsDisplayLoader"
229 // When we have a locked app, we only want to show that one app.
230 // FIXME: do this in a less traumatic way. We currently only allow
231 // locked apps in phone mode (see FIXME in Lockscreen component in
232 // this same file). When that changes, we need to do something
233 // nicer here. But this code is currently just to prevent a
234 // theoretical attack where user enters lockedApp mode, then makes
235 // the screen larger (maybe connects to monitor) and tries to enter
237 property bool tabletMode: shell.sideStageEnabled && !greeter.hasLockedApp
238 source: usageModeSettings.usageMode === "Windowed" ? "Stages/DesktopStage.qml"
239 : tabletMode ? "Stages/TabletStage.qml" : "Stages/PhoneStage.qml"
241 property bool interactive: tutorial.spreadEnabled
243 && panel.indicators.fullyClosed
244 && launcher.progress == 0
245 && !notifications.useModal
247 onInteractiveChanged: { if (interactive) { focus = true; } }
250 target: applicationsDisplayLoader.item
251 property: "objectName"
255 target: applicationsDisplayLoader.item
256 property: "dragAreaWidth"
257 value: shell.edgeSize
260 target: applicationsDisplayLoader.item
261 property: "maximizedAppTopMargin"
262 // Not just using panel.panelHeight as that changes depending on the focused app.
263 value: panel.indicators.minimizedPanelHeight + units.dp(2) // dp(2) for orange line
266 target: applicationsDisplayLoader.item
267 property: "interactive"
268 value: applicationsDisplayLoader.interactive
271 target: applicationsDisplayLoader.item
272 property: "spreadEnabled"
273 value: tutorial.spreadEnabled && !greeter.hasLockedApp
276 target: applicationsDisplayLoader.item
277 property: "inverseProgress"
278 value: greeter.locked ? 0 : launcher.progress
281 target: applicationsDisplayLoader.item
282 property: "orientation"
283 value: shell.orientation
286 target: applicationsDisplayLoader.item
287 property: "background"
288 value: shell.background
294 objectName: "tutorial"
296 active: AccountsService.demoEdges
297 paused: LightDM.Greeter.active
300 edgeSize: shell.edgeSize
302 // EdgeDragAreas don't work with mice. So to avoid trapping the user,
303 // we'll tell the tutorial to avoid using them on the Desktop. The
304 // Desktop doesn't use the same spread design anyway. The tutorial is
305 // all a bit of a placeholder on non-phone form factors right now.
306 // When the design team gives us more guidance, we can do something
308 // TODO: use DeviceConfiguration instead of checking source
309 useEdgeDragArea: applicationsDisplayLoader.source != Qt.resolvedUrl("Stages/DesktopStage.qml")
312 AccountsService.demoEdges = false;
313 active = false; // for immediate response / if AS is having problems
320 objectName: "inputMethod"
321 anchors { fill: parent; topMargin: panel.panelHeight }
322 z: notifications.useModal || panel.indicators.shown || wizard.active ? overlay.z + 1 : overlay.z - 1
326 target: SurfaceManager
328 if (surface.type == MirSurfaceItem.InputMethod) {
329 inputMethod.surface = surface;
333 onSurfaceDestroyed: {
334 if (inputMethod.surface == surface) {
335 inputMethod.surface = null;
336 surface.parent = null;
338 if (!surface.parent) {
339 // there's no one displaying it. delete it right away
345 target: SessionManager
347 if (!session.parentSession && !session.application) {
348 // nothing is using it. delete it right away
356 objectName: "greeter"
358 hides: [launcher, panel.indicators]
359 tabletMode: shell.sideStageEnabled
360 launcherOffset: launcher.progress
361 forcedUnlock: tutorial.running
362 background: shell.background
365 anchors.topMargin: panel.panelHeight
367 // avoid overlapping with Launcher's edge drag area
368 // FIXME: Fix TouchRegistry & friends and remove this workaround
369 // Issue involves launcher's DDA getting disabled on a long
371 dragHandleLeftMargin: launcher.available ? launcher.dragAreaWidth + 1 : 0
378 if (!tutorial.running) {
383 onEmergencyCall: startLockedApp("dialer-app")
386 // See powerConnection for why this is useful
387 id: showGreeterDelayed
395 target: ApplicationManager
396 property: "suspended"
406 if (greeter.locked && callManager.hasCalls && greeter.lockedApp !== "dialer-app") {
407 // We just received an incoming call while locked. The
408 // indicator will have already launched dialer-app for us, but
409 // there is a race between "hasCalls" changing and the dialer
410 // starting up. So in case we lose that race, we'll start/
411 // focus the dialer ourselves here too. Even if the indicator
412 // didn't launch the dialer for some reason (or maybe a call
413 // started via some other means), if an active call is
414 // happening, we want to be in the dialer.
415 startLockedApp("dialer-app")
425 if (Powerd.status === Powerd.Off && reason !== Powerd.Proximity &&
426 !callManager.hasCalls && !tutorial.running) {
427 // We don't want to simply call greeter.showNow() here, because
428 // that will take too long. Qt will delay button event
429 // handling until the greeter is done loading and may think the
430 // user held down the power button the whole time, leading to a
431 // power dialog being shown. Instead, delay showing the
432 // greeter until we've finished handling the event. We could
433 // make the greeter load asynchronously instead, but that
434 // introduces a whole host of timing issues, especially with
435 // its animations. So this is simpler.
436 showGreeterDelayed.start();
441 function showHome() {
442 if (tutorial.running) {
446 greeter.notifyAboutToFocusApp("unity8-dash");
448 var animate = !LightDM.Greeter.active && !stages.shown
449 dash.setCurrentScope(0, animate, false)
450 ApplicationManager.requestFocusApplication("unity8-dash")
453 function showDash() {
454 if (greeter.notifyShowingDashFromDrag()) {
458 if (!greeter.locked && ApplicationManager.focusedApplicationId != "unity8-dash") {
459 ApplicationManager.requestFocusApplication("unity8-dash")
473 anchors.fill: parent //because this draws indicator menus
476 available: tutorial.panelEnabled
477 && (!greeter.locked || AccountsService.enableIndicatorsWhileLocked)
478 && !greeter.hasLockedApp
479 contentEnabled: tutorial.panelContentEnabled
480 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
482 minimizedPanelHeight: units.gu(3)
483 expandedPanelHeight: units.gu(7)
485 indicatorsModel: Indicators.IndicatorsModel {
486 // TODO: This should be sourced by device type (e.g. "desktop", "tablet", "phone"...)
487 profile: indicatorProfile
488 Component.onCompleted: load()
492 greeterShown: greeter.shown
495 property bool topmostApplicationIsFullscreen:
496 ApplicationManager.focusedApplicationId &&
497 ApplicationManager.findApplication(ApplicationManager.focusedApplicationId).fullscreen
499 fullscreenMode: (topmostApplicationIsFullscreen && !LightDM.Greeter.active && launcher.progress == 0)
500 || greeter.hasLockedApp
505 objectName: "launcher"
507 readonly property bool dashSwipe: progress > 0
509 anchors.top: parent.top
510 anchors.topMargin: inverted ? 0 : panel.panelHeight
511 anchors.bottom: parent.bottom
513 dragAreaWidth: shell.edgeSize
514 available: tutorial.launcherEnabled
515 && (!greeter.locked || AccountsService.enableLauncherWhileLocked)
516 && !greeter.hasLockedApp
517 inverted: usageModeSettings.usageMode === "Staged"
518 shadeBackground: !tutorial.running
520 onShowDashHome: showHome()
522 onDashSwipeChanged: {
524 dash.setCurrentScope(0, false, true)
527 onLauncherApplicationSelected: {
528 if (!tutorial.running) {
529 greeter.notifyAboutToFocusApp(appId);
530 shell.activateApplication(appId)
535 panel.indicators.hide()
544 background: shell.background
546 function unlockWhenDoneWithWizard() {
548 Connectivity.unlockAllModems();
552 Component.onCompleted: unlockWhenDoneWithWizard()
553 onActiveChanged: unlockWhenDoneWithWizard()
557 id: modalNotificationBackground
559 visible: notifications.useModal && (notifications.state == "narrow")
572 model: NotificationBackend.Model
575 y: topmostIsFullscreen ? 0 : panel.panelHeight
576 height: parent.height - (topmostIsFullscreen ? 0 : panel.panelHeight)
581 when: overlay.width <= units.gu(60)
583 target: notifications
584 anchors.left: parent.left
585 anchors.right: parent.right
590 when: overlay.width > units.gu(60)
592 target: notifications
593 anchors.left: undefined
594 anchors.right: parent.right
596 PropertyChanges { target: notifications; width: units.gu(38) }
607 shutdownFadeOutRectangle.enabled = true;
608 shutdownFadeOutRectangle.visible = true;
609 shutdownFadeOut.start();
614 target: SessionBroadcast
615 onShowHome: showHome()
619 id: shutdownFadeOutRectangle
620 z: screenGrabber.z + 10
626 NumberAnimation on opacity {
631 if (shutdownFadeOutRectangle.enabled && shutdownFadeOutRectangle.visible) {
632 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