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 AccountsService 0.1
20import Unity.Application 0.1
21import Ubuntu.Components 0.1
22import Ubuntu.Components.Popups 1.0
23import Ubuntu.Connectivity 0.1
24import Ubuntu.Gestures 0.1
25import Ubuntu.SystemImage 0.1
26import Unity.Launcher 0.1
28import LightDM 0.1 as LightDM
30import SessionBroadcast 0.1
37import Unity.Notifications 1.0 as NotificationBackend
38import Unity.Session 0.1
39import Unity.DashCommunicator 0.1
44 // this is only here to select the width / height of the window if not running fullscreen
45 property bool tablet: false
46 width: tablet ? units.gu(160) : applicationArguments.hasGeometry() ? applicationArguments.width() : units.gu(40)
47 height: tablet ? units.gu(100) : applicationArguments.hasGeometry() ? applicationArguments.height() : units.gu(71)
49 property real edgeSize: units.gu(2)
50 property url defaultBackground: Qt.resolvedUrl(shell.width >= units.gu(60) ? "graphics/tablet_background.jpg" : "graphics/phone_background.jpg")
51 property url background
52 readonly property real panelHeight: panel.panelHeight
54 readonly property bool locked: LightDM.Greeter.active && !LightDM.Greeter.authenticated
56 property bool sideStageEnabled: shell.width >= units.gu(100)
57 readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId
59 property int maxFailedLogins: -1 // disabled by default for now, will enable via settings in future
60 property int failedLoginsDelayAttempts: 7 // number of failed logins
61 property int failedLoginsDelaySeconds: 5 * 60 // seconds of forced waiting
63 function activateApplication(appId) {
64 if (ApplicationManager.findApplication(appId)) {
65 ApplicationManager.requestFocusApplication(appId);
67 var execFlags = shell.sideStageEnabled ? ApplicationManager.NoFlag : ApplicationManager.ForceMainStage;
68 ApplicationManager.startApplication(appId, execFlags);
72 function setFakeActiveForApp(app) {
74 greeter.fakeActiveForApp = app
81 property: "applicationManager"
82 value: ApplicationManager
85 Component.onCompleted: {
86 Theme.name = "Ubuntu.Components.Themes.SuruGradient"
90 id: backgroundSettings
91 schema.id: "org.gnome.desktop.background"
93 property url gSettingsPicture: backgroundSettings.pictureUri != undefined && backgroundSettings.pictureUri.length > 0 ? backgroundSettings.pictureUri : shell.defaultBackground
94 onGSettingsPictureChanged: {
95 shell.background = gSettingsPicture
104 objectName: "dashCommunicator"
108 // Handle but do not filter out volume keys
109 Keys.onVolumeUpPressed: { volumeControl.volumeUp(); event.accepted = false; }
110 Keys.onVolumeDownPressed: { volumeControl.volumeDown(); event.accepted = false; }
113 if (event.key == Qt.Key_PowerOff || event.key == Qt.Key_PowerDown) {
114 dialogs.onPowerKeyPressed();
115 event.accepted = true;
117 event.accepted = false;
122 if (event.key == Qt.Key_PowerOff || event.key == Qt.Key_PowerDown) {
123 dialogs.onPowerKeyReleased();
124 event.accepted = true;
126 event.accepted = false;
135 height: parent.height
136 visible: !ApplicationManager.empty
139 target: ApplicationManager
141 if (appId === "dialer-app") {
142 // Always let the dialer-app through. Either user asked
143 // for an emergency call or accepted an incoming call.
144 setFakeActiveForApp(appId)
145 } else if (greeter.fakeActiveForApp !== "" && greeter.fakeActiveForApp !== appId) {
151 onFocusedApplicationIdChanged: {
152 if (greeter.fakeActiveForApp !== "" && greeter.fakeActiveForApp !== ApplicationManager.focusedApplicationId) {
155 panel.indicators.hide();
158 onApplicationAdded: {
159 if (greeter.shown && appId != "unity8-dash") {
162 if (appId === "dialer-app") {
163 // Always let the dialer-app through. Either user asked
164 // for an emergency call or accepted an incoming call.
165 setFakeActiveForApp(appId)
171 id: applicationsDisplayLoader
174 source: shell.sideStageEnabled ? "Stages/TabletStage.qml" : "Stages/PhoneStage.qml"
177 target: applicationsDisplayLoader.item
178 property: "objectName"
182 target: applicationsDisplayLoader.item
183 property: "dragAreaWidth"
184 value: shell.edgeSize
187 target: applicationsDisplayLoader.item
188 property: "maximizedAppTopMargin"
189 // Not just using panel.panelHeight as that changes depending on the focused app.
190 value: panel.indicators.panelHeight
193 target: applicationsDisplayLoader.item
194 property: "interactive"
195 value: edgeDemo.stagesEnabled && !greeter.shown && !lockscreen.shown && panel.indicators.fullyClosed && launcher.progress == 0
198 target: applicationsDisplayLoader.item
199 property: "spreadEnabled"
200 value: edgeDemo.stagesEnabled && greeter.fakeActiveForApp === "" // to support emergency dialer hack
203 target: applicationsDisplayLoader.item
204 property: "inverseProgress"
205 value: launcher.progress
212 objectName: "inputMethod"
213 anchors { fill: parent; topMargin: panel.panelHeight }
214 z: notifications.useModal || panel.indicators.shown ? overlay.z + 1 : overlay.z - 1
218 target: SurfaceManager
220 if (surface.type == MirSurfaceItem.InputMethod) {
221 inputMethod.surface = surface;
225 onSurfaceDestroyed: {
226 if (inputMethod.surface == surface) {
227 inputMethod.surface = null;
228 surface.parent = null;
230 if (!surface.parent) {
231 // there's no one displaying it. delete it right away
239 objectName: "lockscreen"
241 readonly property int backgroundTopMargin: -panel.panelHeight
243 hides: [launcher, panel.indicators]
246 showAnimation: StandardAnimation { property: "opacity"; to: 1 }
247 hideAnimation: StandardAnimation { property: "opacity"; to: 0 }
251 height: parent.height - panel.panelHeight
252 background: shell.background
253 alphaNumeric: AccountsService.passwordDisplayHint === AccountsService.Keyboard
257 onEntered: LightDM.Greeter.respond(passphrase);
258 onCancel: greeter.show()
259 onEmergencyCall: shell.activateApplication("dialer-app") // will automatically enter fake-active mode
261 onShownChanged: if (shown) greeter.fakeActiveForApp = ""
263 Component.onCompleted: {
264 if (greeter.narrowMode) {
265 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole))
271 target: LightDM.Greeter
273 onShowGreeter: greeter.show()
276 if (greeter.narrowMode) {
277 if (isDefaultPrompt) {
278 if (lockscreen.alphaNumeric) {
279 lockscreen.infoText = i18n.tr("Enter your passphrase")
280 lockscreen.errorText = i18n.tr("Sorry, incorrect passphrase")
282 lockscreen.infoText = i18n.tr("Enter your PIN")
283 lockscreen.errorText = i18n.tr("Sorry, incorrect PIN")
286 lockscreen.infoText = i18n.tr("Enter your %1").arg(text.toLowerCase())
287 lockscreen.errorText = i18n.tr("Sorry, incorrect %1").arg(text.toLowerCase())
294 onPromptlessChanged: {
295 if (LightDM.Greeter.promptless && LightDM.Greeter.authenticated) {
303 onAuthenticationComplete: {
304 if (LightDM.Greeter.authenticated) {
305 AccountsService.failedLogins = 0
307 // Else only penalize user for a failed login if they actually were
308 // prompted for a password. We do this below after the promptless
311 if (LightDM.Greeter.promptless) {
315 if (LightDM.Greeter.authenticated) {
319 AccountsService.failedLogins++
320 if (maxFailedLogins >= 2) { // require at least a warning
321 if (AccountsService.failedLogins === maxFailedLogins - 1) {
322 var title = lockscreen.alphaNumeric ?
323 i18n.tr("Sorry, incorrect passphrase.") :
324 i18n.tr("Sorry, incorrect passcode.")
325 var text = i18n.tr("This will be your last attempt.") + " " +
326 (lockscreen.alphaNumeric ?
327 i18n.tr("If passphrase is entered incorrectly, your phone will conduct a factory reset and all personal data will be deleted.") :
328 i18n.tr("If passcode is entered incorrectly, your phone will conduct a factory reset and all personal data will be deleted."))
329 lockscreen.showInfoPopup(title, text)
330 } else if (AccountsService.failedLogins >= maxFailedLogins) {
331 SystemImage.factoryReset() // Ouch!
334 if (failedLoginsDelayAttempts > 0 && AccountsService.failedLogins % failedLoginsDelayAttempts == 0) {
335 lockscreen.forceDelay(failedLoginsDelaySeconds * 1000)
338 lockscreen.clear(true);
339 if (greeter.narrowMode) {
340 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole))
347 target: LightDM.Greeter
349 value: greeter.shown || lockscreen.shown || greeter.fakeActiveForApp != ""
355 opacity: greeterWrapper.showProgress * 0.8
359 // Just a tiny wrapper to adjust greeter's x without messing with its own dragging
364 height: parent.height - panel.panelHeight
367 enabled: !launcher.dashSwipe
371 property bool fullyShown: showProgress === 1.0
372 onFullyShownChanged: {
373 // Wait until the greeter is completely covering lockscreen before resetting it.
374 if (fullyShown && !LightDM.Greeter.authenticated) {
380 readonly property real showProgress: MathUtils.clamp((1 - x/width) + greeter.showProgress - 1, 0, 1)
381 onShowProgressChanged: if (LightDM.Greeter.authenticated && showProgress === 0) greeter.login()
385 objectName: "greeter"
387 signal sessionStarted() // helpful for tests
389 property string fakeActiveForApp: ""
392 hides: [launcher, panel.indicators]
394 loadContent: required || lockscreen.required // keeps content in memory for quick show()
396 defaultBackground: shell.background
399 height: parent.height
401 dragHandleWidth: shell.edgeSize
405 if (LightDM.Greeter.startSessionSync()) {
416 if (greeter.narrowMode) {
417 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole));
419 greeter.fakeActiveForApp = "";
420 greeter.forceActiveFocus();
424 Component.onCompleted: {
425 Connectivity.unlockAllModems()
428 onUnlocked: greeter.hide()
430 // Update launcher items for new user
431 var user = LightDM.Users.data(uid, LightDM.UserRoles.NameRole);
432 AccountsService.user = user;
433 LauncherModel.setUser(user);
436 onTease: launcher.tease()
439 target: ApplicationManager
440 property: "suspended"
441 value: greeter.shown && greeterWrapper.showProgress == 1
450 onDisplayPowerStateChange: {
451 // We ignore any display-off signals when the proximity sensor
452 // is active. This usually indicates something like a phone call.
453 if (status == Powerd.Off && reason != Powerd.Proximity && !edgeDemo.running) {
457 // No reason to chew demo CPU when user isn't watching
458 if (status == Powerd.Off) {
459 edgeDemo.paused = true;
460 } else if (status == Powerd.On) {
461 edgeDemo.paused = false;
466 function showHome() {
467 if (edgeDemo.running) {
471 if (LightDM.Greeter.active) {
472 if (!LightDM.Greeter.authenticated) {
478 var animate = !LightDM.Greeter.active && !stages.shown
479 dash.setCurrentScope("clickscope", animate, false)
480 ApplicationManager.requestFocusApplication("unity8-dash")
483 function showDash() {
492 ApplicationManager.requestFocusApplication("unity8-dash")
505 anchors.fill: parent //because this draws indicator menus
508 available: edgeDemo.panelEnabled && !shell.locked
509 contentEnabled: edgeDemo.panelContentEnabled
510 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
511 panelHeight: units.gu(3)
514 property bool topmostApplicationIsFullscreen:
515 ApplicationManager.focusedApplicationId &&
516 ApplicationManager.findApplication(ApplicationManager.focusedApplicationId).fullscreen
518 fullscreenMode: (topmostApplicationIsFullscreen && !LightDM.Greeter.active && launcher.progress == 0)
519 || greeter.fakeActiveForApp !== ""
524 objectName: "launcher"
526 readonly property bool dashSwipe: progress > 0
528 anchors.top: parent.top
529 anchors.bottom: parent.bottom
531 dragAreaWidth: shell.edgeSize
532 available: edgeDemo.launcherEnabled && !shell.locked
534 onShowDashHome: showHome()
536 onDashSwipeChanged: {
537 if (dashSwipe && ApplicationManager.focusedApplicationId !== "unity8-dash") {
538 dash.setCurrentScope("clickscope", false, true)
541 onLauncherApplicationSelected: {
542 if (greeter.fakeActiveForApp !== "") {
545 if (!edgeDemo.running)
546 shell.activateApplication(appId)
550 panel.indicators.hide()
556 id: modalNotificationBackground
558 visible: notifications.useModal && !greeter.shown && (notifications.state == "narrow")
571 model: NotificationBackend.Model
576 height: parent.height - panel.panelHeight
581 when: overlay.width <= units.gu(60)
582 AnchorChanges { target: notifications; anchors.left: parent.left }
586 when: overlay.width > units.gu(60)
587 AnchorChanges { target: notifications; anchors.left: undefined }
588 PropertyChanges { target: notifications; width: units.gu(38) }
605 shutdownFadeOutRectangle.enabled = true;
606 shutdownFadeOutRectangle.visible = true;
607 shutdownFadeOut.start();
612 id: alphaDisclaimerLabel
613 anchors.centerIn: parent
614 visible: ApplicationManager.fake ? ApplicationManager.fake : false
616 text: "EARLY ALPHA\nNOT READY FOR USE"
619 font.weight: Font.Black
620 horizontalAlignment: Text.AlignHCenter
621 verticalAlignment: Text.AlignVCenter
622 fontSizeMode: Text.Fit
624 scale: Math.min(parent.width, parent.height) / width
629 z: alphaDisclaimerLabel.z + 10
632 indicators: panel.indicators
637 target: SessionBroadcast
638 onShowHome: showHome()
642 id: shutdownFadeOutRectangle
649 NumberAnimation on opacity {
654 if (shutdownFadeOutRectangle.enabled && shutdownFadeOutRectangle.visible) {
655 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