on xenial help sign in
Merge dialer-above branch
c6e3263Michael Terry
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+
1unity8 (7.89+14.10.20140624-0ubuntu1) utopic; urgency=low
34unity8 (7.89+14.10.20140624-0ubuntu1) utopic; urgency=low
2
35
3 [ Ying-Chun Liu ]
36 [ Ying-Chun Liu ]
debian/control+1−1
@@ -18,7 +18,7 @@ Build-Depends: cmake,
18 libpulse-dev,
18 libpulse-dev,
19 libqmenumodel-dev (>= 0.2.7),
19 libqmenumodel-dev (>= 0.2.7),
20 libqt5xmlpatterns5-dev,
20 libqt5xmlpatterns5-dev,
21− libunity-api-dev (>= 7.82),
21+ libunity-api-dev (>= 7.83),
22 libunity-mir-dev,
22 libunity-mir-dev,
23 libusermetricsoutput1-dev,
23 libusermetricsoutput1-dev,
24 libxcb1-dev,
24 libxcb1-dev,
plugins/Dash/CardCreator.js+7−4
@@ -113,7 +113,7 @@ var kOverlayLoaderCode = 'Loader { \n\
113 visible: showHeader && status == Loader.Ready; \n\
113 visible: showHeader && status == Loader.Ready; \n\
114 sourceComponent: ShaderEffect { \n\
114 sourceComponent: ShaderEffect { \n\
115 id: overlay; \n\
115 id: overlay; \n\
116− height: fixedHeaderHeight > 0 ? fixedHeaderHeight + units.gu(1) * 2 : headerHeight; \n\
116+ height: (fixedHeaderHeight > 0 ? fixedHeaderHeight : headerHeight) + units.gu(2); \n\
117 opacity: 0.6; \n\
117 opacity: 0.6; \n\
118 property var source: ShaderEffectSource { \n\
118 property var source: ShaderEffectSource { \n\
119 id: shaderSource; \n\
119 id: shaderSource; \n\
@@ -363,11 +363,11 @@ function cardString(template, components) {
363 }
363 }
364 }
364 }
365 var headerLeftAnchor;
365 var headerLeftAnchor;
366− var headerLeftAnchorHasMagin = false;
366+ var headerLeftAnchorHasMargin = false;
367 if (isHorizontal && hasArt) {
367 if (isHorizontal && hasArt) {
368 headerLeftAnchor = 'left: artShapeHolder.right; \n\
368 headerLeftAnchor = 'left: artShapeHolder.right; \n\
369 leftMargin: units.gu(1);\n';
369 leftMargin: units.gu(1);\n';
370− headerLeftAnchorHasMagin = true;
370+ headerLeftAnchorHasMargin = true;
371 } else {
371 } else {
372 headerLeftAnchor = 'left: parent.left;\n';
372 headerLeftAnchor = 'left: parent.left;\n';
373 }
373 }
@@ -392,7 +392,7 @@ function cardString(template, components) {
392 if (!hasHeaderRow) {
392 if (!hasHeaderRow) {
393 anchors += headerLeftAnchor;
393 anchors += headerLeftAnchor;
394 anchors += headerVerticalAnchors;
394 anchors += headerVerticalAnchors;
395− if (!headerLeftAnchorHasMagin) {
395+ if (!headerLeftAnchorHasMargin) {
396 anchors += 'leftMargin: units.gu(1);\n'
396 anchors += 'leftMargin: units.gu(1);\n'
397 }
397 }
398 } else {
398 } else {
@@ -444,6 +444,9 @@ function cardString(template, components) {
444 titleAnchors = "right: parent.right;";
444 titleAnchors = "right: parent.right;";
445 titleAnchors += headerLeftAnchor;
445 titleAnchors += headerLeftAnchor;
446 titleAnchors += headerVerticalAnchors;
446 titleAnchors += headerVerticalAnchors;
447+ if (!headerLeftAnchorHasMargin) {
448+ titleAnchors += 'leftMargin: units.gu(1);\n'
449+ }
447 }
450 }
448 subtitleAnchors = 'left: titleLabel.left; \n\
451 subtitleAnchors = 'left: titleLabel.left; \n\
449 leftMargin: titleLabel.leftMargin; \n\
452 leftMargin: titleLabel.leftMargin; \n\
plugins/LightDM/CMakeLists.txt+1
@@ -15,6 +15,7 @@ include_directories(
15
15
16set(QMLPLUGIN_SRC
16set(QMLPLUGIN_SRC
17 ../Utils/qsortfilterproxymodelqml.cpp # FIXME evaluate a more generic approach for using other plugins
17 ../Utils/qsortfilterproxymodelqml.cpp # FIXME evaluate a more generic approach for using other plugins
18+ DBusGreeter.cpp
18 DBusGreeterList.cpp
19 DBusGreeterList.cpp
19 Greeter.cpp
20 Greeter.cpp
20 plugin.cpp
21 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:
25 explicit GreeterPrivate(Greeter *parent);
25 explicit GreeterPrivate(Greeter *parent);
26
26
27 QLightDM::Greeter *m_greeter;
27 QLightDM::Greeter *m_greeter;
28+ bool m_active;
28 bool wasPrompted;
29 bool wasPrompted;
29 bool promptless;
30 bool promptless;
30
31
@@ -38,6 +39,7 @@ private:
38
39
39GreeterPrivate::GreeterPrivate(Greeter* parent)
40GreeterPrivate::GreeterPrivate(Greeter* parent)
40 : m_greeter(new QLightDM::Greeter(parent)),
41 : m_greeter(new QLightDM::Greeter(parent)),
42+ m_active(false),
41 wasPrompted(false),
43 wasPrompted(false),
42 promptless(false),
44 promptless(false),
43 q_ptr(parent)
45 q_ptr(parent)
@@ -60,6 +62,21 @@ Greeter::Greeter(QObject* parent)
60 d->m_greeter->connectSync();
62 d->m_greeter->connectSync();
61}
63}
62
64
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+
63bool Greeter::isAuthenticated() const
80bool Greeter::isAuthenticated() const
64{
81{
65 Q_D(const Greeter);
82 Q_D(const Greeter);
plugins/LightDM/Greeter.h+5
@@ -34,6 +34,7 @@ class Greeter : public QObject
34{
34{
35 Q_OBJECT
35 Q_OBJECT
36
36
37+ Q_PROPERTY(bool active READ isActive WRITE setIsActive NOTIFY isActiveChanged)
37 Q_PROPERTY(bool authenticated READ isAuthenticated)
38 Q_PROPERTY(bool authenticated READ isAuthenticated)
38 Q_PROPERTY(QString authenticationUser READ authenticationUser NOTIFY authenticationUserChanged)
39 Q_PROPERTY(QString authenticationUser READ authenticationUser NOTIFY authenticationUserChanged)
39 Q_PROPERTY(bool promptless READ promptless NOTIFY promptlessChanged)
40 Q_PROPERTY(bool promptless READ promptless NOTIFY promptlessChanged)
@@ -41,6 +42,7 @@ class Greeter : public QObject
41public:
42public:
42 explicit Greeter(QObject* parent=0);
43 explicit Greeter(QObject* parent=0);
43
44
45+ bool isActive() const;
44 bool isAuthenticated() const;
46 bool isAuthenticated() const;
45 QString authenticationUser() const;
47 QString authenticationUser() const;
46 bool promptless() const;
48 bool promptless() const;
@@ -49,13 +51,16 @@ public Q_SLOTS:
49 void authenticate(const QString &username=QString());
51 void authenticate(const QString &username=QString());
50 void respond(const QString &response);
52 void respond(const QString &response);
51 bool startSessionSync(const QString &session=QString());
53 bool startSessionSync(const QString &session=QString());
54+ void setIsActive(bool isActive);
52
55
53Q_SIGNALS:
56Q_SIGNALS:
54 void showMessage(const QString &text, bool isError);
57 void showMessage(const QString &text, bool isError);
55 void showPrompt(const QString &text, bool isSecret);
58 void showPrompt(const QString &text, bool isSecret);
56 void authenticationComplete();
59 void authenticationComplete();
57 void authenticationUserChanged(const QString &user);
60 void authenticationUserChanged(const QString &user);
61+ void isActiveChanged();
58 void promptlessChanged();
62 void promptlessChanged();
63+ void showGreeter();
59
64
60 // This signal is emitted by external agents like indicators, and the UI
65 // This signal is emitted by external agents like indicators, and the UI
61 // should switch to this user if possible.
66 // should switch to this user if possible.
plugins/LightDM/plugin.cpp+3
@@ -18,6 +18,7 @@
18 */
18 */
19
19
20#include "plugin.h"
20#include "plugin.h"
21+#include "DBusGreeter.h"
21#include "DBusGreeterList.h"
22#include "DBusGreeterList.h"
22#include "Greeter.h"
23#include "Greeter.h"
23#include "UsersModel.h"
24#include "UsersModel.h"
@@ -39,6 +40,8 @@ static QObject *greeter_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
39
40
40 Greeter *greeter = new Greeter();
41 Greeter *greeter = new Greeter();
41 QDBusConnection connection = QDBusConnection::sessionBus();
42 QDBusConnection connection = QDBusConnection::sessionBus();
43+ DBusGreeter *root = new DBusGreeter(greeter, connection, "/");
44+ connection.registerObject("/", root, QDBusConnection::ExportScriptableContents);
42 DBusGreeterList *list = new DBusGreeterList(greeter, connection, GREETER_LIST_DBUS_PATH);
45 DBusGreeterList *list = new DBusGreeterList(greeter, connection, GREETER_LIST_DBUS_PATH);
43 connection.registerObject(GREETER_LIST_DBUS_PATH, list, QDBusConnection::ExportScriptableContents);
46 connection.registerObject(GREETER_LIST_DBUS_PATH, list, QDBusConnection::ExportScriptableContents);
44 connection.registerService(GREETER_DBUS_SERVICE);
47 connection.registerService(GREETER_DBUS_SERVICE);
plugins/Powerd/Powerd.cpp+16−16
@@ -19,35 +19,35 @@
19#include "Powerd.h"
19#include "Powerd.h"
20#include <QDBusPendingCall>
20#include <QDBusPendingCall>
21
21
22−void autoBrightnessChanged(GSettings *settings, const gchar *key, QDBusInterface *powerd)
22+void autoBrightnessChanged(GSettings *settings, const gchar *key, QDBusInterface *unityScreen)
23{
23{
24 bool value = g_settings_get_boolean(settings, key);
24 bool value = g_settings_get_boolean(settings, key);
25− powerd->asyncCall("userAutobrightnessEnable", QVariant(value));
25+ unityScreen->asyncCall("userAutobrightnessEnable", QVariant(value));
26}
26}
27
27
28Powerd::Powerd(QObject* parent)
28Powerd::Powerd(QObject* parent)
29 : QObject(parent),
29 : QObject(parent),
30− powerd(NULL)
30+ unityScreen(NULL)
31{
31{
32− powerd = new QDBusInterface("com.canonical.powerd",
32+ unityScreen = new QDBusInterface("com.canonical.Unity.Screen",
33− "/com/canonical/powerd",
33+ "/com/canonical/Unity/Screen",
34− "com.canonical.powerd",
34+ "com.canonical.Unity.Screen",
35− QDBusConnection::SM_BUSNAME(), this);
35+ QDBusConnection::SM_BUSNAME(), this);
36
36
37− powerd->connection().connect("com.canonical.powerd",
37+ unityScreen->connection().connect("com.canonical.Unity.Screen",
38− "/com/canonical/powerd",
38+ "/com/canonical/Unity/Screen",
39− "com.canonical.powerd",
39+ "com.canonical.Unity.Screen",
40− "DisplayPowerStateChange",
40+ "DisplayPowerStateChange",
41− this,
41+ this,
42− SIGNAL(displayPowerStateChange(int, unsigned int)));
42+ SIGNAL(displayPowerStateChange(int, int)));
43
43
44 systemSettings = g_settings_new("com.ubuntu.touch.system");
44 systemSettings = g_settings_new("com.ubuntu.touch.system");
45− g_signal_connect(systemSettings, "changed::auto-brightness", G_CALLBACK(autoBrightnessChanged), powerd);
45+ g_signal_connect(systemSettings, "changed::auto-brightness", G_CALLBACK(autoBrightnessChanged), unityScreen);
46− autoBrightnessChanged(systemSettings, "auto-brightness", powerd);
46+ autoBrightnessChanged(systemSettings, "auto-brightness", unityScreen);
47}
47}
48
48
49Powerd::~Powerd()
49Powerd::~Powerd()
50{
50{
51− g_signal_handlers_disconnect_by_data(systemSettings, powerd);
51+ g_signal_handlers_disconnect_by_data(systemSettings, unityScreen);
52 g_object_unref(systemSettings);
52 g_object_unref(systemSettings);
53}
53}
plugins/Powerd/Powerd.h+8−8
@@ -28,15 +28,15 @@ class Powerd: public QObject
28{
28{
29 Q_OBJECT
29 Q_OBJECT
30 Q_ENUMS(Status)
30 Q_ENUMS(Status)
31− Q_FLAGS(DisplayFlag DisplayFlags)
31+ Q_ENUMS(DisplayStateChangeReason)
32
32
33public:
33public:
34− enum DisplayFlag {
34+ enum DisplayStateChangeReason {
35− UseProximity = 1, // Use proximity sensor to override screen state
35+ Unknown = 0,
36− DisableAutoBrightness = 2, // Force autobrightness to be disabled
36+ Inactivity = 1, // Display changed state due to inactivity
37− Bright = 4, // Request the screen to stay bright
37+ PowerKey = 2, // Display changed state due to user pressing power key
38+ Proximity = 3, // Display changed state due to proximity events
38 };
39 };
39− Q_DECLARE_FLAGS(DisplayFlags, DisplayFlag)
40
40
41 enum Status {
41 enum Status {
42 Off,
42 Off,
@@ -47,10 +47,10 @@ public:
47 ~Powerd();
47 ~Powerd();
48
48
49Q_SIGNALS:
49Q_SIGNALS:
50− void displayPowerStateChange(int status, unsigned int flags);
50+ void displayPowerStateChange(int status, int reason);
51
51
52private:
52private:
53− QDBusInterface *powerd;
53+ QDBusInterface *unityScreen;
54 GSettings *systemSettings;
54 GSettings *systemSettings;
55};
55};
56
56
po/es.po+7−7
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2014-06-13 09:55+0200\n"
10"POT-Creation-Date: 2014-06-13 09:55+0200\n"
11−"PO-Revision-Date: 2014-06-02 06:28+0000\n"
11+"PO-Revision-Date: 2014-06-26 03:08+0000\n"
12−"Last-Translator: benjisp94 <benjisp94@gmail.com>\n"
12+"Last-Translator: Adolfo Jayme <fitoschido@gmail.com>\n"
13"Language-Team: Spanish <es@li.org>\n"
13"Language-Team: Spanish <es@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-06-17 06:51+0000\n"
17+"X-Launchpad-Export-Date: 2014-06-27 07:13+0000\n"
18−"X-Generator: Launchpad (build 17045)\n"
18+"X-Generator: Launchpad (build 17077)\n"
19
19
20#: plugins/Unity/Launcher/launcheritem.cpp:43
20#: plugins/Unity/Launcher/launcheritem.cpp:43
21#: plugins/Unity/Launcher/launcheritem.cpp:73
21#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -83,7 +83,7 @@ msgstr "Llamada de emergencia"
83
83
84#: qml/Components/Lockscreen.qml:231
84#: qml/Components/Lockscreen.qml:231
85msgid "OK"
85msgid "OK"
86−msgstr ""
86+msgstr "Aceptar"
87
87
88#: qml/Components/PageHeader.qml:365
88#: qml/Components/PageHeader.qml:365
89msgid "Recent searches"
89msgid "Recent searches"
@@ -100,11 +100,11 @@ msgstr "Hola"
100
100
101#: qml/Components/PinLockscreen.qml:198
101#: qml/Components/PinLockscreen.qml:198
102msgid "CANCEL"
102msgid "CANCEL"
103−msgstr ""
103+msgstr "CANCELAR"
104
104
105#: qml/Components/PinLockscreen.qml:216
105#: qml/Components/PinLockscreen.qml:216
106msgid "DONE"
106msgid "DONE"
107−msgstr ""
107+msgstr "HECHO"
108
108
109#: qml/Components/SeeMore.qml:35
109#: qml/Components/SeeMore.qml:35
110msgid "See more"
110msgid "See more"
qml/Components/Lockscreen.qml+17−5
@@ -186,6 +186,17 @@ Showable {
186 }
186 }
187
187
188 Column {
188 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+
189 anchors {
200 anchors {
190 left: parent.left
201 left: parent.left
191 bottom: parent.bottom
202 bottom: parent.bottom
@@ -203,11 +214,6 @@ Showable {
203 name: "phone-app-call-symbolic"
214 name: "phone-app-call-symbolic"
204 color: "#f3f3e7"
215 color: "#f3f3e7"
205 opacity: 0.6
216 opacity: 0.6
206−
207− MouseArea {
208− anchors.fill: parent
209− onClicked: root.emergencyCall()
210− }
211 }
217 }
212
218
213 Label {
219 Label {
@@ -219,6 +225,12 @@ Showable {
219 }
225 }
220 }
226 }
221
227
228+ MouseArea {
229+ anchors.fill: emergencyCallColumn
230+ onClicked: root.emergencyCall()
231+ enabled: emergencyCallColumn.visible
232+ }
233+
222 Component {
234 Component {
223 id: infoPopupComponent
235 id: infoPopupComponent
224 Dialog {
236 Dialog {
qml/Dash/CardVerticalJournal.qml−3
@@ -67,11 +67,8 @@ DashRenderer {
67 id: loader
67 id: loader
68 sourceComponent: cardTool.cardComponent
68 sourceComponent: cardTool.cardComponent
69 width: cardTool.cardWidth
69 width: cardTool.cardWidth
70− anchors.horizontalCenter: parent.horizontalCenter
71 onLoaded: {
70 onLoaded: {
72 item.objectName = "delegate" + index;
71 item.objectName = "delegate" + index;
73− item.width = Qt.binding(function() { return cardTool.cardWidth; });
74− item.height = Qt.binding(function() { return cardTool.cardHeight; });
75 item.fixedArtShapeSize = Qt.binding(function() { return cardTool.artShapeSize; });
72 item.fixedArtShapeSize = Qt.binding(function() { return cardTool.artShapeSize; });
76 item.fixedHeaderHeight = Qt.binding(function() { return cardTool.headerHeight; });
73 item.fixedHeaderHeight = Qt.binding(function() { return cardTool.headerHeight; });
77 item.cardData = Qt.binding(function() { return model; });
74 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 {
257
257
258 onShowMessage: {
258 onShowMessage: {
259 // inefficient, but we only rarely deal with messages
259 // 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>")
261 if (isError)
261 if (isError)
262− text = "<font color=\"#df382c\">" + text + "</font>"
262+ html = "<font color=\"#df382c\">" + html + "</font>"
263 if (infoLabel.text == "")
263 if (infoLabel.text == "")
264− infoLabel.text = text;
264+ infoLabel.text = html
265 else
265 else
266− infoLabel.text = infoLabel.text + "<br>" + text;
266+ infoLabel.text = infoLabel.text + "<br>" + html
267 }
267 }
268
268
269 onShowPrompt: {
269 onShowPrompt: {
qml/Shell.qml+91−27
@@ -136,7 +136,7 @@ FocusScope {
136 id: dash
136 id: dash
137 objectName: "dash"
137 objectName: "dash"
138
138
139− available: !greeter.shown && !lockscreen.shown
139+ available: !LightDM.Greeter.active
140 hides: [stages, launcher, panel.indicators]
140 hides: [stages, launcher, panel.indicators]
141 shown: disappearingAnimationProgress !== 1.0 && greeterWrapper.showProgress !== 1.0
141 shown: disappearingAnimationProgress !== 1.0 && greeterWrapper.showProgress !== 1.0
142 enabled: disappearingAnimationProgress === 0.0 && greeterWrapper.showProgress === 0.0 && edgeDemo.dashEnabled
142 enabled: disappearingAnimationProgress === 0.0 && greeterWrapper.showProgress === 0.0 && edgeDemo.dashEnabled
@@ -199,7 +199,7 @@ FocusScope {
199
199
200 x: {
200 x: {
201 if (shown) {
201 if (shown) {
202− if (overlayMode || locked) {
202+ if (overlayMode || locked || greeter.fakeActiveForApp !== "") {
203 return 0;
203 return 0;
204 }
204 }
205 return launcher.progress
205 return launcher.progress
@@ -244,10 +244,17 @@ FocusScope {
244 target: ApplicationManager
244 target: ApplicationManager
245
245
246 onFocusRequested: {
246 onFocusRequested: {
247+ if (greeter.fakeActiveForApp !== "" && greeter.fakeActiveForApp !== appId) {
248+ lockscreen.show();
249+ }
250+ greeter.hide();
247 stages.show(true);
251 stages.show(true);
248 }
252 }
249
253
250 onFocusedApplicationIdChanged: {
254 onFocusedApplicationIdChanged: {
255+ if (greeter.fakeActiveForApp !== "" && greeter.fakeActiveForApp !== ApplicationManager.focusedApplicationId) {
256+ lockscreen.show();
257+ }
251 if (ApplicationManager.focusedApplicationId.length > 0) {
258 if (ApplicationManager.focusedApplicationId.length > 0) {
252 stages.show(false);
259 stages.show(false);
253 } else {
260 } else {
@@ -298,6 +305,11 @@ FocusScope {
298
305
299 source: shell.sideStageEnabled ? "Stages/StageWithSideStage.qml" : "Stages/PhoneStage.qml"
306 source: shell.sideStageEnabled ? "Stages/StageWithSideStage.qml" : "Stages/PhoneStage.qml"
300
307
308+ Binding {
309+ target: applicationsDisplayLoader.item
310+ property: "objectName"
311+ value: "stage"
312+ }
301 Binding {
313 Binding {
302 target: applicationsDisplayLoader.item
314 target: applicationsDisplayLoader.item
303 property: "moving"
315 property: "moving"
@@ -313,6 +325,11 @@ FocusScope {
313 property: "dragAreaWidth"
325 property: "dragAreaWidth"
314 value: shell.edgeSize
326 value: shell.edgeSize
315 }
327 }
328+ Binding {
329+ target: applicationsDisplayLoader.item
330+ property: "spreadEnabled"
331+ value: greeter.fakeActiveForApp === "" // to support emergency dialer hack
332+ }
316 }
333 }
317 }
334 }
318
335
@@ -337,6 +354,13 @@ FocusScope {
337
354
338 onEntered: LightDM.Greeter.respond(passphrase);
355 onEntered: LightDM.Greeter.respond(passphrase);
339 onCancel: greeter.show()
356 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 = ""
340
364
341 Component.onCompleted: {
365 Component.onCompleted: {
342 if (LightDM.Users.count == 1) {
366 if (LightDM.Users.count == 1) {
@@ -348,6 +372,8 @@ FocusScope {
348 Connections {
372 Connections {
349 target: LightDM.Greeter
373 target: LightDM.Greeter
350
374
375+ onShowGreeter: greeter.show()
376+
351 onShowPrompt: {
377 onShowPrompt: {
352 if (LightDM.Users.count == 1) {
378 if (LightDM.Users.count == 1) {
353 // TODO: There's no better way for now to determine if its a PIN or a passphrase.
379 // TODO: There's no better way for now to determine if its a PIN or a passphrase.
@@ -367,12 +393,19 @@ FocusScope {
367 }
393 }
368 if (LightDM.Greeter.authenticated) {
394 if (LightDM.Greeter.authenticated) {
369 lockscreen.hide();
395 lockscreen.hide();
396+ greeter.login();
370 } else {
397 } else {
371 lockscreen.clear(true);
398 lockscreen.clear(true);
372 }
399 }
373 }
400 }
374 }
401 }
375
402
403+ Binding {
404+ target: LightDM.Greeter
405+ property: "active"
406+ value: greeter.shown || lockscreen.shown || greeter.fakeActiveForApp != ""
407+ }
408+
376 Rectangle {
409 Rectangle {
377 anchors.fill: parent
410 anchors.fill: parent
378 color: "black"
411 color: "black"
@@ -393,11 +426,16 @@ FocusScope {
393 }
426 }
394
427
395 readonly property real showProgress: MathUtils.clamp((1 - x/width) + greeter.showProgress - 1, 0, 1)
428 readonly property real showProgress: MathUtils.clamp((1 - x/width) + greeter.showProgress - 1, 0, 1)
429+ onShowProgressChanged: if (LightDM.Greeter.promptless && showProgress === 0) greeter.login()
396
430
397 Greeter {
431 Greeter {
398 id: greeter
432 id: greeter
399 objectName: "greeter"
433 objectName: "greeter"
400
434
435+ signal sessionStarted() // helpful for tests
436+
437+ property string fakeActiveForApp: ""
438+
401 available: true
439 available: true
402 hides: [launcher, panel.indicators]
440 hides: [launcher, panel.indicators]
403 shown: true
441 shown: true
@@ -409,14 +447,28 @@ FocusScope {
409
447
410 dragHandleWidth: shell.edgeSize
448 dragHandleWidth: shell.edgeSize
411
449
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+
412 onShownChanged: {
460 onShownChanged: {
413 if (shown) {
461 if (shown) {
414 lockscreen.reset();
462 lockscreen.reset();
463+ if (!LightDM.Greeter.promptless) {
464+ lockscreen.show();
465+ }
415 // If there is only one user, we start authenticating with that one here.
466 // If there is only one user, we start authenticating with that one here.
416 // If there are more users, the Greeter will handle that
467 // If there are more users, the Greeter will handle that
417 if (LightDM.Users.count == 1) {
468 if (LightDM.Users.count == 1) {
418 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole));
469 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole));
419 }
470 }
471+ greeter.fakeActiveForApp = "";
420 greeter.forceActiveFocus();
472 greeter.forceActiveFocus();
421 }
473 }
422 }
474 }
@@ -452,7 +504,7 @@ FocusScope {
452 onDisplayPowerStateChange: {
504 onDisplayPowerStateChange: {
453 // We ignore any display-off signals when the proximity sensor
505 // We ignore any display-off signals when the proximity sensor
454 // is active. This usually indicates something like a phone call.
506 // 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) {
456 greeter.showNow();
508 greeter.showNow();
457 }
509 }
458
510
@@ -466,12 +518,36 @@ FocusScope {
466 }
518 }
467
519
468 function showHome() {
520 function showHome() {
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+
469− var animate = !greeter.shown && !stages.shown
530+ var animate = !LightDM.Greeter.active && !stages.shown
470− greeter.hide()
471 dash.setCurrentScope("clickscope", animate, false)
531 dash.setCurrentScope("clickscope", animate, false)
472 stages.hide()
532 stages.hide()
473 }
533 }
474
534
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+
475 function hideIndicatorMenu(delay) {
551 function hideIndicatorMenu(delay) {
476 panel.hideIndicatorMenu(delay);
552 panel.hideIndicatorMenu(delay);
477 }
553 }
@@ -483,17 +559,18 @@ FocusScope {
483
559
484 Panel {
560 Panel {
485 id: panel
561 id: panel
562+ objectName: "panel"
486 anchors.fill: parent //because this draws indicator menus
563 anchors.fill: parent //because this draws indicator menus
487 indicatorsMenuWidth: parent.width > units.gu(60) ? units.gu(40) : parent.width
564 indicatorsMenuWidth: parent.width > units.gu(60) ? units.gu(40) : parent.width
488 indicators {
565 indicators {
489 hides: [launcher]
566 hides: [launcher]
490− available: edgeDemo.panelEnabled
567+ available: edgeDemo.panelEnabled && greeter.fakeActiveForApp === ""
491 contentEnabled: edgeDemo.panelContentEnabled
568 contentEnabled: edgeDemo.panelContentEnabled
492 }
569 }
493 property string focusedAppId: ApplicationManager.focusedApplicationId
570 property string focusedAppId: ApplicationManager.focusedApplicationId
494 property var focusedApplication: ApplicationManager.findApplication(focusedAppId)
571 property var focusedApplication: ApplicationManager.findApplication(focusedAppId)
495− fullscreenMode: focusedApplication && stages.fullscreen && !greeter.shown && !lockscreen.shown
572+ fullscreenMode: (focusedApplication && stages.fullscreen && !LightDM.Greeter.active) || greeter.fakeActiveForApp !== ""
496− searchVisible: !greeter.shown && !lockscreen.shown && dash.shown && dash.searchable
573+ searchVisible: !LightDM.Greeter.active && dash.shown && dash.searchable
497
574
498 InputFilterArea {
575 InputFilterArea {
499 anchors {
576 anchors {
@@ -518,6 +595,7 @@ FocusScope {
518
595
519 Launcher {
596 Launcher {
520 id: launcher
597 id: launcher
598+ objectName: "launcher"
521
599
522 readonly property bool dashSwipe: progress > 0
600 readonly property bool dashSwipe: progress > 0
523
601
@@ -525,28 +603,14 @@ FocusScope {
525 anchors.bottom: parent.bottom
603 anchors.bottom: parent.bottom
526 width: parent.width
604 width: parent.width
527 dragAreaWidth: shell.edgeSize
605 dragAreaWidth: shell.edgeSize
528− available: edgeDemo.launcherEnabled
606+ available: edgeDemo.launcherEnabled && greeter.fakeActiveForApp === ""
529−
530− onShowDashHome: {
531− if (edgeDemo.running)
532− return;
533
607
534− showHome()
608+ onShowDashHome: showHome()
535− }
536− onDash: {
609+ onDash: showDash()
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− }
548 onDashSwipeChanged: if (dashSwipe && stages.shown) dash.setCurrentScope("clickscope", false, true)
610 onDashSwipeChanged: if (dashSwipe && stages.shown) dash.setCurrentScope("clickscope", false, true)
549 onLauncherApplicationSelected: {
611 onLauncherApplicationSelected: {
612+ if (greeter.fakeActiveForApp !== "")
613+ lockscreen.show()
550 if (!edgeDemo.running)
614 if (!edgeDemo.running)
551 shell.activateApplication(appId)
615 shell.activateApplication(appId)
552 }
616 }
qml/Stages/PhoneStage.qml+13−1
@@ -18,6 +18,7 @@ import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19import Ubuntu.Gestures 0.1
19import Ubuntu.Gestures 0.1
20import Unity.Application 0.1
20import Unity.Application 0.1
21+import LightDM 0.1 as LightDM
21import Utils 0.1
22import Utils 0.1
22import "../Components"
23import "../Components"
23
24
@@ -33,6 +34,7 @@ Item {
33 readonly property bool painting: mainScreenshotImage.visible || fadeInScreenshotImage.visible || appSplash.visible || spreadView.visible
34 readonly property bool painting: mainScreenshotImage.visible || fadeInScreenshotImage.visible || appSplash.visible || spreadView.visible
34 property bool fullscreen: priv.focusedApplication ? priv.focusedApplication.fullscreen : false
35 property bool fullscreen: priv.focusedApplication ? priv.focusedApplication.fullscreen : false
35 property bool locked: spreadView.visible
36 property bool locked: spreadView.visible
37+ property bool spreadEnabled: true
36
38
37 // Not used for PhoneStage, only useful for SideStage and similar
39 // Not used for PhoneStage, only useful for SideStage and similar
38 property bool overlayMode: false
40 property bool overlayMode: false
@@ -131,6 +133,11 @@ Item {
131 mainScreenshotImage.visible = true;
133 mainScreenshotImage.visible = true;
132 } else if (priv.secondApplicationStarting && priv.waitingForScreenshot) {
134 } else if (priv.secondApplicationStarting && priv.waitingForScreenshot) {
133 applicationSwitchingAnimation.start();
135 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+ }
134 }
141 }
135 waitingForScreenshot = false;
142 waitingForScreenshot = false;
136 }
143 }
@@ -145,6 +152,11 @@ Item {
145 priv.newFocusedAppId = appId;
152 priv.newFocusedAppId = appId;
146 root.fullscreen = ApplicationManager.findApplication(appId).fullscreen;
153 root.fullscreen = ApplicationManager.findApplication(appId).fullscreen;
147 applicationSwitchingAnimation.start();
154 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+ }
148 } else {
160 } else {
149 ApplicationManager.focusApplication(appId);
161 ApplicationManager.focusApplication(appId);
150 }
162 }
@@ -244,7 +256,7 @@ Item {
244 EdgeDragArea {
256 EdgeDragArea {
245 id: spreadDragArea
257 id: spreadDragArea
246 direction: Direction.Leftwards
258 direction: Direction.Leftwards
247− enabled: ApplicationManager.count > 1 && spreadView.phase != 2
259+ enabled: ApplicationManager.count > 1 && spreadView.phase != 2 && root.spreadEnabled
248
260
249 anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
261 anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
250 width: root.dragAreaWidth
262 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):
137 ("x-canonical-switch-to-application", "true"),
137 ("x-canonical-switch-to-application", "true"),
138 (
138 (
139 "x-canonical-secondary-icon",
139 "x-canonical-secondary-icon",
140− self._get_icon_path('applicationIcons/phone-app.png')
140+ self._get_icon_path('applicationIcons/dialer-app.png')
141 )
141 )
142 ]
142 ]
143
143
@@ -172,7 +172,7 @@ class InteractiveNotificationBase(NotificationsBase):
172 hints = [
172 hints = [
173 (
173 (
174 "x-canonical-secondary-icon",
174 "x-canonical-secondary-icon",
175− self._get_icon_path('applicationIcons/phone-app.png')
175+ self._get_icon_path('applicationIcons/dialer-app.png')
176 ),
176 ),
177 ("x-canonical-snap-decisions", "true"),
177 ("x-canonical-snap-decisions", "true"),
178 ]
178 ]
@@ -435,7 +435,7 @@ class EphemeralNotificationsTests(NotificationsBase):
435 hints = [
435 hints = [
436 (
436 (
437 "x-canonical-secondary-icon",
437 "x-canonical-secondary-icon",
438− self._get_icon_path('applicationIcons/phone-app.png')
438+ self._get_icon_path('applicationIcons/dialer-app.png')
439 )
439 )
440 ]
440 ]
441
441
@@ -677,7 +677,7 @@ class EphemeralNotificationsTests(NotificationsBase):
677 body = 'This bubble uses the icon-title-body layout with a ' \
677 body = 'This bubble uses the icon-title-body layout with a ' \
678 'secondary icon.'
678 'secondary icon.'
679 icon_path = self._get_icon_path('avatars/anna_olsson.png')
679 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')
681
681
682 notification = shell.create_ephemeral_notification(
682 notification = shell.create_ephemeral_notification(
683 summary,
683 summary,
tests/mocks/AccountsService/AccountsService.cpp+3−1
@@ -18,9 +18,11 @@
18
18
19#include "AccountsService.h"
19#include "AccountsService.h"
20
20
21+#include <paths.h>
22+
21AccountsService::AccountsService(QObject* parent)
23AccountsService::AccountsService(QObject* parent)
22 : QObject(parent),
24 : QObject(parent),
23− m_backgroundFile(TOP_SRCDIR "/qml/graphics/phone_background.jpg"),
25+ m_backgroundFile(qmlDirectory() + "graphics/phone_background.jpg"),
24 m_statsWelcomeScreen(true)
26 m_statsWelcomeScreen(true)
25{
27{
26}
28}
tests/mocks/AccountsService/CMakeLists.txt−2
@@ -1,5 +1,3 @@
1−add_definitions(-DTOP_SRCDIR="${CMAKE_SOURCE_DIR}")
2−
3add_library(MockAccountsService-qml MODULE
1add_library(MockAccountsService-qml MODULE
4 AccountsService.cpp
2 AccountsService.cpp
5 plugin.cpp
3 plugin.cpp
tests/mocks/LightDM/CMakeLists.txt+1
@@ -18,6 +18,7 @@ include_directories(
18)
18)
19
19
20set(QMLPLUGIN_SRC
20set(QMLPLUGIN_SRC
21+ ${CMAKE_SOURCE_DIR}/plugins/LightDM/DBusGreeter.cpp
21 ${CMAKE_SOURCE_DIR}/plugins/LightDM/DBusGreeterList.cpp
22 ${CMAKE_SOURCE_DIR}/plugins/LightDM/DBusGreeterList.cpp
22 ${CMAKE_SOURCE_DIR}/plugins/LightDM/Greeter.cpp
23 ${CMAKE_SOURCE_DIR}/plugins/LightDM/Greeter.cpp
23 ${CMAKE_SOURCE_DIR}/plugins/LightDM/plugin.cpp
24 ${CMAKE_SOURCE_DIR}/plugins/LightDM/plugin.cpp
tests/mocks/LightDM/single-pin/GreeterPrivate.cpp+1−9
@@ -19,8 +19,6 @@
19#include "../Greeter.h"
19#include "../Greeter.h"
20#include "../GreeterPrivate.h"
20#include "../GreeterPrivate.h"
21
21
22−#include <QDebug>
23−
24namespace QLightDM
22namespace QLightDM
25{
23{
26
24
@@ -34,19 +32,13 @@ GreeterPrivate::GreeterPrivate(Greeter* parent)
34void GreeterPrivate::handleAuthenticate()
32void GreeterPrivate::handleAuthenticate()
35{
33{
36 Q_Q(Greeter);
34 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);
41}
36}
42
37
43void GreeterPrivate::handleRespond(const QString &response)
38void GreeterPrivate::handleRespond(const QString &response)
44{
39{
45 Q_Q(Greeter);
40 Q_Q(Greeter);
46−
47−
48 authenticated = (response == "1234");
41 authenticated = (response == "1234");
49− qDebug() << "responding" << response << authenticated;
50 Q_EMIT q->authenticationComplete();
42 Q_EMIT q->authenticationComplete();
51}
43}
52
44
tests/mocks/Powerd/Powerd.h+7−7
@@ -25,15 +25,15 @@ class Powerd: public QObject
25{
25{
26 Q_OBJECT
26 Q_OBJECT
27 Q_ENUMS(Status)
27 Q_ENUMS(Status)
28− Q_FLAGS(DisplayFlag DisplayFlags)
28+ Q_ENUMS(DisplayStateChangeReason)
29
29
30public:
30public:
31− enum DisplayFlag {
31+ enum DisplayStateChangeReason {
32− UseProximity = 1, // Use proximity sensor to override screen state
32+ Unknown = 0,
33− DisableAutoBrightness = 2, // Force autobrightness to be disabled
33+ Inactivity = 1, // Display changed state due to inactivity
34− Bright = 4, // Request the screen to stay bright
34+ PowerKey = 2, // Display changed state due to user pressing power key
35+ Proximity = 3, // Display changed state due to proximity events
35 };
36 };
36− Q_DECLARE_FLAGS(DisplayFlags, DisplayFlag)
37
37
38 enum Status {
38 enum Status {
39 Off,
39 Off,
@@ -43,7 +43,7 @@ public:
43 explicit Powerd(QObject *parent = 0);
43 explicit Powerd(QObject *parent = 0);
44
44
45Q_SIGNALS:
45Q_SIGNALS:
46− void displayPowerStateChange(int status, unsigned int flags);
46+ void displayPowerStateChange(int status, int reason);
47};
47};
48
48
49#endif
49#endif
tests/mocks/Unity/Application/ApplicationManager.cpp+3−3
@@ -361,9 +361,9 @@ void ApplicationManager::buildListOfAvailableApplications()
361 ApplicationInfo *application;
361 ApplicationInfo *application;
362
362
363 application = new ApplicationInfo(this);
363 application = new ApplicationInfo(this);
364− application->setAppId("phone-app");
364+ application->setAppId("dialer-app");
365− application->setName("Phone");
365+ application->setName("Dialer");
366− application->setIcon(QUrl("phone"));
366+ application->setIcon(QUrl("dialer"));
367 application->setStage(ApplicationInfo::SideStage);
367 application->setStage(ApplicationInfo::SideStage);
368 application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
368 application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
369 generateQmlStrings(application);
369 generateQmlStrings(application);
tests/mocks/Unity/Launcher/CMakeLists.txt−2
@@ -1,7 +1,5 @@
1pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=3)
1pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=3)
2
2
3−add_definitions(-DTOP_SRCDIR="${CMAKE_SOURCE_DIR}")
4−
5include_directories(
3include_directories(
6 ${CMAKE_CURRENT_SOURCE_DIR}
4 ${CMAKE_CURRENT_SOURCE_DIR}
7)
5)
tests/mocks/Unity/Launcher/MockLauncherItem.cpp+3−1
@@ -20,6 +20,8 @@
20#include "MockLauncherItem.h"
20#include "MockLauncherItem.h"
21#include "MockQuickListModel.h"
21#include "MockQuickListModel.h"
22
22
23+#include <paths.h>
24+
23using namespace unity::shell::launcher;
25using namespace unity::shell::launcher;
24
26
25MockLauncherItem::MockLauncherItem(const QString &appId, const QString& desktopFile, const QString& name, const QString& icon, QObject* parent):
27MockLauncherItem::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
27 m_appId(appId),
29 m_appId(appId),
28 m_desktopFile(desktopFile),
30 m_desktopFile(desktopFile),
29 m_name(name),
31 m_name(name),
30− m_icon(TOP_SRCDIR "/graphics/applicationIcons/" + icon + ".png"),
32+ m_icon(qmlDirectory() + "graphics/applicationIcons/" + icon + ".png"),
31 m_pinned(false),
33 m_pinned(false),
32 m_running(false),
34 m_running(false),
33 m_recent(false),
35 m_recent(false),
tests/mocks/Unity/Launcher/MockLauncherModel.cpp+1−1
@@ -22,7 +22,7 @@
22
22
23MockLauncherModel::MockLauncherModel(QObject* parent): LauncherModelInterface(parent)
23MockLauncherModel::MockLauncherModel(QObject* parent): LauncherModelInterface(parent)
24{
24{
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);
26 item->setProgress(0);
26 item->setProgress(0);
27 m_list.append(item);
27 m_list.append(item);
28 item->setFocused(true);
28 item->setFocused(true);
tests/mocks/Unity/fake_categories.cpp+1−1
@@ -50,7 +50,7 @@ void Categories::addSpecialCategory(QString const& categoryId, QString const& na
50 }
50 }
51}
51}
52
52
53−bool Categories::overrideCategoryJson(QString const& categoryId, QString const& json)
53+bool Categories::overrideCategoryJson(QString const& /* categoryId */, QString const& /* json */)
54{
54{
55 qFatal("Using un-implemented Categories::overrideCategoryJson");
55 qFatal("Using un-implemented Categories::overrideCategoryJson");
56}
56}
tests/mocks/Unity/fake_scope.cpp+5
@@ -155,6 +155,11 @@ bool Scope::hasDepartments() const
155 return true;
155 return true;
156}
156}
157
157
158+QVariantMap Scope::customizations() const
159+{
160+ return QVariantMap();
161+}
162+
158unity::shell::scopes::DepartmentInterface* Scope::getDepartment(const QString& id)
163unity::shell::scopes::DepartmentInterface* Scope::getDepartment(const QString& id)
159{
164{
160 if (id.isEmpty())
165 if (id.isEmpty())
tests/mocks/Unity/fake_scope.h+2
@@ -64,6 +64,8 @@ public:
64 Q_INVOKABLE unity::shell::scopes::DepartmentInterface* getDepartment(const QString& id) override;
64 Q_INVOKABLE unity::shell::scopes::DepartmentInterface* getDepartment(const QString& id) override;
65 Q_INVOKABLE void loadDepartment(const QString& id) override;
65 Q_INVOKABLE void loadDepartment(const QString& id) override;
66
66
67+ QVariantMap customizations() const override;
68+
67protected:
69protected:
68
70
69 QString m_id;
71 QString m_id;
tests/plugins/Dash/cardcreator/1.res+1
@@ -68,6 +68,7 @@ Label {
68 anchors { right: parent.right;left: parent.left;
68 anchors { right: parent.right;left: parent.left;
69top: artShapeHolder.bottom;
69top: artShapeHolder.bottom;
70 topMargin: units.gu(1);
70 topMargin: units.gu(1);
71+leftMargin: units.gu(1);
71 }
72 }
72 elide: Text.ElideRight;
73 elide: Text.ElideRight;
73 fontSize: "small";
74 fontSize: "small";
tests/plugins/Dash/cardcreator/3.res+1
@@ -68,6 +68,7 @@ Label {
68 anchors { right: parent.right;left: parent.left;
68 anchors { right: parent.right;left: parent.left;
69top: artShapeHolder.bottom;
69top: artShapeHolder.bottom;
70 topMargin: units.gu(1);
70 topMargin: units.gu(1);
71+leftMargin: units.gu(1);
71}
72}
72 elide: Text.ElideRight;
73 elide: Text.ElideRight;
73 fontSize: "small";
74 fontSize: "small";
tests/plugins/Dash/cardcreator/5.res+1−1
@@ -73,7 +73,7 @@ Loader {
73 visible: showHeader && status == Loader.Ready;
73 visible: showHeader && status == Loader.Ready;
74 sourceComponent: ShaderEffect {
74 sourceComponent: ShaderEffect {
75 id: overlay;
75 id: overlay;
76− height: fixedHeaderHeight > 0 ? fixedHeaderHeight + units.gu(1) * 2 : headerHeight;
76+ height: (fixedHeaderHeight > 0 ? fixedHeaderHeight : headerHeight) + units.gu(2);
77 opacity: 0.6;
77 opacity: 0.6;
78 property var source: ShaderEffectSource {
78 property var source: ShaderEffectSource {
79 id: shaderSource;
79 id: shaderSource;
tests/plugins/LightDM/CMakeLists.txt+1−1
@@ -19,7 +19,7 @@ target_link_libraries(test-lightdm-dbus
19
19
20add_definitions(-DCURRENT_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
20add_definitions(-DCURRENT_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
21
21
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)
23add_dependencies(testLightDMDBus test-lightdm-dbus)
23add_dependencies(testLightDMDBus test-lightdm-dbus)
24
24
25add_dependencies(qmluitests testLightDMDBus)
25add_dependencies(qmluitests testLightDMDBus)
tests/plugins/LightDM/dbus.cpp+40
@@ -38,6 +38,13 @@ private Q_SLOTS:
38 // SIGNAL method, because QtDBus doesn't know about PropertiesChanged.
38 // SIGNAL method, because QtDBus doesn't know about PropertiesChanged.
39 // So we connect the hard way for the benefit of any tests that want
39 // So we connect the hard way for the benefit of any tests that want
40 // to watch.
40 // 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&)));
41 QDBusConnection::sessionBus().connect(
48 QDBusConnection::sessionBus().connect(
42 "com.canonical.UnityGreeter",
49 "com.canonical.UnityGreeter",
43 "/list",
50 "/list",
@@ -57,6 +64,12 @@ private Q_SLOTS:
57 view->show();
64 view->show();
58 QTest::qWaitForWindowExposed(view);
65 QTest::qWaitForWindowExposed(view);
59
66
67+ dbusMain = new QDBusInterface("com.canonical.UnityGreeter",
68+ "/",
69+ "com.canonical.UnityGreeter",
70+ QDBusConnection::sessionBus(), view);
71+ QVERIFY(dbusMain->isValid());
72+
60 dbusList = new QDBusInterface("com.canonical.UnityGreeter",
73 dbusList = new QDBusInterface("com.canonical.UnityGreeter",
61 "/list",
74 "/list",
62 "com.canonical.UnityGreeter.List",
75 "com.canonical.UnityGreeter.List",
@@ -155,9 +168,36 @@ private Q_SLOTS:
155 QVERIFY(arguments.at(1).toMap()["EntryIsLocked"] == false);
168 QVERIFY(arguments.at(1).toMap()["EntryIsLocked"] == false);
156 }
169 }
157
170
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+
158private:
197private:
159 QQuickView *view;
198 QQuickView *view;
160 Greeter *greeter;
199 Greeter *greeter;
200+ QDBusInterface *dbusMain;
161 QDBusInterface *dbusList;
201 QDBusInterface *dbusList;
162};
202};
163
203
tests/qmltests/CMakeLists.txt+2−2
@@ -19,8 +19,8 @@ set(qmltest_DEFAULT_TARGETS qmluitests)
19set(qmltest_DEFAULT_NO_ADD_TEST TRUE)
19set(qmltest_DEFAULT_NO_ADD_TEST TRUE)
20set(qmltest_DEFAULT_PROPERTIES ENVIRONMENT "LC_ALL=C")
20set(qmltest_DEFAULT_PROPERTIES ENVIRONMENT "LC_ALL=C")
21
21
22−add_qml_test(. Shell IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks
22+add_qml_test(. Shell ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
23− 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")
24add_qml_test(Components Carousel)
24add_qml_test(Components Carousel)
25add_qml_test(Components DraggingArea)
25add_qml_test(Components DraggingArea)
26add_qml_test(Components EdgeDemoOverlay)
26add_qml_test(Components EdgeDemoOverlay)
tests/qmltests/Components/tst_LazyImage.qml−1
@@ -152,7 +152,6 @@ Rectangle {
152
152
153 function test_lazyimage(data) {
153 function test_lazyimage(data) {
154 data.func();
154 data.func();
155− waitForRendering(baseRect);
156
155
157 if (data.transition) {
156 if (data.transition) {
158 // wait for the transition to complete
157 // wait for the transition to complete
tests/qmltests/Dash/Apps/tst_RunningApplicationsGrid.qml+2−2
@@ -30,7 +30,7 @@ Rectangle {
30 ApplicationManager.stopApplication(ApplicationManager.get(0).appId)
30 ApplicationManager.stopApplication(ApplicationManager.get(0).appId)
31 }
31 }
32
32
33− ApplicationManager.startApplication("phone-app");
33+ ApplicationManager.startApplication("dialer-app");
34 ApplicationManager.startApplication("webbrowser-app");
34 ApplicationManager.startApplication("webbrowser-app");
35 }
35 }
36
36
@@ -70,7 +70,7 @@ Rectangle {
70 verify(browserTile != undefined)
70 verify(browserTile != undefined)
71 browserTile.onPressAndHold.connect(onBrowserLongPressed)
71 browserTile.onPressAndHold.connect(onBrowserLongPressed)
72
72
73− phoneTile = findChild(runningApplicationsGrid, "runningAppTile Phone")
73+ phoneTile = findChild(runningApplicationsGrid, "runningAppTile Dialer")
74 verify(phoneTile != undefined)
74 verify(phoneTile != undefined)
75 phoneTile.onPressAndHold.connect(onPhoneLongPressed)
75 phoneTile.onPressAndHold.connect(onPhoneLongPressed)
76
76
tests/qmltests/Greeter/tst_Lockscreen.qml+1−1
@@ -57,7 +57,7 @@ Rectangle {
57 target: LightDM.Greeter
57 target: LightDM.Greeter
58
58
59 onShowPrompt: {
59 onShowPrompt: {
60− if (text.indexOf("PIN") >= 0) {
60+ if (text === "PIN") {
61 pinPadCheckBox.checked = false
61 pinPadCheckBox.checked = false
62 } else {
62 } else {
63 pinPadCheckBox.checked = true
63 pinPadCheckBox.checked = true
tests/qmltests/Launcher/tst_Launcher.qml+2−2
@@ -115,7 +115,7 @@ Item {
115 /* If I click on the icon of an application on the launcher
115 /* If I click on the icon of an application on the launcher
116 Launcher::launcherApplicationSelected signal should be emitted with the
116 Launcher::launcherApplicationSelected signal should be emitted with the
117 corresponding desktop file. E.g. clicking on phone icon should yield
117 corresponding desktop file. E.g. clicking on phone icon should yield
118− launcherApplicationSelected("[...]phone-app.desktop") */
118+ launcherApplicationSelected("[...]dialer-app.desktop") */
119 function test_clickingOnAppIconCausesSignalEmission() {
119 function test_clickingOnAppIconCausesSignalEmission() {
120 launcher.lastSelectedApplication = ""
120 launcher.lastSelectedApplication = ""
121
121
@@ -131,7 +131,7 @@ Item {
131 mouseClick(appIcon, appIcon.width/2, appIcon.height/2)
131 mouseClick(appIcon, appIcon.width/2, appIcon.height/2)
132
132
133 tryCompare(launcher, "lastSelectedApplication",
133 tryCompare(launcher, "lastSelectedApplication",
134− "phone-app")
134+ "dialer-app")
135
135
136 // Tapping on an application icon also dismisses the launcher
136 // Tapping on an application icon also dismisses the launcher
137 revealer.waitUntilLauncherDisappears()
137 revealer.waitUntilLauncherDisappears()
tests/qmltests/Notifications/tst_VisualSnapDecisionsQueue.qml+1−1
@@ -67,7 +67,7 @@ Row {
67 summary: "Incoming call",
67 summary: "Incoming call",
68 body: "Frank Zappa\n+44 (0)7736 027340",
68 body: "Frank Zappa\n+44 (0)7736 027340",
69 icon: "../graphics/avatars/funky.png",
69 icon: "../graphics/avatars/funky.png",
70− secondaryIcon: "../graphics/applicationIcons/phone-app.png",
70+ secondaryIcon: "../graphics/applicationIcons/dialer-app.png",
71 actions: [{ id: "pickup_id", label: "Pick up"},
71 actions: [{ id: "pickup_id", label: "Pick up"},
72 { id: "decline_1_id", label: "Decline"},
72 { id: "decline_1_id", label: "Decline"},
73 { id: "decline_2_id", label: "Can't talk now, what's up?"},
73 { id: "decline_2_id", label: "Can't talk now, what's up?"},
tests/qmltests/tst_Shell.qml+26−1
@@ -20,6 +20,7 @@
20import QtQuick 2.0
20import QtQuick 2.0
21import QtTest 1.0
21import QtTest 1.0
22import GSettings 1.0
22import GSettings 1.0
23+import LightDM 0.1 as LightDM
23import Unity.Application 0.1
24import Unity.Application 0.1
24import Unity.Test 0.1 as UT
25import Unity.Test 0.1 as UT
25import Powerd 0.1
26import Powerd 0.1
@@ -50,6 +51,11 @@ Item {
50 id: shell
51 id: shell
51 }
52 }
52
53
54+ SignalSpy {
55+ id: sessionSpy
56+ signalName: "sessionStarted"
57+ }
58+
53 UT.UnityTestCase {
59 UT.UnityTestCase {
54 name: "Shell"
60 name: "Shell"
55 when: windowShown
61 when: windowShown
@@ -91,6 +97,8 @@ Item {
91 verify(ok);
97 verify(ok);
92
98
93 swipeAwayGreeter();
99 swipeAwayGreeter();
100+
101+ sessionSpy.target = findChild(shell, "greeter")
94 }
102 }
95
103
96 function cleanup() {
104 function cleanup() {
@@ -195,7 +203,7 @@ Item {
195 tryCompare(mainApp, "state", ApplicationInfo.Running);
203 tryCompare(mainApp, "state", ApplicationInfo.Running);
196
204
197 // Try to suspend while proximity is engaged...
205 // Try to suspend while proximity is engaged...
198− Powerd.displayPowerStateChange(Powerd.Off, Powerd.UseProximity);
206+ Powerd.displayPowerStateChange(Powerd.Off, Powerd.Proximity);
199 tryCompare(greeter, "showProgress", 0);
207 tryCompare(greeter, "showProgress", 0);
200
208
201 // Now really suspend
209 // Now really suspend
@@ -556,5 +564,22 @@ Item {
556 tryCompare(greeter, "showProgress", 0)
564 tryCompare(greeter, "showProgress", 0)
557 waitUntilApplicationWindowIsFullyVisible()
565 waitUntilApplicationWindowIsFullyVisible()
558 }
566 }
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+ }
559 }
584 }
560}
585}
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+}