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.Launcher 0.1
28import LightDM 0.1 as LightDM
30import SessionBroadcast 0.1
39import Unity.Notifications 1.0 as NotificationBackend
40import Unity.Session 0.1
41import Unity.DashCommunicator 0.1
42import Unity.Indicators 0.1 as Indicators
47 // Disable everything while greeter is waiting, so that the user can't swipe
48 // the greeter or launcher until we know whether the session is locked.
49 enabled: !greeter.waiting
51 // this is only here to select the width / height of the window if not running fullscreen
52 property bool tablet: false
53 width: tablet ? units.gu(160) : applicationArguments.hasGeometry() ? applicationArguments.width() : units.gu(40)
54 height: tablet ? units.gu(100) : applicationArguments.hasGeometry() ? applicationArguments.height() : units.gu(71)
56 property real edgeSize: units.gu(2)
57 property url defaultBackground: Qt.resolvedUrl(shell.width >= units.gu(60) ? "graphics/tablet_background.jpg" : "graphics/phone_background.jpg")
58 property url background: asImageTester.status == Image.Ready ? asImageTester.source
59 : gsImageTester.status == Image.Ready ? gsImageTester.source : defaultBackground
60 readonly property real panelHeight: panel.panelHeight
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 function activateApplication(appId) {
82 if (ApplicationManager.findApplication(appId)) {
83 ApplicationManager.requestFocusApplication(appId);
85 var execFlags = shell.sideStageEnabled ? ApplicationManager.NoFlag : ApplicationManager.ForceMainStage;
86 ApplicationManager.startApplication(appId, execFlags);
90 function startLockedApp(app) {
92 greeter.lockedApp = app;
94 shell.activateApplication(app);
97 // This is a dummy image to detect if the custom AS set wallpaper loads successfully.
100 source: AccountsService.backgroundFile != undefined && AccountsService.backgroundFile.length > 0 ? AccountsService.backgroundFile : ""
108 id: backgroundSettings
109 schema.id: "org.gnome.desktop.background"
112 // This is a dummy image to detect if the custom GSettings set wallpaper loads successfully.
115 source: backgroundSettings.pictureUri != undefined && backgroundSettings.pictureUri.length > 0 ? backgroundSettings.pictureUri : ""
123 id: usageModeSettings
124 schema.id: "com.canonical.Unity8"
128 target: LauncherModel
129 property: "applicationManager"
130 value: ApplicationManager
133 Component.onCompleted: {
134 Theme.name = "Ubuntu.Components.Themes.SuruGradient"
135 if (ApplicationManager.count > 0) {
136 ApplicationManager.focusApplication(ApplicationManager.get(0).appId);
138 if (orientationLockEnabled) {
139 orientation = OrientationLock.savedOrientation;
149 objectName: "dashCommunicator"
153 id: physicalKeysMapper
155 onPowerKeyLongPressed: dialogs.showPowerDialog()
156 onVolumeDownTriggered: volumeControl.volumeDown();
157 onVolumeUpTriggered: volumeControl.volumeUp();
158 onScreenshotTriggered: screenGrabber.capture();
160 onAltTabNext: applicationsDisplayLoader.item.altTabNext()
161 onAltTabPrevious: applicationsDisplayLoader.item.altTabPrevious();
167 enabled: Powerd.status === Powerd.On
171 target: ApplicationManager
172 property: "forceDashActive"
173 value: launcher.shown || launcher.dashSwipe
177 Keys.onPressed: physicalKeysMapper.onKeyPressed(event);
178 Keys.onReleased: physicalKeysMapper.onKeyReleased(event);
185 height: parent.height
186 visible: !ApplicationManager.empty
189 target: ApplicationManager
191 // This signal is also fired when we try to focus the current app
192 // again. We rely on this!
193 onFocusedApplicationIdChanged: {
194 var appId = ApplicationManager.focusedApplicationId;
196 if (tutorial.running && appId != "unity8-dash") {
197 // If this happens on first boot, we may be in edge
198 // tutorial or wizard while receiving a call. But a call
199 // is more important than wizard so just bail out of those.
204 if (appId === "dialer-app" && callManager.hasCalls && greeter.locked) {
205 // If we are in the middle of a call, make dialer lockedApp and show it.
206 // This can happen if user backs out of dialer back to greeter, then
207 // launches dialer again.
208 greeter.lockedApp = appId;
210 greeter.notifyAppFocused(appId);
212 panel.indicators.hide();
215 onApplicationAdded: {
221 id: applicationsDisplayLoader
222 objectName: "applicationsDisplayLoader"
225 // When we have a locked app, we only want to show that one app.
226 // FIXME: do this in a less traumatic way. We currently only allow
227 // locked apps in phone mode (see FIXME in Lockscreen component in
228 // this same file). When that changes, we need to do something
229 // nicer here. But this code is currently just to prevent a
230 // theoretical attack where user enters lockedApp mode, then makes
231 // the screen larger (maybe connects to monitor) and tries to enter
233 property bool tabletMode: shell.sideStageEnabled && !greeter.hasLockedApp
234 source: usageModeSettings.usageMode === "Windowed" ? "Stages/DesktopStage.qml"
235 : tabletMode ? "Stages/TabletStage.qml" : "Stages/PhoneStage.qml"
237 property bool interactive: tutorial.spreadEnabled
239 && panel.indicators.fullyClosed
240 && launcher.progress == 0
241 && !notifications.useModal
243 onInteractiveChanged: { if (interactive) { focus = true; } }
246 target: applicationsDisplayLoader.item
247 property: "objectName"
251 target: applicationsDisplayLoader.item
252 property: "dragAreaWidth"
253 value: shell.edgeSize
256 target: applicationsDisplayLoader.item
257 property: "maximizedAppTopMargin"
258 // Not just using panel.panelHeight as that changes depending on the focused app.
259 value: panel.indicators.minimizedPanelHeight + units.dp(2) // dp(2) for orange line
262 target: applicationsDisplayLoader.item
263 property: "interactive"
264 value: applicationsDisplayLoader.interactive
267 target: applicationsDisplayLoader.item
268 property: "spreadEnabled"
269 value: tutorial.spreadEnabled && !greeter.hasLockedApp
272 target: applicationsDisplayLoader.item
273 property: "inverseProgress"
274 value: greeter.locked ? 0 : launcher.progress
277 target: applicationsDisplayLoader.item
278 property: "orientation"
279 value: shell.orientation
282 target: applicationsDisplayLoader.item
283 property: "background"
284 value: shell.background
287 target: applicationsDisplayLoader.item
288 property: "altTabPressed"
289 value: physicalKeysMapper.altTabPressed
296 objectName: "inputMethod"
297 anchors { fill: parent; topMargin: panel.panelHeight }
298 z: notifications.useModal || panel.indicators.shown || wizard.active ? overlay.z + 1 : overlay.z - 1
302 target: SurfaceManager
304 if (surface.type == MirSurfaceItem.InputMethod) {
305 inputMethod.surface = surface;
309 onSurfaceDestroyed: {
310 if (inputMethod.surface == surface) {
311 inputMethod.surface = null;
312 surface.parent = null;
314 if (!surface.parent) {
315 // there's no one displaying it. delete it right away
321 target: SessionManager
323 if (!session.parentSession && !session.application) {
324 // nothing is using it. delete it right away
332 objectName: "greeter"
334 hides: [launcher, panel.indicators]
335 tabletMode: shell.sideStageEnabled
336 launcherOffset: launcher.progress
337 forcedUnlock: tutorial.running
338 background: shell.background
341 anchors.topMargin: panel.panelHeight
343 // avoid overlapping with Launcher's edge drag area
344 // FIXME: Fix TouchRegistry & friends and remove this workaround
345 // Issue involves launcher's DDA getting disabled on a long
347 dragHandleLeftMargin: launcher.available ? launcher.dragAreaWidth + 1 : 0
354 if (!tutorial.running) {
359 onEmergencyCall: startLockedApp("dialer-app")
362 // See powerConnection for why this is useful
363 id: showGreeterDelayed
371 target: ApplicationManager
372 property: "suspended"
382 if (greeter.locked && callManager.hasCalls && greeter.lockedApp !== "dialer-app") {
383 // We just received an incoming call while locked. The
384 // indicator will have already launched dialer-app for us, but
385 // there is a race between "hasCalls" changing and the dialer
386 // starting up. So in case we lose that race, we'll start/
387 // focus the dialer ourselves here too. Even if the indicator
388 // didn't launch the dialer for some reason (or maybe a call
389 // started via some other means), if an active call is
390 // happening, we want to be in the dialer.
391 startLockedApp("dialer-app")
401 if (Powerd.status === Powerd.Off && reason !== Powerd.Proximity &&
402 !callManager.hasCalls && !tutorial.running) {
403 // We don't want to simply call greeter.showNow() here, because
404 // that will take too long. Qt will delay button event
405 // handling until the greeter is done loading and may think the
406 // user held down the power button the whole time, leading to a
407 // power dialog being shown. Instead, delay showing the
408 // greeter until we've finished handling the event. We could
409 // make the greeter load asynchronously instead, but that
410 // introduces a whole host of timing issues, especially with
411 // its animations. So this is simpler.
412 showGreeterDelayed.start();
417 function showHome() {
418 if (tutorial.running) {
422 greeter.notifyAboutToFocusApp("unity8-dash");
424 var animate = !LightDM.Greeter.active && !stages.shown
425 dash.setCurrentScope(0, animate, false)
426 ApplicationManager.requestFocusApplication("unity8-dash")
429 function showDash() {
430 if (greeter.notifyShowingDashFromDrag()) {
434 if (!greeter.locked && ApplicationManager.focusedApplicationId != "unity8-dash") {
435 ApplicationManager.requestFocusApplication("unity8-dash")
449 anchors.fill: parent //because this draws indicator menus
452 available: tutorial.panelEnabled
453 && (!greeter.locked || AccountsService.enableIndicatorsWhileLocked)
454 && !greeter.hasLockedApp
455 contentEnabled: tutorial.panelContentEnabled
456 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
458 minimizedPanelHeight: units.gu(3)
459 expandedPanelHeight: units.gu(7)
461 indicatorsModel: Indicators.IndicatorsModel {
462 // TODO: This should be sourced by device type (e.g. "desktop", "tablet", "phone"...)
463 profile: indicatorProfile
464 Component.onCompleted: load()
468 greeterShown: greeter.shown
471 property bool topmostApplicationIsFullscreen:
472 ApplicationManager.focusedApplicationId &&
473 ApplicationManager.findApplication(ApplicationManager.focusedApplicationId).fullscreen
475 fullscreenMode: (topmostApplicationIsFullscreen && !LightDM.Greeter.active && launcher.progress == 0)
476 || greeter.hasLockedApp
481 objectName: "launcher"
483 readonly property bool dashSwipe: progress > 0
485 anchors.top: parent.top
486 anchors.topMargin: inverted ? 0 : panel.panelHeight
487 anchors.bottom: parent.bottom
489 dragAreaWidth: shell.edgeSize
490 available: tutorial.launcherEnabled
491 && (!greeter.locked || AccountsService.enableLauncherWhileLocked)
492 && !greeter.hasLockedApp
493 inverted: usageModeSettings.usageMode === "Staged"
494 shadeBackground: !tutorial.running
496 onShowDashHome: showHome()
498 onDashSwipeChanged: {
500 dash.setCurrentScope(0, false, true)
503 onLauncherApplicationSelected: {
504 if (!tutorial.running) {
505 greeter.notifyAboutToFocusApp(appId);
506 shell.activateApplication(appId)
511 panel.indicators.hide()
519 background: shell.background
523 id: modalNotificationBackground
525 visible: notifications.useModal && (notifications.state == "narrow")
538 model: NotificationBackend.Model
541 y: topmostIsFullscreen ? 0 : panel.panelHeight
542 height: parent.height - (topmostIsFullscreen ? 0 : panel.panelHeight)
547 when: overlay.width <= units.gu(60)
549 target: notifications
550 anchors.left: parent.left
551 anchors.right: parent.right
556 when: overlay.width > units.gu(60)
558 target: notifications
559 anchors.left: undefined
560 anchors.right: parent.right
562 PropertyChanges { target: notifications; width: units.gu(38) }
573 shutdownFadeOutRectangle.enabled = true;
574 shutdownFadeOutRectangle.visible = true;
575 shutdownFadeOut.start();
581 objectName: "tutorial"
582 active: AccountsService.demoEdges
583 paused: LightDM.Greeter.active
588 edgeSize: shell.edgeSize
591 AccountsService.demoEdges = false;
592 active = false; // for immediate response / if AS is having problems
597 target: SessionBroadcast
598 onShowHome: showHome()
602 id: shutdownFadeOutRectangle
603 z: screenGrabber.z + 10
609 NumberAnimation on opacity {
614 if (shutdownFadeOutRectangle.enabled && shutdownFadeOutRectangle.visible) {
615 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