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.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
28import GlobalShortcut 1.0 // has to be before Utils, because of WindowKeysFilter
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
50 // to be set from outside
51 property int orientationAngle: 0
52 property int orientation
53 property int primaryOrientation
54 property int nativeOrientation
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 function updateFocusedAppOrientation() {
62 applicationsDisplayLoader.item.updateFocusedAppOrientation();
64 function updateFocusedAppOrientationAnimated() {
65 applicationsDisplayLoader.item.updateFocusedAppOrientationAnimated();
67 property bool hasMouse: false
69 // to be read from outside
70 readonly property int mainAppWindowOrientationAngle:
71 applicationsDisplayLoader.item ? applicationsDisplayLoader.item.mainAppWindowOrientationAngle : 0
73 readonly property bool orientationChangesEnabled: panel.indicators.fullyClosed
74 && (applicationsDisplayLoader.item && applicationsDisplayLoader.item.orientationChangesEnabled)
75 && (!greeter || !greeter.animating)
77 readonly property bool showingGreeter: greeter && greeter.shown
79 property bool startingUp: true
80 Timer { id: finishStartUpTimer; interval: 500; onTriggered: startingUp = false }
82 property int supportedOrientations: {
84 // Ensure we don't rotate during start up
85 return Qt.PrimaryOrientation;
86 } else if (greeter && greeter.shown) {
87 return Qt.PrimaryOrientation;
89 return mainApp.supportedOrientations;
92 return Qt.PortraitOrientation
93 | Qt.LandscapeOrientation
94 | Qt.InvertedPortraitOrientation
95 | Qt.InvertedLandscapeOrientation;
99 // For autopilot consumption
100 readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId
102 // internal props from here onwards
103 readonly property var mainApp:
104 applicationsDisplayLoader.item ? applicationsDisplayLoader.item.mainApp : null
106 // Disable everything while greeter is waiting, so that the user can't swipe
107 // the greeter or launcher until we know whether the session is locked.
108 enabled: greeter && !greeter.waiting
110 property real edgeSize: units.gu(2)
111 property url defaultBackground: Qt.resolvedUrl(shell.width >= units.gu(60) ? "graphics/tablet_background.jpg" : "graphics/phone_background.jpg")
112 property url background: asImageTester.status == Image.Ready ? asImageTester.source
113 : gsImageTester.status == Image.Ready ? gsImageTester.source : defaultBackground
115 readonly property alias greeter: greeterLoader.item
117 function activateApplication(appId) {
118 if (ApplicationManager.findApplication(appId)) {
119 ApplicationManager.requestFocusApplication(appId);
121 var execFlags = shell.usageScenario === "phone" ? ApplicationManager.ForceMainStage
122 : ApplicationManager.NoFlag;
123 ApplicationManager.startApplication(appId, execFlags);
127 function startLockedApp(app) {
128 if (greeter.locked) {
129 greeter.lockedApp = app;
131 shell.activateApplication(app);
134 // This is a dummy image to detect if the custom AS set wallpaper loads successfully.
137 source: AccountsService.backgroundFile != undefined && AccountsService.backgroundFile.length > 0 ? AccountsService.backgroundFile : ""
145 id: backgroundSettings
146 schema.id: "org.gnome.desktop.background"
149 // This is a dummy image to detect if the custom GSettings set wallpaper loads successfully.
152 source: backgroundSettings.pictureUri && backgroundSettings.pictureUri.length > 0 ? backgroundSettings.pictureUri : ""
160 target: LauncherModel
161 property: "applicationManager"
162 value: ApplicationManager
165 Component.onCompleted: {
166 Theme.name = "Ubuntu.Components.Themes.SuruGradient"
167 if (ApplicationManager.count > 0) {
168 ApplicationManager.focusApplication(ApplicationManager.get(0).appId);
170 finishStartUpTimer.start();
173 LightDM{id: lightDM} // Provide backend access
176 indicators: panel.indicators
181 objectName: "dashCommunicator"
185 id: physicalKeysMapper
186 objectName: "physicalKeysMapper"
188 onPowerKeyLongPressed: dialogs.showPowerDialog();
189 onVolumeDownTriggered: volumeControl.volumeDown();
190 onVolumeUpTriggered: volumeControl.volumeUp();
191 onScreenshotTriggered: screenGrabber.capture();
195 // dummy shortcut to force creation of GlobalShortcutRegistry before WindowKeyFilter
199 Keys.onPressed: physicalKeysMapper.onKeyPressed(event);
200 Keys.onReleased: physicalKeysMapper.onKeyReleased(event);
204 onActivated: { launcher.fadeOut(); shell.showHome(); }
211 height: parent.height
214 target: ApplicationManager
216 // This signal is also fired when we try to focus the current app
217 // again. We rely on this!
218 onFocusedApplicationIdChanged: {
219 var appId = ApplicationManager.focusedApplicationId;
221 if (tutorial.running && appId != "" && appId != "unity8-dash") {
222 // If this happens on first boot, we may be in edge
223 // tutorial or wizard while receiving a call. But a call
224 // is more important than wizard so just bail out of those.
229 if (appId === "dialer-app" && callManager.hasCalls && greeter.locked) {
230 // If we are in the middle of a call, make dialer lockedApp and show it.
231 // This can happen if user backs out of dialer back to greeter, then
232 // launches dialer again.
233 greeter.lockedApp = appId;
235 greeter.notifyAppFocused(appId);
237 panel.indicators.hide();
240 onApplicationAdded: {
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
259 property string usageScenario: shell.usageScenario === "phone" || greeter.hasLockedApp
261 : shell.usageScenario
263 if(shell.mode === "greeter") {
264 return "Stages/ShimStage.qml"
265 } else if (applicationsDisplayLoader.usageScenario === "phone") {
266 return "Stages/PhoneStage.qml";
267 } else if (applicationsDisplayLoader.usageScenario === "tablet") {
268 return "Stages/TabletStage.qml";
270 return "Stages/DesktopStage.qml";
274 property bool interactive: tutorial.spreadEnabled
275 && (!greeter || !greeter.shown)
276 && panel.indicators.fullyClosed
277 && launcher.progress == 0
278 && !notifications.useModal
280 onInteractiveChanged: { if (interactive) { focus = true; } }
283 target: applicationsDisplayLoader.item
284 property: "objectName"
288 target: applicationsDisplayLoader.item
289 property: "dragAreaWidth"
290 value: shell.edgeSize
293 target: applicationsDisplayLoader.item
294 property: "maximizedAppTopMargin"
295 // Not just using panel.panelHeight as that changes depending on the focused app.
296 value: panel.indicators.minimizedPanelHeight + units.dp(2) // dp(2) for orange line
299 target: applicationsDisplayLoader.item
300 property: "interactive"
301 value: applicationsDisplayLoader.interactive
304 target: applicationsDisplayLoader.item
305 property: "spreadEnabled"
306 value: tutorial.spreadEnabled && (!greeter || (!greeter.hasLockedApp && !greeter.shown))
309 target: applicationsDisplayLoader.item
310 property: "inverseProgress"
311 value: greeter && greeter.locked ? 0 : launcher.progress
314 target: applicationsDisplayLoader.item
315 property: "shellOrientationAngle"
316 value: shell.orientationAngle
319 target: applicationsDisplayLoader.item
320 property: "shellOrientation"
321 value: shell.orientation
324 target: applicationsDisplayLoader.item
325 property: "background"
326 value: shell.background
329 target: applicationsDisplayLoader.item
330 property: "shellPrimaryOrientation"
331 value: shell.primaryOrientation
334 target: applicationsDisplayLoader.item
335 property: "nativeOrientation"
336 value: shell.nativeOrientation
339 target: applicationsDisplayLoader.item
340 property: "nativeWidth"
341 value: shell.nativeWidth
344 target: applicationsDisplayLoader.item
345 property: "nativeHeight"
346 value: shell.nativeHeight
349 target: applicationsDisplayLoader.item
350 property: "beingResized"
351 value: shell.beingResized
354 target: applicationsDisplayLoader.item
355 property: "keepDashRunning"
356 value: launcher.shown || launcher.dashSwipe
359 target: applicationsDisplayLoader.item
360 property: "suspended"
364 target: applicationsDisplayLoader.item
365 property: "altTabPressed"
366 value: physicalKeysMapper.altTabPressed
372 objectName: "tutorial"
375 // EdgeDragAreas don't work with mice. So to avoid trapping the user,
376 // we skip the tutorial on the Desktop to avoid using them. The
377 // Desktop doesn't use the same spread design anyway. The tutorial is
378 // all a bit of a placeholder on non-phone form factors right now.
379 // When the design team gives us more guidance, we can do something
381 active: usageScenario != "desktop" && AccountsService.demoEdges
383 paused: lightDM.greeter.active
386 edgeSize: shell.edgeSize
389 AccountsService.demoEdges = false;
390 active = false; // for immediate response / if AS is having problems
397 objectName: "inputMethod"
398 anchors { fill: parent; topMargin: panel.panelHeight }
399 z: notifications.useModal || panel.indicators.shown || wizard.active ? overlay.z + 1 : overlay.z - 1
403 target: SessionManager
405 if (!session.parentSession && !session.application) {
406 // nothing is using it. delete it right away
415 anchors.topMargin: panel.panelHeight
416 sourceComponent: shell.mode != "shell" ? integratedGreeter :
417 Qt.createComponent(Qt.resolvedUrl("Greeter/ShimGreeter.qml"));
419 item.objectName = "greeter"
424 id: integratedGreeter
427 hides: [launcher, panel.indicators]
428 tabletMode: shell.usageScenario != "phone"
429 launcherOffset: launcher.progress
430 forcedUnlock: tutorial.running
431 background: shell.background
433 // avoid overlapping with Launcher's edge drag area
434 // FIXME: Fix TouchRegistry & friends and remove this workaround
435 // Issue involves launcher's DDA getting disabled on a long
437 dragHandleLeftMargin: launcher.available ? launcher.dragAreaWidth + 1 : 0
444 if (!tutorial.running) {
449 onEmergencyCall: startLockedApp("dialer-app")
454 // See powerConnection for why this is useful
455 id: showGreeterDelayed
467 if (greeter.locked && callManager.hasCalls && greeter.lockedApp !== "dialer-app") {
468 // We just received an incoming call while locked. The
469 // indicator will have already launched dialer-app for us, but
470 // there is a race between "hasCalls" changing and the dialer
471 // starting up. So in case we lose that race, we'll start/
472 // focus the dialer ourselves here too. Even if the indicator
473 // didn't launch the dialer for some reason (or maybe a call
474 // started via some other means), if an active call is
475 // happening, we want to be in the dialer.
476 startLockedApp("dialer-app")
486 if (Powerd.status === Powerd.Off && reason !== Powerd.Proximity &&
487 !callManager.hasCalls && !tutorial.running) {
488 // We don't want to simply call greeter.showNow() here, because
489 // that will take too long. Qt will delay button event
490 // handling until the greeter is done loading and may think the
491 // user held down the power button the whole time, leading to a
492 // power dialog being shown. Instead, delay showing the
493 // greeter until we've finished handling the event. We could
494 // make the greeter load asynchronously instead, but that
495 // introduces a whole host of timing issues, especially with
496 // its animations. So this is simpler.
497 showGreeterDelayed.start();
502 function showHome() {
503 if (tutorial.running) {
507 greeter.notifyAboutToFocusApp("unity8-dash");
509 var animate = !lightDM.greeter.active && !stages.shown
510 dash.setCurrentScope(0, animate, false)
511 ApplicationManager.requestFocusApplication("unity8-dash")
514 function showDash() {
515 if (greeter.notifyShowingDashFromDrag()) {
519 if (!greeter.locked && ApplicationManager.focusedApplicationId != "unity8-dash") {
520 ApplicationManager.requestFocusApplication("unity8-dash")
534 anchors.fill: parent //because this draws indicator menus
537 available: tutorial.panelEnabled
538 && ((!greeter || !greeter.locked) || AccountsService.enableIndicatorsWhileLocked)
539 && (!greeter || !greeter.hasLockedApp)
540 contentEnabled: tutorial.panelContentEnabled
541 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
543 minimizedPanelHeight: units.gu(3)
544 expandedPanelHeight: units.gu(7)
546 indicatorsModel: Indicators.IndicatorsModel {
547 // tablet and phone both use the same profile
548 profile: shell.usageScenario === "desktop" ? "desktop" : "phone"
549 Component.onCompleted: load();
554 greeterShown: greeter.shown
557 property bool topmostApplicationIsFullscreen:
558 ApplicationManager.focusedApplicationId &&
559 ApplicationManager.findApplication(ApplicationManager.focusedApplicationId).fullscreen
561 fullscreenMode: (topmostApplicationIsFullscreen && !lightDM.greeter.active && launcher.progress == 0)
562 || greeter.hasLockedApp
567 objectName: "launcher"
569 readonly property bool dashSwipe: progress > 0
571 anchors.top: parent.top
572 anchors.topMargin: inverted ? 0 : panel.panelHeight
573 anchors.bottom: parent.bottom
575 dragAreaWidth: shell.edgeSize
576 available: tutorial.launcherEnabled
577 && (!greeter.locked || AccountsService.enableLauncherWhileLocked)
578 && !greeter.hasLockedApp
579 inverted: shell.usageScenario !== "desktop"
580 shadeBackground: !tutorial.running
582 onShowDashHome: showHome()
584 onDashSwipeChanged: {
586 dash.setCurrentScope(0, false, true)
589 onLauncherApplicationSelected: {
590 if (!tutorial.running) {
591 greeter.notifyAboutToFocusApp(appId);
592 shell.activateApplication(appId)
597 panel.indicators.hide()
606 background: shell.background
608 function unlockWhenDoneWithWizard() {
610 Connectivity.unlockAllModems();
614 Component.onCompleted: unlockWhenDoneWithWizard()
615 onActiveChanged: unlockWhenDoneWithWizard()
619 id: modalNotificationBackground
621 visible: notifications.useModal
634 model: NotificationBackend.Model
636 hasMouse: shell.hasMouse
638 y: topmostIsFullscreen ? 0 : panel.panelHeight
639 height: parent.height - (topmostIsFullscreen ? 0 : panel.panelHeight)
644 when: overlay.width <= units.gu(60)
646 target: notifications
647 anchors.left: parent.left
648 anchors.right: parent.right
653 when: overlay.width > units.gu(60)
655 target: notifications
656 anchors.left: undefined
657 anchors.right: parent.right
659 PropertyChanges { target: notifications; width: units.gu(38) }
667 objectName: "dialogs"
670 usageScenario: shell.usageScenario
672 shutdownFadeOutRectangle.enabled = true;
673 shutdownFadeOutRectangle.visible = true;
674 shutdownFadeOut.start();
679 target: SessionBroadcast
680 onShowHome: showHome()
690 visible: shell.hasMouse
691 z: screenGrabber.z + 1
695 id: shutdownFadeOutRectangle
702 NumberAnimation on opacity {
707 if (shutdownFadeOutRectangle.enabled && shutdownFadeOutRectangle.visible) {
708 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