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
61 readonly property real panelHeight: panel.panelHeight
63 property bool sideStageEnabled: shell.width >= units.gu(100)
64 readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId
66 property int orientation
67 readonly property int deviceOrientationAngle: Screen.angleBetween(Screen.primaryOrientation, Screen.orientation)
68 onDeviceOrientationAngleChanged: {
69 if (!OrientationLock.enabled) {
70 orientation = Screen.orientation;
73 readonly property bool orientationLockEnabled: OrientationLock.enabled
74 onOrientationLockEnabledChanged: {
75 if (orientationLockEnabled) {
76 OrientationLock.savedOrientation = Screen.orientation;
78 orientation = Screen.orientation;
82 function activateApplication(appId) {
83 if (ApplicationManager.findApplication(appId)) {
84 ApplicationManager.requestFocusApplication(appId);
86 var execFlags = shell.sideStageEnabled ? ApplicationManager.NoFlag : ApplicationManager.ForceMainStage;
87 ApplicationManager.startApplication(appId, execFlags);
91 function startLockedApp(app) {
93 greeter.lockedApp = app;
95 shell.activateApplication(app);
98 // This is a dummy image to detect if the custom AS set wallpaper loads successfully.
101 source: AccountsService.backgroundFile != undefined && AccountsService.backgroundFile.length > 0 ? AccountsService.backgroundFile : ""
109 id: backgroundSettings
110 objectName: "backgroundSettings"
111 schema.id: "org.gnome.desktop.background"
114 // This is a dummy image to detect if the custom GSettings set wallpaper loads successfully.
117 source: backgroundSettings.pictureUri != undefined && backgroundSettings.pictureUri.length > 0 ? backgroundSettings.pictureUri : ""
125 id: usageModeSettings
126 schema.id: "com.canonical.Unity8"
130 target: LauncherModel
131 property: "applicationManager"
132 value: ApplicationManager
135 Component.onCompleted: {
136 Theme.name = "Ubuntu.Components.Themes.SuruGradient"
137 if (ApplicationManager.count > 0) {
138 ApplicationManager.focusApplication(ApplicationManager.get(0).appId);
140 if (orientationLockEnabled) {
141 orientation = OrientationLock.savedOrientation;
151 objectName: "dashCommunicator"
155 id: physicalKeysMapper
157 onPowerKeyLongPressed: dialogs.showPowerDialog()
158 onVolumeDownTriggered: volumeControl.volumeDown();
159 onVolumeUpTriggered: volumeControl.volumeUp();
160 onScreenshotTriggered: screenGrabber.capture();
166 enabled: Powerd.status === Powerd.On
170 target: ApplicationManager
171 property: "forceDashActive"
172 value: launcher.shown || launcher.dashSwipe
176 Keys.onPressed: physicalKeysMapper.onKeyPressed(event);
177 Keys.onReleased: physicalKeysMapper.onKeyReleased(event);
184 height: parent.height
185 visible: !ApplicationManager.empty
188 target: ApplicationManager
190 // This signal is also fired when we try to focus the current app
191 // again. We rely on this!
192 onFocusedApplicationIdChanged: {
193 var appId = ApplicationManager.focusedApplicationId;
195 if (tutorial.running && appId != "" && appId != "unity8-dash") {
196 // If this happens on first boot, we may be in edge
197 // tutorial or wizard while receiving a call. But a call
198 // is more important than wizard so just bail out of those.
203 if (appId === "dialer-app" && callManager.hasCalls && greeter.locked) {
204 // If we are in the middle of a call, make dialer lockedApp and show it.
205 // This can happen if user backs out of dialer back to greeter, then
206 // launches dialer again.
207 greeter.lockedApp = appId;
209 greeter.notifyAppFocused(appId);
211 panel.indicators.hide();
214 onApplicationAdded: {
220 id: applicationsDisplayLoader
221 objectName: "applicationsDisplayLoader"
224 // When we have a locked app, we only want to show that one app.
225 // FIXME: do this in a less traumatic way. We currently only allow
226 // locked apps in phone mode (see FIXME in Lockscreen component in
227 // this same file). When that changes, we need to do something
228 // nicer here. But this code is currently just to prevent a
229 // theoretical attack where user enters lockedApp mode, then makes
230 // the screen larger (maybe connects to monitor) and tries to enter
232 property bool tabletMode: shell.sideStageEnabled && !greeter.hasLockedApp
233 source: usageModeSettings.usageMode === "Windowed" ? "Stages/DesktopStage.qml"
234 : tabletMode ? "Stages/TabletStage.qml" : "Stages/PhoneStage.qml"
236 property bool interactive: tutorial.spreadEnabled
238 && panel.indicators.fullyClosed
239 && launcher.progress == 0
240 && !notifications.useModal
242 onInteractiveChanged: { if (interactive) { focus = true; } }
245 target: applicationsDisplayLoader.item
246 property: "objectName"
250 target: applicationsDisplayLoader.item
251 property: "dragAreaWidth"
252 value: shell.edgeSize
255 target: applicationsDisplayLoader.item
256 property: "maximizedAppTopMargin"
257 // Not just using panel.panelHeight as that changes depending on the focused app.
258 value: panel.indicators.minimizedPanelHeight + units.dp(2) // dp(2) for orange line
261 target: applicationsDisplayLoader.item
262 property: "interactive"
263 value: applicationsDisplayLoader.interactive
266 target: applicationsDisplayLoader.item
267 property: "spreadEnabled"
268 value: tutorial.spreadEnabled && !greeter.hasLockedApp
271 target: applicationsDisplayLoader.item
272 property: "inverseProgress"
273 value: greeter.locked ? 0 : launcher.progress
276 target: applicationsDisplayLoader.item
277 property: "orientation"
278 value: shell.orientation
281 target: applicationsDisplayLoader.item
282 property: "background"
283 value: shell.background
289 objectName: "tutorial"
291 active: AccountsService.demoEdges
292 paused: LightDM.Greeter.active
295 edgeSize: shell.edgeSize
298 AccountsService.demoEdges = false;
299 active = false; // for immediate response / if AS is having problems
306 objectName: "inputMethod"
307 anchors { fill: parent; topMargin: panel.panelHeight }
308 z: notifications.useModal || panel.indicators.shown || wizard.active ? overlay.z + 1 : overlay.z - 1
312 target: SurfaceManager
314 if (surface.type == MirSurfaceItem.InputMethod) {
315 inputMethod.surface = surface;
319 onSurfaceDestroyed: {
320 if (inputMethod.surface == surface) {
321 inputMethod.surface = null;
322 surface.parent = null;
324 if (!surface.parent) {
325 // there's no one displaying it. delete it right away
331 target: SessionManager
333 if (!session.parentSession && !session.application) {
334 // nothing is using it. delete it right away
342 objectName: "greeter"
344 hides: [launcher, panel.indicators]
345 tabletMode: shell.sideStageEnabled
346 launcherOffset: launcher.progress
347 forcedUnlock: tutorial.running
348 background: shell.background
351 anchors.topMargin: panel.panelHeight
353 // avoid overlapping with Launcher's edge drag area
354 // FIXME: Fix TouchRegistry & friends and remove this workaround
355 // Issue involves launcher's DDA getting disabled on a long
357 dragHandleLeftMargin: launcher.available ? launcher.dragAreaWidth + 1 : 0
364 if (!tutorial.running) {
369 onEmergencyCall: startLockedApp("dialer-app")
372 // See powerConnection for why this is useful
373 id: showGreeterDelayed
381 target: ApplicationManager
382 property: "suspended"
392 if (greeter.locked && callManager.hasCalls && greeter.lockedApp !== "dialer-app") {
393 // We just received an incoming call while locked. The
394 // indicator will have already launched dialer-app for us, but
395 // there is a race between "hasCalls" changing and the dialer
396 // starting up. So in case we lose that race, we'll start/
397 // focus the dialer ourselves here too. Even if the indicator
398 // didn't launch the dialer for some reason (or maybe a call
399 // started via some other means), if an active call is
400 // happening, we want to be in the dialer.
401 startLockedApp("dialer-app")
411 if (Powerd.status === Powerd.Off && reason !== Powerd.Proximity &&
412 !callManager.hasCalls && !tutorial.running) {
413 // We don't want to simply call greeter.showNow() here, because
414 // that will take too long. Qt will delay button event
415 // handling until the greeter is done loading and may think the
416 // user held down the power button the whole time, leading to a
417 // power dialog being shown. Instead, delay showing the
418 // greeter until we've finished handling the event. We could
419 // make the greeter load asynchronously instead, but that
420 // introduces a whole host of timing issues, especially with
421 // its animations. So this is simpler.
422 showGreeterDelayed.start();
427 function showHome() {
428 if (tutorial.running) {
432 greeter.notifyAboutToFocusApp("unity8-dash");
434 var animate = !LightDM.Greeter.active && !stages.shown
435 dash.setCurrentScope(0, animate, false)
436 ApplicationManager.requestFocusApplication("unity8-dash")
439 function showDash() {
440 if (greeter.notifyShowingDashFromDrag()) {
444 if (!greeter.locked && ApplicationManager.focusedApplicationId != "unity8-dash") {
445 ApplicationManager.requestFocusApplication("unity8-dash")
459 anchors.fill: parent //because this draws indicator menus
462 available: tutorial.panelEnabled
463 && (!greeter.locked || AccountsService.enableIndicatorsWhileLocked)
464 && !greeter.hasLockedApp
465 contentEnabled: tutorial.panelContentEnabled
466 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
468 minimizedPanelHeight: units.gu(3)
469 expandedPanelHeight: units.gu(7)
471 indicatorsModel: Indicators.IndicatorsModel {
472 // TODO: This should be sourced by device type (e.g. "desktop", "tablet", "phone"...)
473 profile: indicatorProfile
474 Component.onCompleted: load()
478 greeterShown: greeter.shown
481 property bool topmostApplicationIsFullscreen:
482 ApplicationManager.focusedApplicationId &&
483 ApplicationManager.findApplication(ApplicationManager.focusedApplicationId).fullscreen
485 fullscreenMode: (topmostApplicationIsFullscreen && !LightDM.Greeter.active && launcher.progress == 0)
486 || greeter.hasLockedApp
491 objectName: "launcher"
493 readonly property bool dashSwipe: progress > 0
495 anchors.top: parent.top
496 anchors.topMargin: inverted ? 0 : panel.panelHeight
497 anchors.bottom: parent.bottom
499 dragAreaWidth: shell.edgeSize
500 available: tutorial.launcherEnabled
501 && (!greeter.locked || AccountsService.enableLauncherWhileLocked)
502 && !greeter.hasLockedApp
503 inverted: usageModeSettings.usageMode === "Staged"
504 shadeBackground: !tutorial.running
506 onShowDashHome: showHome()
508 onDashSwipeChanged: {
510 dash.setCurrentScope(0, false, true)
513 onLauncherApplicationSelected: {
514 if (!tutorial.running) {
515 greeter.notifyAboutToFocusApp(appId);
516 shell.activateApplication(appId)
521 panel.indicators.hide()
530 background: shell.background
532 function unlockWhenDoneWithWizard() {
534 Connectivity.unlockAllModems();
538 Component.onCompleted: unlockWhenDoneWithWizard()
539 onActiveChanged: unlockWhenDoneWithWizard()
543 id: modalNotificationBackground
545 visible: notifications.useModal && (notifications.state == "narrow")
558 model: NotificationBackend.Model
561 y: topmostIsFullscreen ? 0 : panel.panelHeight
562 height: parent.height - (topmostIsFullscreen ? 0 : panel.panelHeight)
567 when: overlay.width <= units.gu(60)
569 target: notifications
570 anchors.left: parent.left
571 anchors.right: parent.right
576 when: overlay.width > units.gu(60)
578 target: notifications
579 anchors.left: undefined
580 anchors.right: parent.right
582 PropertyChanges { target: notifications; width: units.gu(38) }
593 shutdownFadeOutRectangle.enabled = true;
594 shutdownFadeOutRectangle.visible = true;
595 shutdownFadeOut.start();
600 target: SessionBroadcast
601 onShowHome: showHome()
605 id: shutdownFadeOutRectangle
606 z: screenGrabber.z + 10
612 NumberAnimation on opacity {
617 if (shutdownFadeOutRectangle.enabled && shutdownFadeOutRectangle.visible) {
618 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