2 * Copyright (C) 2013-2015 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.2
19import AccountsService 0.1
20import Unity.Application 0.1
21import Ubuntu.Components 1.3
22import Ubuntu.Components.Popups 1.3
23import Ubuntu.Gestures 0.1
24import Ubuntu.Telephony 0.1 as Telephony
25import Unity.Connectivity 0.1
26import Unity.Launcher 0.1
27import GlobalShortcut 1.0 // has to be before Utils, because of WindowInputFilter
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
49 // to be set from outside
50 property int orientationAngle: 0
51 property int orientation
52 property Orientations orientations
53 property real nativeWidth
54 property real nativeHeight
55 property alias indicatorAreaShowProgress: panel.indicatorAreaShowProgress
56 property bool beingResized
57 property string usageScenario: "phone" // supported values: "phone", "tablet" or "desktop"
58 property string mode: "full-greeter"
59 property bool cursorVisible: false
60 function updateFocusedAppOrientation() {
61 applicationsDisplayLoader.item.updateFocusedAppOrientation();
63 function updateFocusedAppOrientationAnimated() {
64 applicationsDisplayLoader.item.updateFocusedAppOrientationAnimated();
66 property bool hasMouse: false
68 // to be read from outside
69 readonly property int mainAppWindowOrientationAngle:
70 applicationsDisplayLoader.item ? applicationsDisplayLoader.item.mainAppWindowOrientationAngle : 0
72 readonly property bool orientationChangesEnabled: panel.indicators.fullyClosed
73 && (applicationsDisplayLoader.item && applicationsDisplayLoader.item.orientationChangesEnabled)
74 && (!greeter || !greeter.animating)
76 readonly property bool showingGreeter: greeter && greeter.shown
78 property bool startingUp: true
79 Timer { id: finishStartUpTimer; interval: 500; onTriggered: startingUp = false }
81 property int supportedOrientations: {
83 // Ensure we don't rotate during start up
84 return Qt.PrimaryOrientation;
85 } else if (greeter && greeter.shown) {
86 return Qt.PrimaryOrientation;
88 return shell.orientations.map(mainApp.supportedOrientations);
91 return Qt.PortraitOrientation
92 | Qt.LandscapeOrientation
93 | Qt.InvertedPortraitOrientation
94 | Qt.InvertedLandscapeOrientation;
98 // For autopilot consumption
99 readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId
101 // internal props from here onwards
102 readonly property var mainApp:
103 applicationsDisplayLoader.item ? applicationsDisplayLoader.item.mainApp : null
105 // Disable everything while greeter is waiting, so that the user can't swipe
106 // the greeter or launcher until we know whether the session is locked.
107 enabled: greeter && !greeter.waiting
109 property real edgeSize: units.gu(2)
112 id: wallpaperResolver
116 readonly property alias greeter: greeterLoader.item
118 function activateApplication(appId) {
119 if (ApplicationManager.findApplication(appId)) {
120 ApplicationManager.requestFocusApplication(appId);
122 var execFlags = shell.usageScenario === "phone" ? ApplicationManager.ForceMainStage
123 : ApplicationManager.NoFlag;
124 ApplicationManager.startApplication(appId, execFlags);
128 function startLockedApp(app) {
129 if (greeter.locked) {
130 greeter.lockedApp = app;
132 shell.activateApplication(app);
136 target: LauncherModel
137 property: "applicationManager"
138 value: ApplicationManager
141 Component.onCompleted: {
142 theme.name = "Ubuntu.Components.Themes.SuruGradient"
143 if (ApplicationManager.count > 0) {
144 ApplicationManager.focusApplication(ApplicationManager.get(0).appId);
146 finishStartUpTimer.start();
149 LightDM{id: lightDM} // Provide backend access
152 indicators: panel.indicators
157 objectName: "dashCommunicator"
161 id: physicalKeysMapper
162 objectName: "physicalKeysMapper"
164 onPowerKeyLongPressed: dialogs.showPowerDialog();
165 onVolumeDownTriggered: volumeControl.volumeDown();
166 onVolumeUpTriggered: volumeControl.volumeUp();
167 onScreenshotTriggered: screenGrabber.capture();
171 // dummy shortcut to force creation of GlobalShortcutRegistry before WindowKeyFilter
176 Keys.onPressed: physicalKeysMapper.onKeyPressed(event, lastInputTimestamp);
177 Keys.onReleased: physicalKeysMapper.onKeyReleased(event, lastInputTimestamp);
181 onActivated: { launcher.fadeOut(); shell.showHome(); }
188 height: parent.height
191 target: ApplicationManager
193 // This signal is also fired when we try to focus the current app
194 // again. We rely on this!
195 onFocusedApplicationIdChanged: {
196 var appId = ApplicationManager.focusedApplicationId;
198 if (wizard.active && appId != "" && appId != "unity8-dash") {
199 // If this happens on first boot, we may be in edge
200 // tutorial or wizard while receiving a call. But a call
201 // is more important than wizard so just bail out of those.
206 if (appId === "dialer-app" && callManager.hasCalls && greeter.locked) {
207 // If we are in the middle of a call, make dialer lockedApp and show it.
208 // This can happen if user backs out of dialer back to greeter, then
209 // launches dialer again.
210 greeter.lockedApp = appId;
212 greeter.notifyAppFocused(appId);
214 panel.indicators.hide();
217 onApplicationAdded: {
223 id: applicationsDisplayLoader
224 objectName: "applicationsDisplayLoader"
227 // When we have a locked app, we only want to show that one app.
228 // FIXME: do this in a less traumatic way. We currently only allow
229 // locked apps in phone mode (see FIXME in Lockscreen component in
230 // this same file). When that changes, we need to do something
231 // nicer here. But this code is currently just to prevent a
232 // theoretical attack where user enters lockedApp mode, then makes
233 // the screen larger (maybe connects to monitor) and tries to enter
236 property string usageScenario: shell.usageScenario === "phone" || greeter.hasLockedApp
238 : shell.usageScenario
240 if(shell.mode === "greeter") {
241 return "Stages/ShimStage.qml"
242 } else if (applicationsDisplayLoader.usageScenario === "phone") {
243 return "Stages/PhoneStage.qml";
244 } else if (applicationsDisplayLoader.usageScenario === "tablet") {
245 return "Stages/TabletStage.qml";
247 return "Stages/DesktopStage.qml";
251 property bool interactive: (!greeter || !greeter.shown)
252 && panel.indicators.fullyClosed
253 && launcher.progress == 0
254 && !notifications.useModal
256 onInteractiveChanged: { if (interactive) { focus = true; } }
259 target: applicationsDisplayLoader.item
260 property: "objectName"
264 target: applicationsDisplayLoader.item
265 property: "dragAreaWidth"
266 value: shell.edgeSize
269 target: applicationsDisplayLoader.item
270 property: "maximizedAppTopMargin"
271 // Not just using panel.panelHeight as that changes depending on the focused app.
272 value: panel.indicators.minimizedPanelHeight + units.dp(2) // dp(2) for orange line
275 target: applicationsDisplayLoader.item
276 property: "interactive"
277 value: applicationsDisplayLoader.interactive
280 target: applicationsDisplayLoader.item
281 property: "spreadEnabled"
282 value: tutorial.spreadEnabled && (!greeter || (!greeter.hasLockedApp && !greeter.shown))
285 target: applicationsDisplayLoader.item
286 property: "inverseProgress"
287 value: greeter && greeter.locked ? 0 : launcher.progress
290 target: applicationsDisplayLoader.item
291 property: "shellOrientationAngle"
292 value: shell.orientationAngle
295 target: applicationsDisplayLoader.item
296 property: "shellOrientation"
297 value: shell.orientation
300 target: applicationsDisplayLoader.item
301 property: "orientations"
302 value: shell.orientations
305 target: applicationsDisplayLoader.item
306 property: "background"
307 value: wallpaperResolver.background
310 target: applicationsDisplayLoader.item
311 property: "nativeWidth"
312 value: shell.nativeWidth
315 target: applicationsDisplayLoader.item
316 property: "nativeHeight"
317 value: shell.nativeHeight
320 target: applicationsDisplayLoader.item
321 property: "beingResized"
322 value: shell.beingResized
325 target: applicationsDisplayLoader.item
326 property: "keepDashRunning"
327 value: launcher.shown || launcher.dashSwipe
330 target: applicationsDisplayLoader.item
331 property: "suspended"
335 target: applicationsDisplayLoader.item
336 property: "altTabPressed"
337 value: physicalKeysMapper.altTabPressed
344 objectName: "inputMethod"
345 anchors { fill: parent; topMargin: panel.panelHeight }
346 z: notifications.useModal || panel.indicators.shown || wizard.active || tutorial.running ? overlay.z + 1 : overlay.z - 1
350 target: SessionManager
352 if (!session.parentSession && !session.application) {
353 // nothing is using it. delete it right away
362 anchors.topMargin: panel.panelHeight
363 sourceComponent: shell.mode != "shell" ? integratedGreeter :
364 Qt.createComponent(Qt.resolvedUrl("Greeter/ShimGreeter.qml"));
366 item.objectName = "greeter"
371 id: integratedGreeter
374 hides: [launcher, panel.indicators]
375 tabletMode: shell.usageScenario != "phone"
376 launcherOffset: launcher.progress
377 forcedUnlock: wizard.active
378 background: wallpaperResolver.background
380 // avoid overlapping with Launcher's edge drag area
381 // FIXME: Fix TouchRegistry & friends and remove this workaround
382 // Issue involves launcher's DDA getting disabled on a long
384 dragHandleLeftMargin: launcher.available ? launcher.dragAreaWidth + 1 : 0
391 if (!tutorial.running) {
396 onEmergencyCall: startLockedApp("dialer-app")
401 // See powerConnection for why this is useful
402 id: showGreeterDelayed
414 if (greeter.locked && callManager.hasCalls && greeter.lockedApp !== "dialer-app") {
415 // We just received an incoming call while locked. The
416 // indicator will have already launched dialer-app for us, but
417 // there is a race between "hasCalls" changing and the dialer
418 // starting up. So in case we lose that race, we'll start/
419 // focus the dialer ourselves here too. Even if the indicator
420 // didn't launch the dialer for some reason (or maybe a call
421 // started via some other means), if an active call is
422 // happening, we want to be in the dialer.
423 startLockedApp("dialer-app")
433 if (Powerd.status === Powerd.Off && reason !== Powerd.Proximity &&
434 !callManager.hasCalls && !wizard.active) {
435 // We don't want to simply call greeter.showNow() here, because
436 // that will take too long. Qt will delay button event
437 // handling until the greeter is done loading and may think the
438 // user held down the power button the whole time, leading to a
439 // power dialog being shown. Instead, delay showing the
440 // greeter until we've finished handling the event. We could
441 // make the greeter load asynchronously instead, but that
442 // introduces a whole host of timing issues, especially with
443 // its animations. So this is simpler.
444 showGreeterDelayed.start();
449 function showHome() {
450 greeter.notifyAboutToFocusApp("unity8-dash");
452 var animate = !lightDM.greeter.active && !stages.shown
453 dash.setCurrentScope(0, animate, false)
454 ApplicationManager.requestFocusApplication("unity8-dash")
457 function showDash() {
458 if (greeter.notifyShowingDashFromDrag()) {
462 if (!greeter.locked && ApplicationManager.focusedApplicationId != "unity8-dash") {
463 ApplicationManager.requestFocusApplication("unity8-dash")
477 anchors.fill: parent //because this draws indicator menus
480 available: tutorial.panelEnabled
481 && ((!greeter || !greeter.locked) || AccountsService.enableIndicatorsWhileLocked)
482 && (!greeter || !greeter.hasLockedApp)
483 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
485 minimizedPanelHeight: units.gu(3)
486 expandedPanelHeight: units.gu(7)
488 indicatorsModel: Indicators.IndicatorsModel {
489 // tablet and phone both use the same profile
490 profile: shell.usageScenario === "desktop" ? "desktop" : "phone"
491 Component.onCompleted: load();
496 greeterShown: greeter.shown
499 property bool topmostApplicationIsFullscreen:
500 ApplicationManager.focusedApplicationId &&
501 ApplicationManager.findApplication(ApplicationManager.focusedApplicationId).fullscreen
503 fullscreenMode: (topmostApplicationIsFullscreen && !lightDM.greeter.active && launcher.progress == 0)
504 || greeter.hasLockedApp
505 locked: greeter && greeter.active
510 objectName: "launcher"
512 readonly property bool dashSwipe: progress > 0
514 anchors.top: parent.top
515 anchors.topMargin: inverted ? 0 : panel.panelHeight
516 anchors.bottom: parent.bottom
518 dragAreaWidth: shell.edgeSize
519 available: tutorial.launcherEnabled
520 && (!greeter.locked || AccountsService.enableLauncherWhileLocked)
521 && !greeter.hasLockedApp
522 inverted: shell.usageScenario !== "desktop"
524 onShowDashHome: showHome()
526 onDashSwipeChanged: {
528 dash.setCurrentScope(0, false, true)
531 onLauncherApplicationSelected: {
532 greeter.notifyAboutToFocusApp(appId);
533 shell.activateApplication(appId);
537 panel.indicators.hide()
544 objectName: "tutorial"
547 paused: callManager.hasCalls || greeter.shown
548 keyboardVisible: inputMethod.state === "shown"
549 usageScenario: shell.usageScenario
550 lastInputTimestamp: inputFilter.lastInputTimestamp
553 stage: applicationsDisplayLoader.item
560 background: wallpaperResolver.background
562 function unlockWhenDoneWithWizard() {
564 Connectivity.unlockAllModems();
568 Component.onCompleted: unlockWhenDoneWithWizard()
569 onActiveChanged: unlockWhenDoneWithWizard()
573 id: modalNotificationBackground
575 visible: notifications.useModal
588 model: NotificationBackend.Model
590 hasMouse: shell.hasMouse
591 background: wallpaperResolver.background
593 y: topmostIsFullscreen ? 0 : panel.panelHeight
594 height: parent.height - (topmostIsFullscreen ? 0 : panel.panelHeight)
599 when: overlay.width <= units.gu(60)
601 target: notifications
602 anchors.left: parent.left
603 anchors.right: parent.right
608 when: overlay.width > units.gu(60)
610 target: notifications
611 anchors.left: undefined
612 anchors.right: parent.right
614 PropertyChanges { target: notifications; width: units.gu(38) }
622 objectName: "dialogs"
625 usageScenario: shell.usageScenario
627 shutdownFadeOutRectangle.enabled = true;
628 shutdownFadeOutRectangle.visible = true;
629 shutdownFadeOut.start();
634 target: SessionBroadcast
635 onShowHome: showHome()
640 rotationAngle: -shell.orientationAngle
646 visible: shell.hasMouse
647 z: screenGrabber.z + 1
651 id: shutdownFadeOutRectangle
658 NumberAnimation on opacity {
663 if (shutdownFadeOutRectangle.enabled && shutdownFadeOutRectangle.visible) {
664 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