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
38import Unity.Notifications 1.0 as NotificationBackend
39import Unity.Session 0.1
40import Unity.DashCommunicator 0.1
41import Unity.Indicators 0.1 as Indicators
46 // Disable everything while greeter is waiting, so that the user can't swipe
47 // the greeter or launcher until we know whether the session is locked.
48 enabled: !greeter.waiting
50 // this is only here to select the width / height of the window if not running fullscreen
51 property bool tablet: false
52 width: tablet ? units.gu(160) : applicationArguments.hasGeometry() ? applicationArguments.width() : units.gu(40)
53 height: tablet ? units.gu(100) : applicationArguments.hasGeometry() ? applicationArguments.height() : units.gu(71)
55 property real edgeSize: units.gu(2)
56 property url defaultBackground: Qt.resolvedUrl(shell.width >= units.gu(60) ? "graphics/tablet_background.jpg" : "graphics/phone_background.jpg")
57 property url background: asImageTester.status == Image.Ready ? asImageTester.source
58 : gsImageTester.status == Image.Ready ? gsImageTester.source : defaultBackground
59 readonly property real panelHeight: panel.panelHeight
61 property bool sideStageEnabled: shell.width >= units.gu(100)
62 readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId
64 property int orientation
65 readonly property int deviceOrientationAngle: Screen.angleBetween(Screen.primaryOrientation, Screen.orientation)
66 onDeviceOrientationAngleChanged: {
67 if (!OrientationLock.enabled) {
68 orientation = Screen.orientation;
71 readonly property bool orientationLockEnabled: OrientationLock.enabled
72 onOrientationLockEnabledChanged: {
73 if (orientationLockEnabled) {
74 OrientationLock.savedOrientation = Screen.orientation;
76 orientation = Screen.orientation;
80 function activateApplication(appId) {
81 if (ApplicationManager.findApplication(appId)) {
82 ApplicationManager.requestFocusApplication(appId);
84 var execFlags = shell.sideStageEnabled ? ApplicationManager.NoFlag : ApplicationManager.ForceMainStage;
85 ApplicationManager.startApplication(appId, execFlags);
89 function startLockedApp(app) {
91 greeter.lockedApp = app;
93 shell.activateApplication(app);
96 // This is a dummy image to detect if the custom AS set wallpaper loads successfully.
99 source: AccountsService.backgroundFile != undefined && AccountsService.backgroundFile.length > 0 ? AccountsService.backgroundFile : ""
107 id: backgroundSettings
108 objectName: "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"
155 enabled: Powerd.status === Powerd.On
159 target: ApplicationManager
160 property: "forceDashActive"
161 value: launcher.shown || launcher.dashSwipe
166 onVolumeDownPressed: volumeControl.volumeDown()
167 onVolumeUpPressed: volumeControl.volumeUp()
168 onBothVolumeKeysPressed: screenGrabber.capture()
173 // Nokia earpieces give TogglePlayPause, while the iPhone's earpiece gives Play
174 if (event.key == Qt.Key_MediaTogglePlayPause || event.key == Qt.Key_MediaPlay) {
175 event.accepted = callManager.handleMediaKey(false);
176 } else if (event.key == Qt.Key_PowerOff || event.key == Qt.Key_PowerDown) {
177 // FIXME: We only consider power key presses if the screen is
178 // on because of bugs 1410830/1409003. The theory is that when
179 // those bugs are encountered, there is a >2s delay between the
180 // power press event and the power release event, which causes
181 // the shutdown dialog to appear on resume. So to avoid that
182 // symptom while we investigate the root cause, we simply won't
183 // initiate any dialogs when the screen is off.
184 if (Powerd.status === Powerd.On) {
185 dialogs.onPowerKeyPressed();
187 event.accepted = true;
189 volumeKeyFilter.onKeyPressed(event.key);
190 event.accepted = false;
195 if (event.key == Qt.Key_PowerOff || event.key == Qt.Key_PowerDown) {
196 dialogs.onPowerKeyReleased();
197 event.accepted = true;
199 volumeKeyFilter.onKeyReleased(event.key);
200 event.accepted = false;
209 height: parent.height
210 visible: !ApplicationManager.empty
213 target: ApplicationManager
216 if (appId === "dialer-app" && callManager.hasCalls && greeter.locked) {
217 // If we are in the middle of a call, make dialer lockedApp and show it.
218 // This can happen if user backs out of dialer back to greeter, then
219 // launches dialer again.
220 greeter.lockedApp = appId;
223 greeter.notifyAppFocused(appId);
226 onFocusedApplicationIdChanged: {
227 greeter.notifyAppFocused(ApplicationManager.focusedApplicationId);
228 panel.indicators.hide();
231 onApplicationAdded: {
232 if (edgeDemo.running && appId != "unity8-dash") {
233 // If this happens on first boot, we may be in edge
234 // tutorial or wizard while receiving a call. But a call
235 // is more important than wizard so just bail out of those.
236 edgeDemo.hideEdgeDemos();
240 greeter.notifyAppFocused(appId);
246 id: applicationsDisplayLoader
247 objectName: "applicationsDisplayLoader"
250 // When we have a locked app, we only want to show that one app.
251 // FIXME: do this in a less traumatic way. We currently only allow
252 // locked apps in phone mode (see FIXME in Lockscreen component in
253 // this same file). When that changes, we need to do something
254 // nicer here. But this code is currently just to prevent a
255 // theoretical attack where user enters lockedApp mode, then makes
256 // the screen larger (maybe connects to monitor) and tries to enter
258 property bool tabletMode: shell.sideStageEnabled && !greeter.hasLockedApp
259 source: usageModeSettings.usageMode === "Windowed" ? "Stages/DesktopStage.qml"
260 : tabletMode ? "Stages/TabletStage.qml" : "Stages/PhoneStage.qml"
263 target: applicationsDisplayLoader.item
264 property: "objectName"
268 target: applicationsDisplayLoader.item
269 property: "dragAreaWidth"
270 value: shell.edgeSize
273 target: applicationsDisplayLoader.item
274 property: "maximizedAppTopMargin"
275 // Not just using panel.panelHeight as that changes depending on the focused app.
276 value: panel.indicators.minimizedPanelHeight + units.dp(2) // dp(2) for orange line
279 target: applicationsDisplayLoader.item
280 property: "interactive"
281 value: edgeDemo.stagesEnabled && !greeter.shown && panel.indicators.fullyClosed && launcher.progress == 0 && !notifications.useModal
284 target: applicationsDisplayLoader.item
285 property: "spreadEnabled"
286 value: edgeDemo.stagesEnabled && !greeter.hasLockedApp
289 target: applicationsDisplayLoader.item
290 property: "inverseProgress"
291 value: launcher.progress
294 target: applicationsDisplayLoader.item
295 property: "orientation"
296 value: shell.orientation
299 target: applicationsDisplayLoader.item
300 property: "background"
301 value: shell.background
308 objectName: "inputMethod"
309 anchors { fill: parent; topMargin: panel.panelHeight }
310 z: notifications.useModal || panel.indicators.shown || wizard.active ? overlay.z + 1 : overlay.z - 1
314 target: SurfaceManager
316 if (surface.type == MirSurfaceItem.InputMethod) {
317 inputMethod.surface = surface;
321 onSurfaceDestroyed: {
322 if (inputMethod.surface == surface) {
323 inputMethod.surface = null;
324 surface.parent = null;
326 if (!surface.parent) {
327 // there's no one displaying it. delete it right away
333 target: SessionManager
335 if (!session.parentSession && !session.application) {
336 // nothing is using it. delete it right away
344 objectName: "greeter"
346 hides: [launcher, panel.indicators]
347 tabletMode: shell.sideStageEnabled
348 launcherOffset: launcher.progress
349 forcedUnlock: edgeDemo.running
350 background: shell.background
353 anchors.topMargin: panel.panelHeight
355 // avoid overlapping with Launcher's edge drag area
356 // FIXME: Fix TouchRegistry & friends and remove this workaround
357 // Issue involves launcher's DDA getting disabled on a long
359 dragHandleLeftMargin: launcher.available ? launcher.dragAreaWidth + 1 : 0
365 onTease: launcher.tease()
367 onEmergencyCall: startLockedApp("dialer-app")
370 // See powerConnection for why this is useful
371 id: showGreeterDelayed
379 target: ApplicationManager
380 property: "suspended"
390 if (greeter.locked && callManager.hasCalls && greeter.lockedApp !== "dialer-app") {
391 // We just received an incoming call while locked. The
392 // indicator will have already launched dialer-app for us, but
393 // there is a race between "hasCalls" changing and the dialer
394 // starting up. So in case we lose that race, we'll start/
395 // focus the dialer ourselves here too. Even if the indicator
396 // didn't launch the dialer for some reason (or maybe a call
397 // started via some other means), if an active call is
398 // happening, we want to be in the dialer.
399 startLockedApp("dialer-app")
409 if (Powerd.status === Powerd.Off && reason !== Powerd.Proximity &&
410 !callManager.hasCalls && !edgeDemo.running) {
411 // We don't want to simply call greeter.showNow() here, because
412 // that will take too long. Qt will delay button event
413 // handling until the greeter is done loading and may think the
414 // user held down the power button the whole time, leading to a
415 // power dialog being shown. Instead, delay showing the
416 // greeter until we've finished handling the event. We could
417 // make the greeter load asynchronously instead, but that
418 // introduces a whole host of timing issues, especially with
419 // its animations. So this is simpler.
420 showGreeterDelayed.start();
425 function showHome() {
426 if (edgeDemo.running) {
430 greeter.notifyAboutToFocusApp("unity8-dash");
432 var animate = !LightDM.Greeter.active && !stages.shown
433 dash.setCurrentScope(0, animate, false)
434 ApplicationManager.requestFocusApplication("unity8-dash")
437 function showDash() {
438 if (greeter.active) {
439 greeter.notifyShowingDashFromDrag();
443 if (ApplicationManager.focusedApplicationId != "unity8-dash") {
444 ApplicationManager.requestFocusApplication("unity8-dash")
458 anchors.fill: parent //because this draws indicator menus
461 available: edgeDemo.panelEnabled && (!greeter.locked || AccountsService.enableIndicatorsWhileLocked) && !greeter.hasLockedApp
462 contentEnabled: edgeDemo.panelContentEnabled
463 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
465 minimizedPanelHeight: units.gu(3)
466 expandedPanelHeight: units.gu(7)
468 indicatorsModel: Indicators.IndicatorsModel {
469 Component.onCompleted: load(indicatorProfile);
473 greeterShown: greeter.shown
476 property bool topmostApplicationIsFullscreen:
477 ApplicationManager.focusedApplicationId &&
478 ApplicationManager.findApplication(ApplicationManager.focusedApplicationId).fullscreen
480 fullscreenMode: (topmostApplicationIsFullscreen && !LightDM.Greeter.active && launcher.progress == 0)
481 || greeter.hasLockedApp
486 objectName: "launcher"
488 readonly property bool dashSwipe: progress > 0
490 anchors.top: parent.top
491 anchors.topMargin: inverted ? 0 : panel.panelHeight
492 anchors.bottom: parent.bottom
494 dragAreaWidth: shell.edgeSize
495 available: edgeDemo.launcherEnabled && (!greeter.locked || AccountsService.enableLauncherWhileLocked) && !greeter.hasLockedApp
496 inverted: usageModeSettings.usageMode === "Staged"
498 onShowDashHome: showHome()
500 onDashSwipeChanged: {
502 dash.setCurrentScope(0, false, true)
505 onLauncherApplicationSelected: {
506 if (!edgeDemo.running) {
507 greeter.notifyAboutToFocusApp(appId);
508 shell.activateApplication(appId)
513 panel.indicators.hide()
521 background: shell.background
525 id: modalNotificationBackground
527 visible: notifications.useModal && (notifications.state == "narrow")
540 model: NotificationBackend.Model
543 y: topmostIsFullscreen ? 0 : panel.panelHeight
544 height: parent.height - (topmostIsFullscreen ? 0 : panel.panelHeight)
549 when: overlay.width <= units.gu(60)
551 target: notifications
552 anchors.left: parent.left
553 anchors.right: parent.right
558 when: overlay.width > units.gu(60)
560 target: notifications
561 anchors.left: undefined
562 anchors.right: parent.right
564 PropertyChanges { target: notifications; width: units.gu(38) }
575 shutdownFadeOutRectangle.enabled = true;
576 shutdownFadeOutRectangle.visible = true;
577 shutdownFadeOut.start();
583 objectName: "edgeDemo"
585 paused: Powerd.status === Powerd.Off || wizard.active // Saves power
593 target: SessionBroadcast
594 onShowHome: showHome()
598 id: shutdownFadeOutRectangle
605 NumberAnimation on opacity {
610 if (shutdownFadeOutRectangle.enabled && shutdownFadeOutRectangle.visible) {
611 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