on xenial help sign in
Merge dialer-above branch
commitc6e3263d317eb850b60a5d13f4f91c5e15e30264 authorMichael Terry <michael.terry@canonical.com> dateTue 1 Jul 2014, 16:23 (12 years ago) parent62624585f4766e
45 files changed+654−119
debian/changelog+33 debian/control+1−1 plugins/Dash/CardCreator.js+7−4 plugins/LightDM/CMakeLists.txt+1 plugins/LightDM/DBusGreeter.cpp+65 plugins/LightDM/DBusGreeter.h+55 plugins/LightDM/Greeter.cpp+17 plugins/LightDM/Greeter.h+5 plugins/LightDM/plugin.cpp+3 plugins/Powerd/Powerd.cpp+16−16 plugins/Powerd/Powerd.h+8−8 po/es.po+7−7 qml/Components/Lockscreen.qml+17−5 qml/Dash/CardVerticalJournal.qml−3 qml/Dash/graphics/phone/screenshots/phone@12.png → qml/Dash/graphics/phone/screenshots/dialer@12.png qml/Greeter/LoginList.qml+4−4 qml/Shell.qml+91−27 qml/Stages/PhoneStage.qml+13−1 qml/graphics/applicationIcons/phone-app@18.png → qml/graphics/applicationIcons/dialer-app@18.png tests/autopilot/unity8/shell/tests/test_notifications.py+4−4 tests/mocks/AccountsService/AccountsService.cpp+3−1 tests/mocks/AccountsService/CMakeLists.txt−2 tests/mocks/LightDM/CMakeLists.txt+1 tests/mocks/LightDM/single-pin/GreeterPrivate.cpp+1−9 tests/mocks/Powerd/Powerd.h+7−7 tests/mocks/Unity/Application/ApplicationManager.cpp+3−3 tests/mocks/Unity/Launcher/CMakeLists.txt−2 tests/mocks/Unity/Launcher/MockLauncherItem.cpp+3−1 tests/mocks/Unity/Launcher/MockLauncherModel.cpp+1−1 tests/mocks/Unity/fake_categories.cpp+1−1 tests/mocks/Unity/fake_scope.cpp+5 tests/mocks/Unity/fake_scope.h+2 tests/plugins/Dash/cardcreator/1.res+1 tests/plugins/Dash/cardcreator/3.res+1 tests/plugins/Dash/cardcreator/5.res+1−1 tests/plugins/LightDM/CMakeLists.txt+1−1 tests/plugins/LightDM/dbus.cpp+40 tests/qmltests/CMakeLists.txt+2−2 tests/qmltests/Components/tst_LazyImage.qml−1 tests/qmltests/Dash/Apps/tst_RunningApplicationsGrid.qml+2−2 tests/qmltests/Greeter/tst_Lockscreen.qml+1−1 tests/qmltests/Launcher/tst_Launcher.qml+2−2 tests/qmltests/Notifications/tst_VisualSnapDecisionsQueue.qml+1−1 tests/qmltests/tst_Shell.qml+26−1 tests/qmltests/tst_ShellWithPin.qml+202
debian/changelog+33
@@ -1,3 +1,36 @@
1+unity8 (7.89+14.10.20140627-0ubuntu1) utopic; urgency=low
2+
3+ [ Michael Terry ]
4+ * Fix path in launcher mock after moving our mock icons, to avoid a
5+ lot of "icon not found" warnings during qmluitests.
6+ * Fix the testMultiGreeter qmluitest. Incoming method variables are
7+ apparently read-only in Qt5.3. (LP: #1332488)
8+
9+ [ CI bot ]
10+ * Resync trunk
11+
12+ [ Michał Sawicz ]
13+ * Adapt scope mock to new api and quiet unused variable warnings.
14+ * Fix dynamic overlay height. (LP: #1334879)
15+ * Don't center items in CardVerticalJournal, kind of beats the
16+ purpose... Also don't bind unnecessarily.
17+
18+ [ Ying-Chun Liu ]
19+ * Fix LP:1330957 Fix some failed test cases. (LP: #1330957)
20+
21+ [ Albert Astals ]
22+ * Don't seem to need this waitForRendering And makes test fail in 5.3
23+
24+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Fri, 27 Jun 2014 08:47:58 +0000
25+
26+unity8 (7.89+14.10.20140624.1-0ubuntu1) utopic; urgency=low
27+
28+ [ Alberto Aguirre ]
29+ * Update Powerd plugin and Shell.qml to accommodate changes in the
30+ display power state notification.
31+
32+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Tue, 24 Jun 2014 17:11:08 +0000
33+
134unity8 (7.89+14.10.20140624-0ubuntu1) utopic; urgency=low
235
336 [ Ying-Chun Liu ]
debian/control+1−1
@@ -18,7 +18,7 @@ Build-Depends: cmake,
1818 libpulse-dev,
1919 libqmenumodel-dev (>= 0.2.7),
2020 libqt5xmlpatterns5-dev,
21− libunity-api-dev (>= 7.82),
21+ libunity-api-dev (>= 7.83),
2222 libunity-mir-dev,
2323 libusermetricsoutput1-dev,
2424 libxcb1-dev,
plugins/Dash/CardCreator.js+7−4
@@ -113,7 +113,7 @@ var kOverlayLoaderCode = 'Loader { \n\
113113 visible: showHeader && status == Loader.Ready; \n\
114114 sourceComponent: ShaderEffect { \n\
115115 id: overlay; \n\
116− height: fixedHeaderHeight > 0 ? fixedHeaderHeight + units.gu(1) * 2 : headerHeight; \n\
116+ height: (fixedHeaderHeight > 0 ? fixedHeaderHeight : headerHeight) + units.gu(2); \n\
117117 opacity: 0.6; \n\
118118 property var source: ShaderEffectSource { \n\
119119 id: shaderSource; \n\
@@ -363,11 +363,11 @@ function cardString(template, components) {
363363 }
364364 }
365365 var headerLeftAnchor;
366− var headerLeftAnchorHasMagin = false;
366+ var headerLeftAnchorHasMargin = false;
367367 if (isHorizontal && hasArt) {
368368 headerLeftAnchor = 'left: artShapeHolder.right; \n\
369369 leftMargin: units.gu(1);\n';
370− headerLeftAnchorHasMagin = true;
370+ headerLeftAnchorHasMargin = true;
371371 } else {
372372 headerLeftAnchor = 'left: parent.left;\n';
373373 }
@@ -392,7 +392,7 @@ function cardString(template, components) {
392392 if (!hasHeaderRow) {
393393 anchors += headerLeftAnchor;
394394 anchors += headerVerticalAnchors;
395− if (!headerLeftAnchorHasMagin) {
395+ if (!headerLeftAnchorHasMargin) {
396396 anchors += 'leftMargin: units.gu(1);\n'
397397 }
398398 } else {
@@ -444,6 +444,9 @@ function cardString(template, components) {
444444 titleAnchors = "right: parent.right;";
445445 titleAnchors += headerLeftAnchor;
446446 titleAnchors += headerVerticalAnchors;
447+ if (!headerLeftAnchorHasMargin) {
448+ titleAnchors += 'leftMargin: units.gu(1);\n'
449+ }
447450 }
448451 subtitleAnchors = 'left: titleLabel.left; \n\
449452 leftMargin: titleLabel.leftMargin; \n\
plugins/LightDM/CMakeLists.txt+1
@@ -15,6 +15,7 @@ include_directories(
1515
1616set(QMLPLUGIN_SRC
1717 ../Utils/qsortfilterproxymodelqml.cpp # FIXME evaluate a more generic approach for using other plugins
18+ DBusGreeter.cpp
1819 DBusGreeterList.cpp
1920 Greeter.cpp
2021 plugin.cpp
plugins/LightDM/DBusGreeter.cppnew file+65
@@ -0,0 +1,65 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
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.
7+ *
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.
12+ *
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/>.
15+ */
16+
17+#include "DBusGreeter.h"
18+#include "Greeter.h"
19+
20+#include <QDBusMessage>
21+#include <QStringList>
22+
23+DBusGreeter::DBusGreeter(Greeter *greeter, const QDBusConnection &connection, const QString &path)
24+ : QObject(greeter),
25+ m_greeter(greeter),
26+ m_connection(connection),
27+ m_path(path)
28+{
29+ connect(m_greeter, SIGNAL(isActiveChanged()), this, SLOT(isActiveChangedHandler()));
30+}
31+
32+bool DBusGreeter::isActive() const
33+{
34+ return m_greeter->isActive();
35+}
36+
37+void DBusGreeter::ShowGreeter()
38+{
39+ return Q_EMIT m_greeter->showGreeter();
40+}
41+
42+void DBusGreeter::isActiveChangedHandler()
43+{
44+ notifyPropertyChanged("IsActive", isActive());
45+ Q_EMIT isActiveChanged();
46+}
47+
48+// Manually emit a PropertiesChanged signal over DBus, because QtDBus
49+// doesn't do it for us on Q_PROPERTIES, oddly enough.
50+void DBusGreeter::notifyPropertyChanged(const QString& propertyName, const QVariant &value)
51+{
52+ QDBusMessage message;
53+ QVariantMap changedProps;
54+
55+ changedProps.insert(propertyName, value);
56+
57+ message = QDBusMessage::createSignal(m_path,
58+ "org.freedesktop.DBus.Properties",
59+ "PropertiesChanged");
60+ message << "com.canonical.UnityGreeter";
61+ message << changedProps;
62+ message << QStringList();
63+
64+ m_connection.send(message);
65+}
plugins/LightDM/DBusGreeter.hnew file+55
@@ -0,0 +1,55 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
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.
7+ *
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.
12+ *
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/>.
15+ */
16+
17+#ifndef UNITY_DBUSGREETER_H
18+#define UNITY_DBUSGREETER_H
19+
20+#include <QDBusConnection>
21+#include <QObject>
22+
23+class Greeter;
24+class QDBusInterface;
25+
26+/** This is an internal class used to talk with the indicators.
27+ */
28+
29+class DBusGreeter : public QObject
30+{
31+ Q_OBJECT
32+ Q_CLASSINFO("D-Bus Interface", "com.canonical.UnityGreeter")
33+
34+ Q_PROPERTY(bool IsActive READ isActive NOTIFY isActiveChanged) // since 14.10
35+
36+public:
37+ explicit DBusGreeter(Greeter *greeter, const QDBusConnection &connection, const QString &path);
38+
39+ bool isActive() const;
40+ Q_SCRIPTABLE void ShowGreeter(); // temporary, until we split the greeter again
41+
42+Q_SIGNALS:
43+ void isActiveChanged();
44+
45+private Q_SLOTS:
46+ void isActiveChangedHandler();
47+ void notifyPropertyChanged(const QString &propertyName, const QVariant &value);
48+
49+private:
50+ Greeter *m_greeter;
51+ QDBusConnection m_connection;
52+ QString m_path;
53+};
54+
55+#endif
plugins/LightDM/Greeter.cpp+17
@@ -25,6 +25,7 @@ public:
2525 explicit GreeterPrivate(Greeter *parent);
2626
2727 QLightDM::Greeter *m_greeter;
28+ bool m_active;
2829 bool wasPrompted;
2930 bool promptless;
3031
@@ -38,6 +39,7 @@ private:
3839
3940GreeterPrivate::GreeterPrivate(Greeter* parent)
4041 : m_greeter(new QLightDM::Greeter(parent)),
42+ m_active(false),
4143 wasPrompted(false),
4244 promptless(false),
4345 q_ptr(parent)
@@ -60,6 +62,21 @@ Greeter::Greeter(QObject* parent)
6062 d->m_greeter->connectSync();
6163}
6264
65+bool Greeter::isActive() const
66+{
67+ Q_D(const Greeter);
68+ return d->m_active;
69+}
70+
71+void Greeter::setIsActive(bool active)
72+{
73+ Q_D(Greeter);
74+ if (d->m_active != active) {
75+ d->m_active = active;
76+ Q_EMIT isActiveChanged();
77+ }
78+}
79+
6380bool Greeter::isAuthenticated() const
6481{
6582 Q_D(const Greeter);
plugins/LightDM/Greeter.h+5
@@ -34,6 +34,7 @@ class Greeter : public QObject
3434{
3535 Q_OBJECT
3636
37+ Q_PROPERTY(bool active READ isActive WRITE setIsActive NOTIFY isActiveChanged)
3738 Q_PROPERTY(bool authenticated READ isAuthenticated)
3839 Q_PROPERTY(QString authenticationUser READ authenticationUser NOTIFY authenticationUserChanged)
3940 Q_PROPERTY(bool promptless READ promptless NOTIFY promptlessChanged)
@@ -41,6 +42,7 @@ class Greeter : public QObject
4142public:
4243 explicit Greeter(QObject* parent=0);
4344
45+ bool isActive() const;
4446 bool isAuthenticated() const;
4547 QString authenticationUser() const;
4648 bool promptless() const;
@@ -49,13 +51,16 @@ public Q_SLOTS:
4951 void authenticate(const QString &username=QString());
5052 void respond(const QString &response);
5153 bool startSessionSync(const QString &session=QString());
54+ void setIsActive(bool isActive);
5255
5356Q_SIGNALS:
5457 void showMessage(const QString &text, bool isError);
5558 void showPrompt(const QString &text, bool isSecret);
5659 void authenticationComplete();
5760 void authenticationUserChanged(const QString &user);
61+ void isActiveChanged();
5862 void promptlessChanged();
63+ void showGreeter();
5964
6065 // This signal is emitted by external agents like indicators, and the UI
6166 // should switch to this user if possible.
plugins/LightDM/plugin.cpp+3
@@ -18,6 +18,7 @@
1818 */
1919
2020#include "plugin.h"
21+#include "DBusGreeter.h"
2122#include "DBusGreeterList.h"
2223#include "Greeter.h"
2324#include "UsersModel.h"
@@ -39,6 +40,8 @@ static QObject *greeter_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
3940
4041 Greeter *greeter = new Greeter();
4142 QDBusConnection connection = QDBusConnection::sessionBus();
43+ DBusGreeter *root = new DBusGreeter(greeter, connection, "/");
44+ connection.registerObject("/", root, QDBusConnection::ExportScriptableContents);
4245 DBusGreeterList *list = new DBusGreeterList(greeter, connection, GREETER_LIST_DBUS_PATH);
4346 connection.registerObject(GREETER_LIST_DBUS_PATH, list, QDBusConnection::ExportScriptableContents);
4447 connection.registerService(GREETER_DBUS_SERVICE);
plugins/Powerd/Powerd.cpp+16−16
@@ -19,35 +19,35 @@
1919#include "Powerd.h"
2020#include <QDBusPendingCall>
2121
22−void autoBrightnessChanged(GSettings *settings, const gchar *key, QDBusInterface *powerd)
22+void autoBrightnessChanged(GSettings *settings, const gchar *key, QDBusInterface *unityScreen)
2323{
2424 bool value = g_settings_get_boolean(settings, key);
25− powerd->asyncCall("userAutobrightnessEnable", QVariant(value));
25+ unityScreen->asyncCall("userAutobrightnessEnable", QVariant(value));
2626}
2727
2828Powerd::Powerd(QObject* parent)
2929 : QObject(parent),
30− powerd(NULL)
30+ unityScreen(NULL)
3131{
32− powerd = new QDBusInterface("com.canonical.powerd",
33− "/com/canonical/powerd",
34− "com.canonical.powerd",
35− QDBusConnection::SM_BUSNAME(), this);
32+ unityScreen = new QDBusInterface("com.canonical.Unity.Screen",
33+ "/com/canonical/Unity/Screen",
34+ "com.canonical.Unity.Screen",
35+ QDBusConnection::SM_BUSNAME(), this);
3636
37− powerd->connection().connect("com.canonical.powerd",
38− "/com/canonical/powerd",
39− "com.canonical.powerd",
40− "DisplayPowerStateChange",
41− this,
42− SIGNAL(displayPowerStateChange(int, unsigned int)));
37+ unityScreen->connection().connect("com.canonical.Unity.Screen",
38+ "/com/canonical/Unity/Screen",
39+ "com.canonical.Unity.Screen",
40+ "DisplayPowerStateChange",
41+ this,
42+ SIGNAL(displayPowerStateChange(int, int)));
4343
4444 systemSettings = g_settings_new("com.ubuntu.touch.system");
45− g_signal_connect(systemSettings, "changed::auto-brightness", G_CALLBACK(autoBrightnessChanged), powerd);
46− autoBrightnessChanged(systemSettings, "auto-brightness", powerd);
45+ g_signal_connect(systemSettings, "changed::auto-brightness", G_CALLBACK(autoBrightnessChanged), unityScreen);
46+ autoBrightnessChanged(systemSettings, "auto-brightness", unityScreen);
4747}
4848
4949Powerd::~Powerd()
5050{
51− g_signal_handlers_disconnect_by_data(systemSettings, powerd);
51+ g_signal_handlers_disconnect_by_data(systemSettings, unityScreen);
5252 g_object_unref(systemSettings);
5353}
plugins/Powerd/Powerd.h+8−8
@@ -28,15 +28,15 @@ class Powerd: public QObject
2828{
2929 Q_OBJECT
3030 Q_ENUMS(Status)
31− Q_FLAGS(DisplayFlag DisplayFlags)
31+ Q_ENUMS(DisplayStateChangeReason)
3232
3333public:
34− enum DisplayFlag {
35− UseProximity = 1, // Use proximity sensor to override screen state
36− DisableAutoBrightness = 2, // Force autobrightness to be disabled
37− Bright = 4, // Request the screen to stay bright
34+ enum DisplayStateChangeReason {
35+ Unknown = 0,
36+ Inactivity = 1, // Display changed state due to inactivity
37+ PowerKey = 2, // Display changed state due to user pressing power key
38+ Proximity = 3, // Display changed state due to proximity events
3839 };
39− Q_DECLARE_FLAGS(DisplayFlags, DisplayFlag)
4040
4141 enum Status {
4242 Off,
@@ -47,10 +47,10 @@ public:
4747 ~Powerd();
4848
4949Q_SIGNALS:
50− void displayPowerStateChange(int status, unsigned int flags);
50+ void displayPowerStateChange(int status, int reason);
5151
5252private:
53− QDBusInterface *powerd;
53+ QDBusInterface *unityScreen;
5454 GSettings *systemSettings;
5555};
5656
po/es.po+7−7
@@ -8,14 +8,14 @@ msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010"POT-Creation-Date: 2014-06-13 09:55+0200\n"
11−"PO-Revision-Date: 2014-06-02 06:28+0000\n"
12−"Last-Translator: benjisp94 <benjisp94@gmail.com>\n"
11+"PO-Revision-Date: 2014-06-26 03:08+0000\n"
12+"Last-Translator: Adolfo Jayme <fitoschido@gmail.com>\n"
1313"Language-Team: Spanish <es@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-06-17 06:51+0000\n"
18−"X-Generator: Launchpad (build 17045)\n"
17+"X-Launchpad-Export-Date: 2014-06-27 07:13+0000\n"
18+"X-Generator: Launchpad (build 17077)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -83,7 +83,7 @@ msgstr "Llamada de emergencia"
8383
8484#: qml/Components/Lockscreen.qml:231
8585msgid "OK"
86−msgstr ""
86+msgstr "Aceptar"
8787
8888#: qml/Components/PageHeader.qml:365
8989msgid "Recent searches"
@@ -100,11 +100,11 @@ msgstr "Hola"
100100
101101#: qml/Components/PinLockscreen.qml:198
102102msgid "CANCEL"
103−msgstr ""
103+msgstr "CANCELAR"
104104
105105#: qml/Components/PinLockscreen.qml:216
106106msgid "DONE"
107−msgstr ""
107+msgstr "HECHO"
108108
109109#: qml/Components/SeeMore.qml:35
110110msgid "See more"
qml/Components/Lockscreen.qml+17−5
@@ -186,6 +186,17 @@ Showable {
186186 }
187187
188188 Column {
189+ id: emergencyCallColumn
190+
191+ // FIXME: We *should* show emergency dialer if there is a SIM present,
192+ // regardless of whether the side stage is enabled. But right now,
193+ // the assumption is that narrow screens are phones which have SIMs
194+ // and wider screens are tablets which don't. When we do allow this
195+ // on devices with a side stage and a SIM, work should be done to
196+ // ensure that the main stage is disabled while the dialer is present
197+ // in the side stage.
198+ visible: !shell.sideStageEnabled
199+
189200 anchors {
190201 left: parent.left
191202 bottom: parent.bottom
@@ -203,11 +214,6 @@ Showable {
203214 name: "phone-app-call-symbolic"
204215 color: "#f3f3e7"
205216 opacity: 0.6
206−
207− MouseArea {
208− anchors.fill: parent
209− onClicked: root.emergencyCall()
210− }
211217 }
212218
213219 Label {
@@ -219,6 +225,12 @@ Showable {
219225 }
220226 }
221227
228+ MouseArea {
229+ anchors.fill: emergencyCallColumn
230+ onClicked: root.emergencyCall()
231+ enabled: emergencyCallColumn.visible
232+ }
233+
222234 Component {
223235 id: infoPopupComponent
224236 Dialog {
qml/Dash/CardVerticalJournal.qml−3
@@ -67,11 +67,8 @@ DashRenderer {
6767 id: loader
6868 sourceComponent: cardTool.cardComponent
6969 width: cardTool.cardWidth
70− anchors.horizontalCenter: parent.horizontalCenter
7170 onLoaded: {
7271 item.objectName = "delegate" + index;
73− item.width = Qt.binding(function() { return cardTool.cardWidth; });
74− item.height = Qt.binding(function() { return cardTool.cardHeight; });
7572 item.fixedArtShapeSize = Qt.binding(function() { return cardTool.artShapeSize; });
7673 item.fixedHeaderHeight = Qt.binding(function() { return cardTool.headerHeight; });
7774 item.cardData = Qt.binding(function() { return model; });
qml/Dash/graphics/phone/screenshots/phone@12.png → qml/Dash/graphics/phone/screenshots/dialer@12.pngrenamed

Binary file not shown.

qml/Greeter/LoginList.qml+4−4
@@ -257,13 +257,13 @@ Item {
257257
258258 onShowMessage: {
259259 // inefficient, but we only rarely deal with messages
260− text = text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/\n/g, "<br>");
260+ var html = text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/\n/g, "<br>")
261261 if (isError)
262− text = "<font color=\"#df382c\">" + text + "</font>"
262+ html = "<font color=\"#df382c\">" + html + "</font>"
263263 if (infoLabel.text == "")
264− infoLabel.text = text;
264+ infoLabel.text = html
265265 else
266− infoLabel.text = infoLabel.text + "<br>" + text;
266+ infoLabel.text = infoLabel.text + "<br>" + html
267267 }
268268
269269 onShowPrompt: {
qml/Shell.qml+91−27
@@ -136,7 +136,7 @@ FocusScope {
136136 id: dash
137137 objectName: "dash"
138138
139− available: !greeter.shown && !lockscreen.shown
139+ available: !LightDM.Greeter.active
140140 hides: [stages, launcher, panel.indicators]
141141 shown: disappearingAnimationProgress !== 1.0 && greeterWrapper.showProgress !== 1.0
142142 enabled: disappearingAnimationProgress === 0.0 && greeterWrapper.showProgress === 0.0 && edgeDemo.dashEnabled
@@ -199,7 +199,7 @@ FocusScope {
199199
200200 x: {
201201 if (shown) {
202− if (overlayMode || locked) {
202+ if (overlayMode || locked || greeter.fakeActiveForApp !== "") {
203203 return 0;
204204 }
205205 return launcher.progress
@@ -244,10 +244,17 @@ FocusScope {
244244 target: ApplicationManager
245245
246246 onFocusRequested: {
247+ if (greeter.fakeActiveForApp !== "" && greeter.fakeActiveForApp !== appId) {
248+ lockscreen.show();
249+ }
250+ greeter.hide();
247251 stages.show(true);
248252 }
249253
250254 onFocusedApplicationIdChanged: {
255+ if (greeter.fakeActiveForApp !== "" && greeter.fakeActiveForApp !== ApplicationManager.focusedApplicationId) {
256+ lockscreen.show();
257+ }
251258 if (ApplicationManager.focusedApplicationId.length > 0) {
252259 stages.show(false);
253260 } else {
@@ -298,6 +305,11 @@ FocusScope {
298305
299306 source: shell.sideStageEnabled ? "Stages/StageWithSideStage.qml" : "Stages/PhoneStage.qml"
300307
308+ Binding {
309+ target: applicationsDisplayLoader.item
310+ property: "objectName"
311+ value: "stage"
312+ }
301313 Binding {
302314 target: applicationsDisplayLoader.item
303315 property: "moving"
@@ -313,6 +325,11 @@ FocusScope {
313325 property: "dragAreaWidth"
314326 value: shell.edgeSize
315327 }
328+ Binding {
329+ target: applicationsDisplayLoader.item
330+ property: "spreadEnabled"
331+ value: greeter.fakeActiveForApp === "" // to support emergency dialer hack
332+ }
316333 }
317334 }
318335
@@ -337,6 +354,13 @@ FocusScope {
337354
338355 onEntered: LightDM.Greeter.respond(passphrase);
339356 onCancel: greeter.show()
357+ onEmergencyCall: {
358+ greeter.fakeActiveForApp = "dialer-app"
359+ shell.activateApplication("dialer-app")
360+ lockscreen.hide()
361+ }
362+
363+ onShownChanged: if (shown) greeter.fakeActiveForApp = ""
340364
341365 Component.onCompleted: {
342366 if (LightDM.Users.count == 1) {
@@ -348,6 +372,8 @@ FocusScope {
348372 Connections {
349373 target: LightDM.Greeter
350374
375+ onShowGreeter: greeter.show()
376+
351377 onShowPrompt: {
352378 if (LightDM.Users.count == 1) {
353379 // TODO: There's no better way for now to determine if its a PIN or a passphrase.
@@ -367,12 +393,19 @@ FocusScope {
367393 }
368394 if (LightDM.Greeter.authenticated) {
369395 lockscreen.hide();
396+ greeter.login();
370397 } else {
371398 lockscreen.clear(true);
372399 }
373400 }
374401 }
375402
403+ Binding {
404+ target: LightDM.Greeter
405+ property: "active"
406+ value: greeter.shown || lockscreen.shown || greeter.fakeActiveForApp != ""
407+ }
408+
376409 Rectangle {
377410 anchors.fill: parent
378411 color: "black"
@@ -393,11 +426,16 @@ FocusScope {
393426 }
394427
395428 readonly property real showProgress: MathUtils.clamp((1 - x/width) + greeter.showProgress - 1, 0, 1)
429+ onShowProgressChanged: if (LightDM.Greeter.promptless && showProgress === 0) greeter.login()
396430
397431 Greeter {
398432 id: greeter
399433 objectName: "greeter"
400434
435+ signal sessionStarted() // helpful for tests
436+
437+ property string fakeActiveForApp: ""
438+
401439 available: true
402440 hides: [launcher, panel.indicators]
403441 shown: true
@@ -409,14 +447,28 @@ FocusScope {
409447
410448 dragHandleWidth: shell.edgeSize
411449
450+ function login() {
451+ enabled = false;
452+ LightDM.Greeter.startSessionSync();
453+ sessionStarted();
454+ greeter.hide();
455+ lockscreen.hide();
456+ launcher.hide();
457+ enabled = true;
458+ }
459+
412460 onShownChanged: {
413461 if (shown) {
414462 lockscreen.reset();
463+ if (!LightDM.Greeter.promptless) {
464+ lockscreen.show();
465+ }
415466 // If there is only one user, we start authenticating with that one here.
416467 // If there are more users, the Greeter will handle that
417468 if (LightDM.Users.count == 1) {
418469 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole));
419470 }
471+ greeter.fakeActiveForApp = "";
420472 greeter.forceActiveFocus();
421473 }
422474 }
@@ -452,7 +504,7 @@ FocusScope {
452504 onDisplayPowerStateChange: {
453505 // We ignore any display-off signals when the proximity sensor
454506 // is active. This usually indicates something like a phone call.
455− if (status == Powerd.Off && (flags & Powerd.UseProximity) == 0) {
507+ if (status == Powerd.Off && reason != Powerd.Proximity) {
456508 greeter.showNow();
457509 }
458510
@@ -466,12 +518,36 @@ FocusScope {
466518 }
467519
468520 function showHome() {
469− var animate = !greeter.shown && !stages.shown
470− greeter.hide()
521+ if (edgeDemo.running)
522+ return
523+
524+ if (LightDM.Greeter.active) {
525+ if (!LightDM.Greeter.promptless)
526+ lockscreen.show()
527+ greeter.hide()
528+ }
529+
530+ var animate = !LightDM.Greeter.active && !stages.shown
471531 dash.setCurrentScope("clickscope", animate, false)
472532 stages.hide()
473533 }
474534
535+ function showDash() {
536+ if (LightDM.Greeter.active && !LightDM.Greeter.promptless)
537+ return;
538+
539+ if (stages.shown && !stages.overlayMode) {
540+ if (!stages.locked) {
541+ stages.hide();
542+ launcher.hide();
543+ }
544+ }
545+ if (greeter.shown) {
546+ greeter.hideRight();
547+ launcher.hide();
548+ }
549+ }
550+
475551 function hideIndicatorMenu(delay) {
476552 panel.hideIndicatorMenu(delay);
477553 }
@@ -483,17 +559,18 @@ FocusScope {
483559
484560 Panel {
485561 id: panel
562+ objectName: "panel"
486563 anchors.fill: parent //because this draws indicator menus
487564 indicatorsMenuWidth: parent.width > units.gu(60) ? units.gu(40) : parent.width
488565 indicators {
489566 hides: [launcher]
490− available: edgeDemo.panelEnabled
567+ available: edgeDemo.panelEnabled && greeter.fakeActiveForApp === ""
491568 contentEnabled: edgeDemo.panelContentEnabled
492569 }
493570 property string focusedAppId: ApplicationManager.focusedApplicationId
494571 property var focusedApplication: ApplicationManager.findApplication(focusedAppId)
495− fullscreenMode: focusedApplication && stages.fullscreen && !greeter.shown && !lockscreen.shown
496− searchVisible: !greeter.shown && !lockscreen.shown && dash.shown && dash.searchable
572+ fullscreenMode: (focusedApplication && stages.fullscreen && !LightDM.Greeter.active) || greeter.fakeActiveForApp !== ""
573+ searchVisible: !LightDM.Greeter.active && dash.shown && dash.searchable
497574
498575 InputFilterArea {
499576 anchors {
@@ -518,6 +595,7 @@ FocusScope {
518595
519596 Launcher {
520597 id: launcher
598+ objectName: "launcher"
521599
522600 readonly property bool dashSwipe: progress > 0
523601
@@ -525,28 +603,14 @@ FocusScope {
525603 anchors.bottom: parent.bottom
526604 width: parent.width
527605 dragAreaWidth: shell.edgeSize
528− available: edgeDemo.launcherEnabled
529−
530− onShowDashHome: {
531− if (edgeDemo.running)
532− return;
606+ available: edgeDemo.launcherEnabled && greeter.fakeActiveForApp === ""
533607
534− showHome()
535− }
536− onDash: {
537− if (stages.shown && !stages.overlayMode) {
538− if (!stages.locked) {
539− stages.hide();
540− launcher.hide();
541− }
542− }
543− if (greeter.shown) {
544− greeter.hideRight();
545− launcher.hide();
546− }
547− }
608+ onShowDashHome: showHome()
609+ onDash: showDash()
548610 onDashSwipeChanged: if (dashSwipe && stages.shown) dash.setCurrentScope("clickscope", false, true)
549611 onLauncherApplicationSelected: {
612+ if (greeter.fakeActiveForApp !== "")
613+ lockscreen.show()
550614 if (!edgeDemo.running)
551615 shell.activateApplication(appId)
552616 }
qml/Stages/PhoneStage.qml+13−1
@@ -18,6 +18,7 @@ import QtQuick 2.0
1818import Ubuntu.Components 0.1
1919import Ubuntu.Gestures 0.1
2020import Unity.Application 0.1
21+import LightDM 0.1 as LightDM
2122import Utils 0.1
2223import "../Components"
2324
@@ -33,6 +34,7 @@ Item {
3334 readonly property bool painting: mainScreenshotImage.visible || fadeInScreenshotImage.visible || appSplash.visible || spreadView.visible
3435 property bool fullscreen: priv.focusedApplication ? priv.focusedApplication.fullscreen : false
3536 property bool locked: spreadView.visible
37+ property bool spreadEnabled: true
3638
3739 // Not used for PhoneStage, only useful for SideStage and similar
3840 property bool overlayMode: false
@@ -131,6 +133,11 @@ Item {
131133 mainScreenshotImage.visible = true;
132134 } else if (priv.secondApplicationStarting && priv.waitingForScreenshot) {
133135 applicationSwitchingAnimation.start();
136+ if (LightDM.Greeter.active && !LightDM.Greeter.promptless) {
137+ // When greeter is up, no fancy animations, since user may
138+ // glimpse an app they shouldn't
139+ applicationSwitchingAnimation.complete();
140+ }
134141 }
135142 waitingForScreenshot = false;
136143 }
@@ -145,6 +152,11 @@ Item {
145152 priv.newFocusedAppId = appId;
146153 root.fullscreen = ApplicationManager.findApplication(appId).fullscreen;
147154 applicationSwitchingAnimation.start();
155+ if (LightDM.Greeter.active && !LightDM.Greeter.promptless) {
156+ // When greeter is up, no fancy animations, since user may
157+ // glimpse an app they shouldn't
158+ applicationSwitchingAnimation.complete();
159+ }
148160 } else {
149161 ApplicationManager.focusApplication(appId);
150162 }
@@ -244,7 +256,7 @@ Item {
244256 EdgeDragArea {
245257 id: spreadDragArea
246258 direction: Direction.Leftwards
247− enabled: ApplicationManager.count > 1 && spreadView.phase != 2
259+ enabled: ApplicationManager.count > 1 && spreadView.phase != 2 && root.spreadEnabled
248260
249261 anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
250262 width: root.dragAreaWidth
qml/graphics/applicationIcons/phone-app@18.png → qml/graphics/applicationIcons/dialer-app@18.pngrenamed

Binary file not shown.

tests/autopilot/unity8/shell/tests/test_notifications.py+4−4
@@ -137,7 +137,7 @@ class InteractiveNotificationBase(NotificationsBase):
137137 ("x-canonical-switch-to-application", "true"),
138138 (
139139 "x-canonical-secondary-icon",
140− self._get_icon_path('applicationIcons/phone-app.png')
140+ self._get_icon_path('applicationIcons/dialer-app.png')
141141 )
142142 ]
143143
@@ -172,7 +172,7 @@ class InteractiveNotificationBase(NotificationsBase):
172172 hints = [
173173 (
174174 "x-canonical-secondary-icon",
175− self._get_icon_path('applicationIcons/phone-app.png')
175+ self._get_icon_path('applicationIcons/dialer-app.png')
176176 ),
177177 ("x-canonical-snap-decisions", "true"),
178178 ]
@@ -435,7 +435,7 @@ class EphemeralNotificationsTests(NotificationsBase):
435435 hints = [
436436 (
437437 "x-canonical-secondary-icon",
438− self._get_icon_path('applicationIcons/phone-app.png')
438+ self._get_icon_path('applicationIcons/dialer-app.png')
439439 )
440440 ]
441441
@@ -677,7 +677,7 @@ class EphemeralNotificationsTests(NotificationsBase):
677677 body = 'This bubble uses the icon-title-body layout with a ' \
678678 'secondary icon.'
679679 icon_path = self._get_icon_path('avatars/anna_olsson.png')
680− hint_icon = self._get_icon_path('applicationIcons/phone-app.png')
680+ hint_icon = self._get_icon_path('applicationIcons/dialer-app.png')
681681
682682 notification = shell.create_ephemeral_notification(
683683 summary,
tests/mocks/AccountsService/AccountsService.cpp+3−1
@@ -18,9 +18,11 @@
1818
1919#include "AccountsService.h"
2020
21+#include <paths.h>
22+
2123AccountsService::AccountsService(QObject* parent)
2224 : QObject(parent),
23− m_backgroundFile(TOP_SRCDIR "/qml/graphics/phone_background.jpg"),
25+ m_backgroundFile(qmlDirectory() + "graphics/phone_background.jpg"),
2426 m_statsWelcomeScreen(true)
2527{
2628}
tests/mocks/AccountsService/CMakeLists.txt−2
@@ -1,5 +1,3 @@
1−add_definitions(-DTOP_SRCDIR="${CMAKE_SOURCE_DIR}")
2−
31add_library(MockAccountsService-qml MODULE
42 AccountsService.cpp
53 plugin.cpp
tests/mocks/LightDM/CMakeLists.txt+1
@@ -18,6 +18,7 @@ include_directories(
1818)
1919
2020set(QMLPLUGIN_SRC
21+ ${CMAKE_SOURCE_DIR}/plugins/LightDM/DBusGreeter.cpp
2122 ${CMAKE_SOURCE_DIR}/plugins/LightDM/DBusGreeterList.cpp
2223 ${CMAKE_SOURCE_DIR}/plugins/LightDM/Greeter.cpp
2324 ${CMAKE_SOURCE_DIR}/plugins/LightDM/plugin.cpp
tests/mocks/LightDM/single-pin/GreeterPrivate.cpp+1−9
@@ -19,8 +19,6 @@
1919#include "../Greeter.h"
2020#include "../GreeterPrivate.h"
2121
22−#include <QDebug>
23−
2422namespace QLightDM
2523{
2624
@@ -34,19 +32,13 @@ GreeterPrivate::GreeterPrivate(Greeter* parent)
3432void GreeterPrivate::handleAuthenticate()
3533{
3634 Q_Q(Greeter);
37−
38− qDebug() << "handleAuthentication called!" << authenticationUser;
39−
40− Q_EMIT q->showPrompt("PIN:", Greeter::PromptTypeSecret);
35+ Q_EMIT q->showPrompt("PIN", Greeter::PromptTypeSecret);
4136}
4237
4338void GreeterPrivate::handleRespond(const QString &response)
4439{
4540 Q_Q(Greeter);
46−
47−
4841 authenticated = (response == "1234");
49− qDebug() << "responding" << response << authenticated;
5042 Q_EMIT q->authenticationComplete();
5143}
5244
tests/mocks/Powerd/Powerd.h+7−7
@@ -25,15 +25,15 @@ class Powerd: public QObject
2525{
2626 Q_OBJECT
2727 Q_ENUMS(Status)
28− Q_FLAGS(DisplayFlag DisplayFlags)
28+ Q_ENUMS(DisplayStateChangeReason)
2929
3030public:
31− enum DisplayFlag {
32− UseProximity = 1, // Use proximity sensor to override screen state
33− DisableAutoBrightness = 2, // Force autobrightness to be disabled
34− Bright = 4, // Request the screen to stay bright
31+ enum DisplayStateChangeReason {
32+ Unknown = 0,
33+ Inactivity = 1, // Display changed state due to inactivity
34+ PowerKey = 2, // Display changed state due to user pressing power key
35+ Proximity = 3, // Display changed state due to proximity events
3536 };
36− Q_DECLARE_FLAGS(DisplayFlags, DisplayFlag)
3737
3838 enum Status {
3939 Off,
@@ -43,7 +43,7 @@ public:
4343 explicit Powerd(QObject *parent = 0);
4444
4545Q_SIGNALS:
46− void displayPowerStateChange(int status, unsigned int flags);
46+ void displayPowerStateChange(int status, int reason);
4747};
4848
4949#endif
tests/mocks/Unity/Application/ApplicationManager.cpp+3−3
@@ -361,9 +361,9 @@ void ApplicationManager::buildListOfAvailableApplications()
361361 ApplicationInfo *application;
362362
363363 application = new ApplicationInfo(this);
364− application->setAppId("phone-app");
365− application->setName("Phone");
366− application->setIcon(QUrl("phone"));
364+ application->setAppId("dialer-app");
365+ application->setName("Dialer");
366+ application->setIcon(QUrl("dialer"));
367367 application->setStage(ApplicationInfo::SideStage);
368368 application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
369369 generateQmlStrings(application);
tests/mocks/Unity/Launcher/CMakeLists.txt−2
@@ -1,7 +1,5 @@
11pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=3)
22
3−add_definitions(-DTOP_SRCDIR="${CMAKE_SOURCE_DIR}")
4−
53include_directories(
64 ${CMAKE_CURRENT_SOURCE_DIR}
75)
tests/mocks/Unity/Launcher/MockLauncherItem.cpp+3−1
@@ -20,6 +20,8 @@
2020#include "MockLauncherItem.h"
2121#include "MockQuickListModel.h"
2222
23+#include <paths.h>
24+
2325using namespace unity::shell::launcher;
2426
2527MockLauncherItem::MockLauncherItem(const QString &appId, const QString& desktopFile, const QString& name, const QString& icon, QObject* parent):
@@ -27,7 +29,7 @@ MockLauncherItem::MockLauncherItem(const QString &appId, const QString& desktopF
2729 m_appId(appId),
2830 m_desktopFile(desktopFile),
2931 m_name(name),
30− m_icon(TOP_SRCDIR "/graphics/applicationIcons/" + icon + ".png"),
32+ m_icon(qmlDirectory() + "graphics/applicationIcons/" + icon + ".png"),
3133 m_pinned(false),
3234 m_running(false),
3335 m_recent(false),
tests/mocks/Unity/Launcher/MockLauncherModel.cpp+1−1
@@ -22,7 +22,7 @@
2222
2323MockLauncherModel::MockLauncherModel(QObject* parent): LauncherModelInterface(parent)
2424{
25− MockLauncherItem *item = new MockLauncherItem("phone-app", "/usr/share/applications/phone-app.desktop", "Phone", "phone-app", this);
25+ MockLauncherItem *item = new MockLauncherItem("dialer-app", "/usr/share/applications/dialer-app.desktop", "Dialer", "dialer-app", this);
2626 item->setProgress(0);
2727 m_list.append(item);
2828 item->setFocused(true);
tests/mocks/Unity/fake_categories.cpp+1−1
@@ -50,7 +50,7 @@ void Categories::addSpecialCategory(QString const& categoryId, QString const& na
5050 }
5151}
5252
53−bool Categories::overrideCategoryJson(QString const& categoryId, QString const& json)
53+bool Categories::overrideCategoryJson(QString const& /* categoryId */, QString const& /* json */)
5454{
5555 qFatal("Using un-implemented Categories::overrideCategoryJson");
5656}
tests/mocks/Unity/fake_scope.cpp+5
@@ -155,6 +155,11 @@ bool Scope::hasDepartments() const
155155 return true;
156156}
157157
158+QVariantMap Scope::customizations() const
159+{
160+ return QVariantMap();
161+}
162+
158163unity::shell::scopes::DepartmentInterface* Scope::getDepartment(const QString& id)
159164{
160165 if (id.isEmpty())
tests/mocks/Unity/fake_scope.h+2
@@ -64,6 +64,8 @@ public:
6464 Q_INVOKABLE unity::shell::scopes::DepartmentInterface* getDepartment(const QString& id) override;
6565 Q_INVOKABLE void loadDepartment(const QString& id) override;
6666
67+ QVariantMap customizations() const override;
68+
6769protected:
6870
6971 QString m_id;
tests/plugins/Dash/cardcreator/1.res+1
@@ -68,6 +68,7 @@ Label {
6868 anchors { right: parent.right;left: parent.left;
6969top: artShapeHolder.bottom;
7070 topMargin: units.gu(1);
71+leftMargin: units.gu(1);
7172 }
7273 elide: Text.ElideRight;
7374 fontSize: "small";
tests/plugins/Dash/cardcreator/3.res+1
@@ -68,6 +68,7 @@ Label {
6868 anchors { right: parent.right;left: parent.left;
6969top: artShapeHolder.bottom;
7070 topMargin: units.gu(1);
71+leftMargin: units.gu(1);
7172}
7273 elide: Text.ElideRight;
7374 fontSize: "small";
tests/plugins/Dash/cardcreator/5.res+1−1
@@ -73,7 +73,7 @@ Loader {
7373 visible: showHeader && status == Loader.Ready;
7474 sourceComponent: ShaderEffect {
7575 id: overlay;
76− height: fixedHeaderHeight > 0 ? fixedHeaderHeight + units.gu(1) * 2 : headerHeight;
76+ height: (fixedHeaderHeight > 0 ? fixedHeaderHeight : headerHeight) + units.gu(2);
7777 opacity: 0.6;
7878 property var source: ShaderEffectSource {
7979 id: shaderSource;
tests/plugins/LightDM/CMakeLists.txt+1−1
@@ -19,7 +19,7 @@ target_link_libraries(test-lightdm-dbus
1919
2020add_definitions(-DCURRENT_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
2121
22−add_custom_target(testLightDMDBus dbus-launch env QML2_IMPORT_PATH=${CMAKE_BINARY_DIR}/tests/mocks LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full ${CMAKE_CURRENT_BINARY_DIR}/test-lightdm-dbus)
22+add_custom_target(testLightDMDBus xvfb-run --server-args "-screen 0 1024x768x24" --auto-servernum dbus-launch env QML2_IMPORT_PATH=${CMAKE_BINARY_DIR}/tests/mocks LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full ${CMAKE_CURRENT_BINARY_DIR}/test-lightdm-dbus)
2323add_dependencies(testLightDMDBus test-lightdm-dbus)
2424
2525add_dependencies(qmluitests testLightDMDBus)
tests/plugins/LightDM/dbus.cpp+40
@@ -38,6 +38,13 @@ private Q_SLOTS:
3838 // SIGNAL method, because QtDBus doesn't know about PropertiesChanged.
3939 // So we connect the hard way for the benefit of any tests that want
4040 // to watch.
41+ QDBusConnection::sessionBus().connect(
42+ "com.canonical.UnityGreeter",
43+ "/",
44+ "org.freedesktop.DBus.Properties",
45+ "PropertiesChanged",
46+ this,
47+ SIGNAL(PropertiesChangedRelay(const QString&, const QVariantMap&, const QStringList&)));
4148 QDBusConnection::sessionBus().connect(
4249 "com.canonical.UnityGreeter",
4350 "/list",
@@ -57,6 +64,12 @@ private Q_SLOTS:
5764 view->show();
5865 QTest::qWaitForWindowExposed(view);
5966
67+ dbusMain = new QDBusInterface("com.canonical.UnityGreeter",
68+ "/",
69+ "com.canonical.UnityGreeter",
70+ QDBusConnection::sessionBus(), view);
71+ QVERIFY(dbusMain->isValid());
72+
6073 dbusList = new QDBusInterface("com.canonical.UnityGreeter",
6174 "/list",
6275 "com.canonical.UnityGreeter.List",
@@ -155,9 +168,36 @@ private Q_SLOTS:
155168 QVERIFY(arguments.at(1).toMap()["EntryIsLocked"] == false);
156169 }
157170
171+ void testIsActive()
172+ {
173+ QVERIFY(!greeter->isActive());
174+ QVERIFY(!dbusMain->property("IsActive").toBool());
175+
176+ QSignalSpy spy(this, SIGNAL(PropertiesChangedRelay(QString, QVariantMap, QStringList)));
177+ greeter->setIsActive(true);
178+ spy.wait();
179+
180+ QVERIFY(greeter->isActive());
181+ QVERIFY(dbusMain->property("IsActive").toBool());
182+
183+ QCOMPARE(spy.count(), 1);
184+ QList<QVariant> arguments = spy.takeFirst();
185+ QCOMPARE(arguments.at(0).toString(), QString("com.canonical.UnityGreeter"));
186+ QVERIFY(arguments.at(1).toMap().contains("IsActive"));
187+ QVERIFY(arguments.at(1).toMap()["IsActive"].toBool());
188+ }
189+
190+ void testShowGreeter()
191+ {
192+ // Just confirm the call exists and doesn't fail
193+ QDBusReply<void> reply = dbusMain->call("ShowGreeter");
194+ QVERIFY(reply.isValid());
195+ }
196+
158197private:
159198 QQuickView *view;
160199 Greeter *greeter;
200+ QDBusInterface *dbusMain;
161201 QDBusInterface *dbusList;
162202};
163203
tests/qmltests/CMakeLists.txt+2−2
@@ -19,8 +19,8 @@ set(qmltest_DEFAULT_TARGETS qmluitests)
1919set(qmltest_DEFAULT_NO_ADD_TEST TRUE)
2020set(qmltest_DEFAULT_PROPERTIES ENVIRONMENT "LC_ALL=C")
2121
22−add_qml_test(. Shell IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks
23− ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
22+add_qml_test(. Shell ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
23+add_qml_test(. ShellWithPin ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single-pin")
2424add_qml_test(Components Carousel)
2525add_qml_test(Components DraggingArea)
2626add_qml_test(Components EdgeDemoOverlay)
tests/qmltests/Components/tst_LazyImage.qml−1
@@ -152,7 +152,6 @@ Rectangle {
152152
153153 function test_lazyimage(data) {
154154 data.func();
155− waitForRendering(baseRect);
156155
157156 if (data.transition) {
158157 // wait for the transition to complete
tests/qmltests/Dash/Apps/tst_RunningApplicationsGrid.qml+2−2
@@ -30,7 +30,7 @@ Rectangle {
3030 ApplicationManager.stopApplication(ApplicationManager.get(0).appId)
3131 }
3232
33− ApplicationManager.startApplication("phone-app");
33+ ApplicationManager.startApplication("dialer-app");
3434 ApplicationManager.startApplication("webbrowser-app");
3535 }
3636
@@ -70,7 +70,7 @@ Rectangle {
7070 verify(browserTile != undefined)
7171 browserTile.onPressAndHold.connect(onBrowserLongPressed)
7272
73− phoneTile = findChild(runningApplicationsGrid, "runningAppTile Phone")
73+ phoneTile = findChild(runningApplicationsGrid, "runningAppTile Dialer")
7474 verify(phoneTile != undefined)
7575 phoneTile.onPressAndHold.connect(onPhoneLongPressed)
7676
tests/qmltests/Greeter/tst_Lockscreen.qml+1−1
@@ -57,7 +57,7 @@ Rectangle {
5757 target: LightDM.Greeter
5858
5959 onShowPrompt: {
60− if (text.indexOf("PIN") >= 0) {
60+ if (text === "PIN") {
6161 pinPadCheckBox.checked = false
6262 } else {
6363 pinPadCheckBox.checked = true
tests/qmltests/Launcher/tst_Launcher.qml+2−2
@@ -115,7 +115,7 @@ Item {
115115 /* If I click on the icon of an application on the launcher
116116 Launcher::launcherApplicationSelected signal should be emitted with the
117117 corresponding desktop file. E.g. clicking on phone icon should yield
118− launcherApplicationSelected("[...]phone-app.desktop") */
118+ launcherApplicationSelected("[...]dialer-app.desktop") */
119119 function test_clickingOnAppIconCausesSignalEmission() {
120120 launcher.lastSelectedApplication = ""
121121
@@ -131,7 +131,7 @@ Item {
131131 mouseClick(appIcon, appIcon.width/2, appIcon.height/2)
132132
133133 tryCompare(launcher, "lastSelectedApplication",
134− "phone-app")
134+ "dialer-app")
135135
136136 // Tapping on an application icon also dismisses the launcher
137137 revealer.waitUntilLauncherDisappears()
tests/qmltests/Notifications/tst_VisualSnapDecisionsQueue.qml+1−1
@@ -67,7 +67,7 @@ Row {
6767 summary: "Incoming call",
6868 body: "Frank Zappa\n+44 (0)7736 027340",
6969 icon: "../graphics/avatars/funky.png",
70− secondaryIcon: "../graphics/applicationIcons/phone-app.png",
70+ secondaryIcon: "../graphics/applicationIcons/dialer-app.png",
7171 actions: [{ id: "pickup_id", label: "Pick up"},
7272 { id: "decline_1_id", label: "Decline"},
7373 { id: "decline_2_id", label: "Can't talk now, what's up?"},
tests/qmltests/tst_Shell.qml+26−1
@@ -20,6 +20,7 @@
2020import QtQuick 2.0
2121import QtTest 1.0
2222import GSettings 1.0
23+import LightDM 0.1 as LightDM
2324import Unity.Application 0.1
2425import Unity.Test 0.1 as UT
2526import Powerd 0.1
@@ -50,6 +51,11 @@ Item {
5051 id: shell
5152 }
5253
54+ SignalSpy {
55+ id: sessionSpy
56+ signalName: "sessionStarted"
57+ }
58+
5359 UT.UnityTestCase {
5460 name: "Shell"
5561 when: windowShown
@@ -91,6 +97,8 @@ Item {
9197 verify(ok);
9298
9399 swipeAwayGreeter();
100+
101+ sessionSpy.target = findChild(shell, "greeter")
94102 }
95103
96104 function cleanup() {
@@ -195,7 +203,7 @@ Item {
195203 tryCompare(mainApp, "state", ApplicationInfo.Running);
196204
197205 // Try to suspend while proximity is engaged...
198− Powerd.displayPowerStateChange(Powerd.Off, Powerd.UseProximity);
206+ Powerd.displayPowerStateChange(Powerd.Off, Powerd.Proximity);
199207 tryCompare(greeter, "showProgress", 0);
200208
201209 // Now really suspend
@@ -556,5 +564,22 @@ Item {
556564 tryCompare(greeter, "showProgress", 0)
557565 waitUntilApplicationWindowIsFullyVisible()
558566 }
567+
568+ function test_showGreeterDBusCall() {
569+ var greeter = findChild(shell, "greeter")
570+ tryCompare(greeter, "showProgress", 0)
571+ LightDM.Greeter.showGreeter()
572+ tryCompare(greeter, "showProgress", 1)
573+ }
574+
575+ function test_login() {
576+ var greeter = findChild(shell, "greeter")
577+ greeter.show()
578+ tryCompare(greeter, "showProgress", 1)
579+
580+ tryCompare(sessionSpy, "count", 0)
581+ swipeAwayGreeter()
582+ tryCompare(sessionSpy, "count", 1)
583+ }
559584 }
560585}
tests/qmltests/tst_ShellWithPin.qmlnew file+202
@@ -0,0 +1,202 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
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.
7+ *
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.
12+ *
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/>.
15+ */
16+
17+import QtQuick 2.0
18+import QtTest 1.0
19+import GSettings 1.0
20+import LightDM 0.1 as LightDM
21+import Unity.Application 0.1
22+import Unity.Test 0.1 as UT
23+import Powerd 0.1
24+
25+import "../../qml"
26+
27+Item {
28+ width: shell.width
29+ height: shell.height
30+
31+ QtObject {
32+ id: applicationArguments
33+
34+ function hasGeometry() {
35+ return false;
36+ }
37+
38+ function width() {
39+ return 0;
40+ }
41+
42+ function height() {
43+ return 0;
44+ }
45+ }
46+
47+ Shell {
48+ id: shell
49+ }
50+
51+ SignalSpy {
52+ id: sessionSpy
53+ signalName: "sessionStarted"
54+ }
55+
56+ UT.UnityTestCase {
57+ name: "ShellWithPin"
58+ when: windowShown
59+
60+ function initTestCase() {
61+ var ok = false;
62+ var attempts = 0;
63+ var maxAttempts = 1000;
64+
65+ // Qt loads a qml scene asynchronously. So early on, some findChild() calls made in
66+ // tests may fail because the desired child item wasn't loaded yet.
67+ // Thus here we try to ensure the scene has been fully loaded before proceeding with the tests.
68+ // As I couldn't find an API in QQuickView & friends to tell me that the scene is 100% loaded
69+ // (all items instantiated, etc), I resort to checking the existence of some key items until
70+ // repeatedly until they're all there.
71+ do {
72+ var dashContentList = findChild(shell, "dashContentList");
73+ waitForRendering(dashContentList);
74+ var homeLoader = findChild(dashContentList, "clickscope loader");
75+ ok = homeLoader !== null
76+ && homeLoader.item !== undefined;
77+
78+ var greeter = findChild(shell, "greeter");
79+ ok &= greeter !== null;
80+
81+ var launcherPanel = findChild(shell, "launcherPanel");
82+ ok &= launcherPanel !== null;
83+
84+ attempts++;
85+ if (!ok) {
86+ console.log("Attempt " + attempts + " failed. Waiting a bit before trying again.");
87+ // wait a bit before retrying
88+ wait(100);
89+ } else {
90+ console.log("All seem fine after " + attempts + " attempts.");
91+ }
92+ } while (!ok && attempts <= maxAttempts);
93+
94+ verify(ok);
95+
96+ sessionSpy.target = findChild(shell, "greeter")
97+ }
98+
99+ function init() {
100+ swipeAwayGreeter()
101+ }
102+
103+ function cleanup() {
104+ LightDM.Greeter.showGreeter()
105+ var greeter = findChild(shell, "greeter")
106+ tryCompare(greeter, "showProgress", 1)
107+
108+ // kill all (fake) running apps
109+ killApps()
110+ }
111+
112+ function killApps() {
113+ while (ApplicationManager.count > 0) {
114+ ApplicationManager.stopApplication(ApplicationManager.get(0).appId)
115+ }
116+ compare(ApplicationManager.count, 0)
117+ }
118+
119+ function swipeAwayGreeter() {
120+ var greeter = findChild(shell, "greeter");
121+ tryCompare(greeter, "showProgress", 1);
122+
123+ var touchX = shell.width - (shell.edgeSize / 2);
124+ var touchY = shell.height / 2;
125+ touchFlick(shell, touchX, touchY, shell.width * 0.1, touchY);
126+
127+ // wait until the animation has finished
128+ tryCompare(greeter, "showProgress", 0);
129+
130+ // and for pin to be ready
131+ var lockscreen = findChild(shell, "lockscreen");
132+ var pinPadLoader = findChild(lockscreen, "pinPadLoader");
133+ tryCompare(pinPadLoader, "status", Loader.Ready)
134+ waitForRendering(lockscreen)
135+ }
136+
137+ function enterPin(pin) {
138+ var inputField = findChild(shell, "pinentryField")
139+ for (var i = 0; i < pin.length; ++i) {
140+ var character = pin.charAt(i)
141+ var button = findChild(shell, "pinPadButton" + character)
142+ mouseClick(button, units.gu(1), units.gu(1))
143+ }
144+ }
145+
146+ function test_login() {
147+ tryCompare(sessionSpy, "count", 0)
148+ enterPin("1234")
149+ tryCompare(sessionSpy, "count", 1)
150+ }
151+
152+ function test_emergencyCall() {
153+ var greeter = findChild(shell, "greeter")
154+ var lockscreen = findChild(shell, "lockscreen")
155+ var emergencyButton = findChild(lockscreen, "emergencyCallIcon")
156+ var panel = findChild(shell, "panel")
157+ var indicators = findChild(shell, "indicators")
158+ var launcher = findChild(shell, "launcher")
159+ var stage = findChild(shell, "stage")
160+
161+ mouseClick(emergencyButton, units.gu(1), units.gu(1))
162+
163+ tryCompare(lockscreen, "shown", false)
164+ tryCompare(greeter, "fakeActiveForApp", "dialer-app")
165+ tryCompare(panel, "fullscreenMode", true)
166+ tryCompare(indicators, "available", false)
167+ tryCompare(launcher, "available", false)
168+ tryCompare(stage, "spreadEnabled", false)
169+
170+ // Cancel emergency mode, and go back to normal
171+ LightDM.Greeter.showGreeter()
172+
173+ tryCompare(lockscreen, "shown", true)
174+ tryCompare(greeter, "shown", true)
175+ tryCompare(greeter, "fakeActiveForApp", "")
176+ tryCompare(panel, "fullscreenMode", false)
177+ tryCompare(indicators, "available", true)
178+ tryCompare(launcher, "available", true)
179+ tryCompare(stage, "spreadEnabled", true)
180+ }
181+
182+ function test_emergencyCallCrash() {
183+ var lockscreen = findChild(shell, "lockscreen")
184+ var emergencyButton = findChild(lockscreen, "emergencyCallIcon")
185+ mouseClick(emergencyButton, units.gu(1), units.gu(1))
186+
187+ tryCompare(lockscreen, "shown", false)
188+ killApps() // kill dialer-app, as if it crashed
189+ tryCompare(lockscreen, "shown", true)
190+ }
191+
192+ function test_emergencyCallAppLaunch() {
193+ var lockscreen = findChild(shell, "lockscreen")
194+ var emergencyButton = findChild(lockscreen, "emergencyCallIcon")
195+ mouseClick(emergencyButton, units.gu(1), units.gu(1))
196+
197+ tryCompare(lockscreen, "shown", false)
198+ ApplicationManager.startApplication("gallery-app", ApplicationManager.NoFlag)
199+ tryCompare(lockscreen, "shown", true)
200+ }
201+ }
202+}