2 * Copyright (C) 2013-2016 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
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
45import WindowManager 0.1
51 // to be set from outside
52 property int orientationAngle: 0
53 property int orientation
54 property Orientations orientations
55 property real nativeWidth
56 property real nativeHeight
57 property alias indicatorAreaShowProgress: panel.indicatorAreaShowProgress
58 property bool beingResized
59 property string usageScenario: "phone" // supported values: "phone", "tablet" or "desktop"
60 property string mode: "full-greeter"
61 property alias oskEnabled: inputMethod.enabled
62 function updateFocusedAppOrientation() {
63 applicationsDisplayLoader.item.updateFocusedAppOrientation();
65 function updateFocusedAppOrientationAnimated() {
66 applicationsDisplayLoader.item.updateFocusedAppOrientationAnimated();
68 property bool hasMouse: false
70 // to be read from outside
71 readonly property int mainAppWindowOrientationAngle:
72 applicationsDisplayLoader.item ? applicationsDisplayLoader.item.mainAppWindowOrientationAngle : 0
74 readonly property bool orientationChangesEnabled: panel.indicators.fullyClosed
75 && (applicationsDisplayLoader.item && applicationsDisplayLoader.item.orientationChangesEnabled)
76 && (!greeter || !greeter.animating)
78 readonly property bool showingGreeter: greeter && greeter.shown
80 property bool startingUp: true
81 Timer { id: finishStartUpTimer; interval: 500; onTriggered: startingUp = false }
83 property int supportedOrientations: {
85 // Ensure we don't rotate during start up
86 return Qt.PrimaryOrientation;
87 } else if (greeter && greeter.shown) {
88 return Qt.PrimaryOrientation;
89 } else if (applicationsDisplayLoader.item) {
90 return shell.orientations.map(applicationsDisplayLoader.item.supportedOrientations);
93 return Qt.PortraitOrientation
94 | Qt.LandscapeOrientation
95 | Qt.InvertedPortraitOrientation
96 | Qt.InvertedLandscapeOrientation;
100 readonly property var mainApp:
101 applicationsDisplayLoader.item ? applicationsDisplayLoader.item.mainApp : null
104 _onMainAppChanged(mainApp.appId);
108 target: ApplicationManager
110 if (shell.mainApp && shell.mainApp.appId === appId) {
111 _onMainAppChanged(appId);
115 function _onMainAppChanged(appId) {
116 if (wizard.active && appId != "" && appId != "unity8-dash") {
117 // If this happens on first boot, we may be in edge
118 // tutorial or wizard while receiving a call. But a call
119 // is more important than wizard so just bail out of those.
124 if (appId === "dialer-app" && callManager.hasCalls && greeter.locked) {
125 // If we are in the middle of a call, make dialer lockedApp and show it.
126 // This can happen if user backs out of dialer back to greeter, then
127 // launches dialer again.
128 greeter.lockedApp = appId;
130 greeter.notifyAppFocusRequested(appId);
132 panel.indicators.hide();
136 // For autopilot consumption
137 readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId
139 // Disable everything while greeter is waiting, so that the user can't swipe
140 // the greeter or launcher until we know whether the session is locked.
141 enabled: greeter && !greeter.waiting
143 property real edgeSize: units.gu(settings.edgeDragWidth)
146 id: wallpaperResolver
150 readonly property alias greeter: greeterLoader.item
152 function activateApplication(appId) {
153 if (ApplicationManager.findApplication(appId)) {
154 ApplicationManager.requestFocusApplication(appId);
156 ApplicationManager.startApplication(appId);
160 function startLockedApp(app) {
161 if (greeter.locked) {
162 greeter.lockedApp = app;
164 shell.activateApplication(app);
168 target: LauncherModel
169 property: "applicationManager"
170 value: ApplicationManager
173 Component.onCompleted: {
174 theme.name = "Ubuntu.Components.Themes.SuruDark"
175 finishStartUpTimer.start();
178 LightDM{id: lightDM} // Provide backend access
181 indicators: panel.indicators
186 objectName: "dashCommunicator"
190 id: physicalKeysMapper
191 objectName: "physicalKeysMapper"
193 onPowerKeyLongPressed: dialogs.showPowerDialog();
194 onVolumeDownTriggered: volumeControl.volumeDown();
195 onVolumeUpTriggered: volumeControl.volumeUp();
196 onScreenshotTriggered: screenGrabber.capture();
200 // dummy shortcut to force creation of GlobalShortcutRegistry before WindowInputFilter
205 Keys.onPressed: physicalKeysMapper.onKeyPressed(event, lastInputTimestamp);
206 Keys.onReleased: physicalKeysMapper.onKeyReleased(event, lastInputTimestamp);
210 onHomeKeyActivated: { launcher.fadeOut(); shell.showHome(); }
211 onTouchBegun: { cursor.opacity = 0; }
213 // move the (hidden) cursor to the last known touch position
214 var mappedCoords = mapFromItem(null, pos.x, pos.y);
215 cursor.x = mappedCoords.x;
216 cursor.y = mappedCoords.y;
222 schema.id: "com.canonical.Unity8"
229 height: parent.height
231 TopLevelSurfaceList {
232 id: topLevelSurfaceList
233 objectName: "topLevelSurfaceList"
234 applicationsModel: ApplicationManager
238 id: applicationsDisplayLoader
239 objectName: "applicationsDisplayLoader"
242 // When we have a locked app, we only want to show that one app.
243 // FIXME: do this in a less traumatic way. We currently only allow
244 // locked apps in phone mode (see FIXME in Lockscreen component in
245 // this same file). When that changes, we need to do something
246 // nicer here. But this code is currently just to prevent a
247 // theoretical attack where user enters lockedApp mode, then makes
248 // the screen larger (maybe connects to monitor) and tries to enter
251 property string usageScenario: shell.usageScenario === "phone" || greeter.hasLockedApp
253 : shell.usageScenario
254 readonly property string qmlComponent: {
255 if(shell.mode === "greeter") {
256 return "Stages/ShimStage.qml"
257 } else if (applicationsDisplayLoader.usageScenario === "phone") {
258 return "Stages/PhoneStage.qml";
259 } else if (applicationsDisplayLoader.usageScenario === "tablet") {
260 return "Stages/TabletStage.qml";
262 return "Stages/DesktopStage.qml";
265 // TODO: Ensure the current stage is destroyed before the new one gets loaded.
266 // Currently the new one will get loaded while the old is still hanging
267 // around for a bit, which might lead to conflicts where both stages
268 // change the model simultaneously.
269 onQmlComponentChanged: {
270 if (item) item.stageAboutToBeUnloaded();
271 source = qmlComponent;
274 property bool interactive: (!greeter || !greeter.shown)
275 && panel.indicators.fullyClosed
276 && launcher.progress == 0
277 && !notifications.useModal
279 onInteractiveChanged: { if (interactive) { focus = true; } }
282 target: applicationsDisplayLoader.item
287 target: applicationsDisplayLoader.item
288 property: "objectName"
292 target: applicationsDisplayLoader.item
293 property: "dragAreaWidth"
294 value: shell.edgeSize
297 target: applicationsDisplayLoader.item
298 property: "maximizedAppTopMargin"
299 // Not just using panel.panelHeight as that changes depending on the focused app.
300 value: panel.indicators.minimizedPanelHeight
303 target: applicationsDisplayLoader.item
304 property: "interactive"
305 value: applicationsDisplayLoader.interactive
308 target: applicationsDisplayLoader.item
309 property: "spreadEnabled"
310 value: tutorial.spreadEnabled && (!greeter || (!greeter.hasLockedApp && !greeter.shown))
313 target: applicationsDisplayLoader.item
314 property: "inverseProgress"
315 value: greeter && greeter.locked ? 0 : launcher.progress
318 target: applicationsDisplayLoader.item
319 property: "shellOrientationAngle"
320 value: shell.orientationAngle
323 target: applicationsDisplayLoader.item
324 property: "shellOrientation"
325 value: shell.orientation
328 target: applicationsDisplayLoader.item
329 property: "orientations"
330 value: shell.orientations
333 target: applicationsDisplayLoader.item
334 property: "background"
335 value: wallpaperResolver.background
338 target: applicationsDisplayLoader.item
339 property: "nativeWidth"
340 value: shell.nativeWidth
343 target: applicationsDisplayLoader.item
344 property: "nativeHeight"
345 value: shell.nativeHeight
348 target: applicationsDisplayLoader.item
349 property: "beingResized"
350 value: shell.beingResized
353 target: applicationsDisplayLoader.item
354 property: "keepDashRunning"
355 value: launcher.shown || launcher.dashSwipe
358 target: applicationsDisplayLoader.item
359 property: "suspended"
363 target: applicationsDisplayLoader.item
364 property: "altTabPressed"
365 value: physicalKeysMapper.altTabPressed
368 target: applicationsDisplayLoader.item
369 property: "leftMargin"
370 value: shell.usageScenario == "desktop" && !settings.autohideLauncher ? launcher.panelWidth: 0
373 target: applicationsDisplayLoader.item
374 property: "applicationManager"
375 value: ApplicationManager
378 target: applicationsDisplayLoader.item
379 property: "topLevelSurfaceList"
380 value: topLevelSurfaceList
387 objectName: "inputMethod"
390 topMargin: panel.panelHeight
391 leftMargin: launcher.lockedVisible ? launcher.panelWidth : 0
393 z: notifications.useModal || panel.indicators.shown || wizard.active || tutorial.running ? overlay.z + 1 : overlay.z - 1
399 anchors.topMargin: panel.panelHeight
400 sourceComponent: shell.mode != "shell" ? integratedGreeter :
401 Qt.createComponent(Qt.resolvedUrl("Greeter/ShimGreeter.qml"));
403 item.objectName = "greeter"
408 id: integratedGreeter
411 hides: [launcher, panel.indicators]
412 tabletMode: shell.usageScenario != "phone"
413 launcherOffset: launcher.progress
414 forcedUnlock: wizard.active
415 background: wallpaperResolver.background
417 // avoid overlapping with Launcher's edge drag area
418 // FIXME: Fix TouchRegistry & friends and remove this workaround
419 // Issue involves launcher's DDA getting disabled on a long
421 dragHandleLeftMargin: launcher.available ? launcher.dragAreaWidth + 1 : 0
428 if (!tutorial.running) {
433 onEmergencyCall: startLockedApp("dialer-app")
438 // See powerConnection for why this is useful
439 id: showGreeterDelayed
451 if (greeter.locked && callManager.hasCalls && greeter.lockedApp !== "dialer-app") {
452 // We just received an incoming call while locked. The
453 // indicator will have already launched dialer-app for us, but
454 // there is a race between "hasCalls" changing and the dialer
455 // starting up. So in case we lose that race, we'll start/
456 // focus the dialer ourselves here too. Even if the indicator
457 // didn't launch the dialer for some reason (or maybe a call
458 // started via some other means), if an active call is
459 // happening, we want to be in the dialer.
460 startLockedApp("dialer-app")
470 if (Powerd.status === Powerd.Off && reason !== Powerd.Proximity &&
471 !callManager.hasCalls && !wizard.active) {
472 // We don't want to simply call greeter.showNow() here, because
473 // that will take too long. Qt will delay button event
474 // handling until the greeter is done loading and may think the
475 // user held down the power button the whole time, leading to a
476 // power dialog being shown. Instead, delay showing the
477 // greeter until we've finished handling the event. We could
478 // make the greeter load asynchronously instead, but that
479 // introduces a whole host of timing issues, especially with
480 // its animations. So this is simpler.
481 showGreeterDelayed.start();
486 function showHome() {
487 greeter.notifyUserRequestedApp("unity8-dash");
489 var animate = !lightDM.greeter.active && !stages.shown
490 dash.setCurrentScope(0, animate, false)
491 ApplicationManager.requestFocusApplication("unity8-dash")
494 function showDash() {
495 if (greeter.notifyShowingDashFromDrag()) {
499 if (!greeter.locked && ApplicationManager.focusedApplicationId != "unity8-dash") {
500 ApplicationManager.requestFocusApplication("unity8-dash")
514 anchors.fill: parent //because this draws indicator menus
517 available: tutorial.panelEnabled
518 && ((!greeter || !greeter.locked) || AccountsService.enableIndicatorsWhileLocked)
519 && (!greeter || !greeter.hasLockedApp)
520 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
522 minimizedPanelHeight: units.gu(3)
523 expandedPanelHeight: units.gu(7)
525 indicatorsModel: Indicators.IndicatorsModel {
526 // tablet and phone both use the same profile
528 Component.onCompleted: load();
533 greeterShown: greeter.shown
536 readonly property bool focusedSurfaceIsFullscreen: MirFocusController.focusedSurface
537 ? MirFocusController.focusedSurface.state === Mir.FullscreenState
539 fullscreenMode: (focusedSurfaceIsFullscreen && !lightDM.greeter.active && launcher.progress == 0)
540 || greeter.hasLockedApp
541 locked: greeter && greeter.active
546 objectName: "launcher"
548 readonly property bool dashSwipe: progress > 0
550 anchors.top: parent.top
551 anchors.topMargin: inverted ? 0 : panel.panelHeight
552 anchors.bottom: parent.bottom
554 dragAreaWidth: shell.edgeSize
555 available: tutorial.launcherEnabled
556 && (!greeter.locked || AccountsService.enableLauncherWhileLocked)
557 && !greeter.hasLockedApp
558 inverted: shell.usageScenario !== "desktop"
559 superPressed: physicalKeysMapper.superPressed
560 superTabPressed: physicalKeysMapper.superTabPressed
561 panelWidth: units.gu(settings.launcherWidth)
562 lockedVisible: shell.usageScenario == "desktop" && !settings.autohideLauncher && !panel.fullscreenMode
564 onShowDashHome: showHome()
566 onDashSwipeChanged: {
568 dash.setCurrentScope(0, false, true)
571 onLauncherApplicationSelected: {
572 greeter.notifyUserRequestedApp(appId);
573 shell.activateApplication(appId);
577 panel.indicators.hide()
582 applicationsDisplayLoader.focus = true;
587 shortcut: Qt.AltModifier | Qt.Key_F1
589 launcher.openForKeyboardNavigation();
593 shortcut: Qt.MetaModifier | Qt.Key_0
595 if (LauncherModel.get(9)) {
596 activateApplication(LauncherModel.get(9).appId);
603 shortcut: Qt.MetaModifier | (Qt.Key_1 + index)
605 if (LauncherModel.get(index)) {
606 activateApplication(LauncherModel.get(index).appId);
615 objectName: "tutorial"
618 paused: callManager.hasCalls || greeter.shown
619 keyboardVisible: inputMethod.state === "shown"
620 usageScenario: shell.usageScenario
621 lastInputTimestamp: inputFilter.lastInputTimestamp
624 stage: applicationsDisplayLoader.item
632 function unlockWhenDoneWithWizard() {
634 Connectivity.unlockAllModems();
638 Component.onCompleted: unlockWhenDoneWithWizard()
639 onActiveChanged: unlockWhenDoneWithWizard()
642 MouseArea { // modal notifications prevent interacting with other contents
644 visible: notifications.useModal
651 model: NotificationBackend.Model
653 hasMouse: shell.hasMouse
654 background: wallpaperResolver.background
656 y: topmostIsFullscreen ? 0 : panel.panelHeight
657 height: parent.height - (topmostIsFullscreen ? 0 : panel.panelHeight)
662 when: overlay.width <= units.gu(60)
664 target: notifications
665 anchors.left: parent.left
666 anchors.right: parent.right
671 when: overlay.width > units.gu(60)
673 target: notifications
674 anchors.left: undefined
675 anchors.right: parent.right
677 PropertyChanges { target: notifications; width: units.gu(38) }
685 objectName: "dialogs"
688 usageScenario: shell.usageScenario
690 shutdownFadeOutRectangle.enabled = true;
691 shutdownFadeOutRectangle.visible = true;
692 shutdownFadeOut.start();
697 target: SessionBroadcast
698 onShowHome: showHome()
703 rotationAngle: -shell.orientationAngle
709 visible: shell.hasMouse
710 z: screenGrabber.z + 1
712 onPushedLeftBoundary: {
713 if (buttons === Qt.NoButton) {
714 launcher.pushEdge(amount);
718 onPushedRightBoundary: {
719 if (buttons === Qt.NoButton && applicationsDisplayLoader.item
720 && applicationsDisplayLoader.item.pushRightEdge) {
721 applicationsDisplayLoader.item.pushRightEdge(amount);
725 onMouseMoved: { cursor.opacity = 1; }
732 id: shutdownFadeOutRectangle
739 NumberAnimation on opacity {
744 if (shutdownFadeOutRectangle.enabled && shutdownFadeOutRectangle.visible) {
745 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