on xenial help sign in
Stop unity8 from getting in a "switch-to-greeter" loop when locking on a desktop. (LP: #1593718)
commit40aec9c21069670498053590e3c7c1f540b817d1 authorMichael Terry <michael.terry@canonical.com> dateMon 27 Jun 2016, 18:44 (10 years ago) parente91046711cf308
14 files changed+323−26
plugins/Unity/Session/CMakeLists.txt+2 plugins/Unity/Session/dbusunitysessionservice.cpp+50−18 plugins/Unity/Session/dbusunitysessionservice.h+7 qml/Greeter/Greeter.qml+4−1 tests/CMakeLists.txt+6 tests/plugins/AccountsService/CMakeLists.txt−5 tests/plugins/Unity/Session/CMakeLists.txt+29−1 tests/plugins/Unity/Session/LightDMServer.cpp+29 tests/plugins/Unity/Session/LightDMServer.h+38 tests/plugins/Unity/Session/LogindServer.cpp+33 tests/plugins/Unity/Session/LogindServer.h+43 tests/plugins/Unity/Session/interfaces.xml+17 tests/plugins/Unity/Session/server.cpp+50 tests/plugins/Unity/Session/sessionbackendtest.cpp+15−1
plugins/Unity/Session/CMakeLists.txt+2
@@ -6,6 +6,8 @@ include_directories(
66 ${libunity8-private_SOURCE_DIR}
77)
88
9+add_definitions(-DSM_BUSNAME=systemBus)
10+
911set(QMLSESSIONPLUGIN_SRC
1012 plugin.cpp
1113 dbusunitysessionservice.cpp
plugins/Unity/Session/dbusunitysessionservice.cpp+50−18
@@ -64,19 +64,19 @@ public:
6464 QStringLiteral("GetSessionByPID"));
6565 msg << (quint32) getpid();
6666
67− QDBusReply<QDBusObjectPath> reply = QDBusConnection::systemBus().call(msg);
67+ QDBusReply<QDBusObjectPath> reply = QDBusConnection::SM_BUSNAME().call(msg);
6868 if (reply.isValid()) {
6969 logindSessionPath = reply.value().path();
7070
7171 // start watching the Active property
72− QDBusConnection::systemBus().connect(LOGIN1_SERVICE, logindSessionPath, QStringLiteral("org.freedesktop.DBus.Properties"), QStringLiteral("PropertiesChanged"),
73− this, SLOT(onPropertiesChanged(QString,QVariantMap,QStringList)));
72+ QDBusConnection::SM_BUSNAME().connect(LOGIN1_SERVICE, logindSessionPath, QStringLiteral("org.freedesktop.DBus.Properties"), QStringLiteral("PropertiesChanged"),
73+ this, SLOT(onPropertiesChanged(QString,QVariantMap,QStringList)));
7474
7575 setupSystemdInhibition();
7676
7777 // re-enable the inhibition upon resume from sleep
78− QDBusConnection::systemBus().connect(LOGIN1_SERVICE, LOGIN1_PATH, LOGIN1_IFACE, QStringLiteral("PrepareForSleep"),
79− this, SLOT(onResuming(bool)));
78+ QDBusConnection::SM_BUSNAME().connect(LOGIN1_SERVICE, LOGIN1_PATH, LOGIN1_IFACE, QStringLiteral("PrepareForSleep"),
79+ this, SLOT(onResuming(bool)));
8080 } else {
8181 qWarning() << "Failed to get logind session path" << reply.error().message();
8282 }
@@ -96,7 +96,7 @@ public:
9696 msg << "Unity8 handles power events"; // why
9797 msg << "block"; // mode
9898
99− QDBusPendingCall pendingCall = QDBusConnection::systemBus().asyncCall(msg);
99+ QDBusPendingCall pendingCall = QDBusConnection::SM_BUSNAME().asyncCall(msg);
100100 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall, this);
101101 connect(watcher, &QDBusPendingCallWatcher::finished,
102102 this, [this](QDBusPendingCallWatcher* watcher) {
@@ -114,7 +114,7 @@ public:
114114 bool checkLogin1Call(const QString &method) const
115115 {
116116 QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE, LOGIN1_PATH, LOGIN1_IFACE, method);
117− QDBusReply<QString> reply = QDBusConnection::systemBus().call(msg);
117+ QDBusReply<QString> reply = QDBusConnection::SM_BUSNAME().call(msg);
118118 return reply.isValid() && (reply == QStringLiteral("yes") || reply == QStringLiteral("challenge"));
119119 }
120120
@@ -125,7 +125,7 @@ public:
125125 LOGIN1_IFACE,
126126 method);
127127 msg.setArguments(args);
128− QDBusConnection::systemBus().asyncCall(msg);
128+ QDBusConnection::SM_BUSNAME().asyncCall(msg);
129129 }
130130
131131 void setActive(bool active)
@@ -157,7 +157,7 @@ public:
157157 msg << LOGIN1_SESSION_IFACE;
158158 msg << ACTIVE_KEY;
159159
160− QDBusPendingCall pendingCall = QDBusConnection::systemBus().asyncCall(msg);
160+ QDBusPendingCall pendingCall = QDBusConnection::SM_BUSNAME().asyncCall(msg);
161161 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall, this);
162162 connect(watcher, &QDBusPendingCallWatcher::finished,
163163 this, [this](QDBusPendingCallWatcher* watcher) {
@@ -191,7 +191,7 @@ public:
191191 msg << LOGIN1_SESSION_IFACE;
192192 msg << IDLE_SINCE_KEY;
193193
194− QDBusReply<QVariant> reply = QDBusConnection::systemBus().call(msg);
194+ QDBusReply<QVariant> reply = QDBusConnection::SM_BUSNAME().call(msg);
195195 if (reply.isValid()) {
196196 return reply.value().value<quint64>();
197197 } else {
@@ -208,7 +208,7 @@ public:
208208 LOGIN1_SESSION_IFACE,
209209 QStringLiteral("SetIdleHint"));
210210 msg << idle;
211− QDBusConnection::systemBus().asyncCall(msg);
211+ QDBusConnection::SM_BUSNAME().asyncCall(msg);
212212 }
213213
214214private Q_SLOTS:
@@ -243,11 +243,11 @@ DBusUnitySessionService::DBusUnitySessionService()
243243 : UnityDBusObject(QStringLiteral("/com/canonical/Unity/Session"), QStringLiteral("com.canonical.Unity"))
244244{
245245 if (!d->logindSessionPath.isEmpty()) {
246− // connect our Lock() slot to the logind's session Lock() signal
247− QDBusConnection::systemBus().connect(LOGIN1_SERVICE, d->logindSessionPath, LOGIN1_SESSION_IFACE, QStringLiteral("Lock"), this, SLOT(Lock()));
246+ // connect our PromptLock() slot to the logind's session Lock() signal
247+ QDBusConnection::SM_BUSNAME().connect(LOGIN1_SERVICE, d->logindSessionPath, LOGIN1_SESSION_IFACE, QStringLiteral("Lock"), this, SLOT(PromptLock()));
248248 // ... and our Unlocked() signal to the logind's session Unlock() signal
249249 // (lightdm handles the unlocking by calling logind's Unlock method which in turn emits this signal we connect to)
250− QDBusConnection::systemBus().connect(LOGIN1_SERVICE, d->logindSessionPath, LOGIN1_SESSION_IFACE, QStringLiteral("Unlock"), this, SIGNAL(Unlocked()));
250+ QDBusConnection::SM_BUSNAME().connect(LOGIN1_SERVICE, d->logindSessionPath, LOGIN1_SESSION_IFACE, QStringLiteral("Unlock"), this, SLOT(doUnlock()));
251251 connect(d, &DBusUnitySessionServicePrivate::prepareForSleep, this, &DBusUnitySessionService::PromptLock);
252252 } else {
253253 qWarning() << "Failed to connect to logind's session Lock/Unlock signals";
@@ -332,15 +332,41 @@ QString DBusUnitySessionService::HostName() const
332332
333333void DBusUnitySessionService::PromptLock()
334334{
335+ // Prompt as in quick. No locking animation needed. Usually used by
336+ // indicator-session in combination with a switch to greeter or other
337+ // user session.
335338 Q_EMIT LockRequested();
336339 Q_EMIT lockRequested();
337340}
338341
339342void DBusUnitySessionService::Lock()
340343{
341− // signal u8 to show the lockscreen/greeter
344+ // Normal lock (with animation, as compared to PromptLock above). Usually
345+ // used by indicator-session to lock the session in place.
346+ //
347+ // FIXME: We also -- as a bit of a hack around indicator-session not fully
348+ // supporting a phone profile -- switch to greeter here. The unity7 flow is
349+ // that the user chooses "Lock/Switch" from the indicator, and then can go
350+ // to greeter by selecting "Switch" again from the indicator, which is now
351+ // exposed by the desktop_lockscreen profile. But since in unity8, we try
352+ // to expose most things all the time, we don't use the separate lockscreen
353+ // profile. Instead, we just go directly to the greeter the first time
354+ // a user presses "Lock/Switch". This isn't what this DBus call is
355+ // supposed to do, but we can live with it for now.
356+ //
357+ // Here's a bug about indicator-session growing a converged Touch profile:
358+ // https://launchpad.net/bugs/1557716
359+ //
360+ // We only do this here in the animated-lock call because that's the only
361+ // time the indicator locks without also asking the display manager to
362+ // switch sessions on us. And since we are switching screens, we also
363+ // don't bother respecting the animate request, simply doing a PromptLock.
342364 PromptLock();
365+ switchToGreeter();
366+}
343367
368+void DBusUnitySessionService::switchToGreeter()
369+{
344370 // lock the session using the org.freedesktop.DisplayManager system DBUS service
345371 const QString sessionPath = QString::fromLocal8Bit(qgetenv("XDG_SESSION_PATH"));
346372 QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.DisplayManager"),
@@ -348,7 +374,7 @@ void DBusUnitySessionService::Lock()
348374 QStringLiteral("org.freedesktop.DisplayManager.Session"),
349375 QStringLiteral("Lock"));
350376
351− QDBusPendingCall pendingCall = QDBusConnection::systemBus().asyncCall(msg);
377+ QDBusPendingCall pendingCall = QDBusConnection::SM_BUSNAME().asyncCall(msg);
352378 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall, this);
353379 connect(watcher, &QDBusPendingCallWatcher::finished,
354380 this, [this](QDBusPendingCallWatcher* watcher) {
@@ -365,6 +391,12 @@ void DBusUnitySessionService::Lock()
365391 });
366392}
367393
394+void DBusUnitySessionService::doUnlock()
395+{
396+ Q_EMIT Unlocked();
397+ Q_EMIT unlocked();
398+}
399+
368400bool DBusUnitySessionService::IsLocked() const
369401{
370402 return !d->isSessionActive;
@@ -486,7 +518,7 @@ void DBusGnomeScreensaverWrapper::SetActive(bool lock)
486518
487519void DBusGnomeScreensaverWrapper::Lock()
488520{
489− performAsyncUnityCall(QStringLiteral("Lock"));
521+ performAsyncUnityCall(QStringLiteral("PromptLock"));
490522}
491523
492524quint32 DBusGnomeScreensaverWrapper::GetActiveTime() const
@@ -523,7 +555,7 @@ bool DBusScreensaverWrapper::SetActive(bool lock)
523555
524556void DBusScreensaverWrapper::Lock()
525557{
526− performAsyncUnityCall(QStringLiteral("Lock"));
558+ performAsyncUnityCall(QStringLiteral("PromptLock"));
527559}
528560
529561quint32 DBusScreensaverWrapper::GetActiveTime() const
plugins/Unity/Session/dbusunitysessionservice.h+7
@@ -106,6 +106,7 @@ Q_SIGNALS:
106106 * Emitted after the session has been unlocked.
107107 */
108108 Q_SCRIPTABLE void Unlocked();
109+ void unlocked();
109110
110111public Q_SLOTS:
111112 /**
@@ -258,6 +259,12 @@ public Q_SLOTS:
258259 * @return whether the session is currently locked
259260 */
260261 Q_SCRIPTABLE bool IsLocked() const;
262+
263+private Q_SLOTS:
264+ void doUnlock();
265+
266+private:
267+ void switchToGreeter();
261268};
262269
263270class DBusGnomeSessionManagerWrapper : public UnityDBusObject
qml/Greeter/Greeter.qml+4−1
@@ -478,7 +478,10 @@ Showable {
478478 Connections {
479479 target: DBusUnitySessionService
480480 onLockRequested: root.forceShow()
481− onUnlocked: root.forcedUnlock = true
481+ onUnlocked: {
482+ root.forcedUnlock = true;
483+ root.hideNow();
484+ }
482485 }
483486
484487 Binding {
tests/CMakeLists.txt+6
@@ -126,6 +126,12 @@ function(add_unity8_qmlbenchmark PATH COMPONENT_NAME ITERATIONS)
126126 add_unity8_qmltest(${PATH} ${COMPONENT_NAME} ITERATIONS ${ITERATIONS} ${ARGN})
127127endfunction()
128128
129+# used to make dbus adaptor classes from xml to mock system services
130+if(DEFINED ENV{DEB_BUILD_MULTIARCH})
131+ set(QDBUSXML2CPP_EXECUTABLE "/usr/lib/$ENV{DEB_BUILD_MULTIARCH}/qt5/bin/qdbusxml2cpp")
132+else()
133+ FIND_PROGRAM(QDBUSXML2CPP_EXECUTABLE qdbusxml2cpp)
134+endif()
129135
130136# Actual test definitions
131137add_subdirectory(plugins)
tests/plugins/AccountsService/CMakeLists.txt−5
@@ -1,8 +1,3 @@
1−if(DEFINED ENV{DEB_BUILD_MULTIARCH})
2− set(QDBUSXML2CPP_EXECUTABLE "/usr/lib/$ENV{DEB_BUILD_MULTIARCH}/qt5/bin/qdbusxml2cpp")
3−else()
4− FIND_PROGRAM(QDBUSXML2CPP_EXECUTABLE qdbusxml2cpp)
5−endif()
61macro(make_dbus_class NAME INTERFACE)
72 if(${CMAKE_CURRENT_SOURCE_DIR}/interfaces.xml IS_NEWER_THAN ${CMAKE_CURRENT_BINARY_DIR}/${NAME}Adaptor.h)
83 execute_process(COMMAND ${QDBUSXML2CPP_EXECUTABLE} -c ${NAME}Adaptor -i types.h -a ${CMAKE_CURRENT_BINARY_DIR}/${NAME}Adaptor ${CMAKE_CURRENT_SOURCE_DIR}/interfaces.xml ${INTERFACE})
tests/plugins/Unity/Session/CMakeLists.txt+29−1
@@ -1,3 +1,13 @@
1+macro(make_dbus_class NAME INTERFACE)
2+ if(${CMAKE_CURRENT_SOURCE_DIR}/interfaces.xml IS_NEWER_THAN ${CMAKE_CURRENT_BINARY_DIR}/${NAME}Adaptor.h)
3+ execute_process(COMMAND ${QDBUSXML2CPP_EXECUTABLE} -c ${NAME}Adaptor -a ${CMAKE_CURRENT_BINARY_DIR}/${NAME}Adaptor ${CMAKE_CURRENT_SOURCE_DIR}/interfaces.xml ${INTERFACE})
4+ endif()
5+endmacro(make_dbus_class)
6+
7+make_dbus_class(LightDMSession org.freedesktop.DisplayManager.Session)
8+make_dbus_class(LogindManager org.freedesktop.login1.Manager)
9+make_dbus_class(LogindSession org.freedesktop.login1.Session)
10+
111include_directories(
212 ${CMAKE_CURRENT_BINARY_DIR}
313 ${CMAKE_SOURCE_DIR}/plugins/Unity/Session
@@ -9,6 +19,17 @@ add_definitions(-DSM_BUSNAME=sessionBus)
919add_definitions(-DSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}")
1020add_definitions(-DSESSION_TESTING)
1121
22+### LightDMServer
23+add_executable(LightDMServer
24+ ${CMAKE_CURRENT_BINARY_DIR}/LightDMSessionAdaptor.cpp
25+ ${CMAKE_CURRENT_BINARY_DIR}/LogindManagerAdaptor.cpp
26+ ${CMAKE_CURRENT_BINARY_DIR}/LogindSessionAdaptor.cpp
27+ LightDMServer.cpp
28+ LogindServer.cpp
29+ server.cpp
30+)
31+qt5_use_modules(LightDMServer Core DBus)
32+
1233### SessionBackendTest
1334add_executable(sessionbackendtestExec
1435 sessionbackendtest.cpp
@@ -21,6 +42,13 @@ target_link_libraries(sessionbackendtestExec
2142qt5_use_modules(sessionbackendtestExec Test Core Qml DBus)
2243
2344add_unity8_unittest(SessionBackend dbus-test-runner
45+ ENVIRONMENT XDG_SESSION_PATH=/session
2446 ARG_PREFIX "--parameter"
25− ARGS --task $<TARGET_FILE:sessionbackendtestExec>
47+ ARGS
48+ --task $<TARGET_FILE:LightDMServer>
49+ --task-name server
50+ --ignore-return
51+ --task $<TARGET_FILE:sessionbackendtestExec>
52+ --task-name client
53+ --wait-for org.freedesktop.DisplayManager
2654)
tests/plugins/Unity/Session/LightDMServer.cppnew file+29
@@ -0,0 +1,29 @@
1+/*
2+ * Copyright 2016 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * version 3 along with this program. If not, see
15+ * <http://www.gnu.org/licenses/>
16+ */
17+
18+#include "LightDMServer.h"
19+
20+LightDMServer::LightDMServer(QObject *logind, QObject *parent)
21+ : QObject(parent)
22+ , m_logind(logind)
23+{
24+}
25+
26+void LightDMServer::Lock()
27+{
28+ QMetaObject::invokeMethod(m_logind, "Lock");
29+}
tests/plugins/Unity/Session/LightDMServer.hnew file+38
@@ -0,0 +1,38 @@
1+/*
2+ * Copyright 2016 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * version 3 along with this program. If not, see
15+ * <http://www.gnu.org/licenses/>
16+ */
17+
18+#ifndef UNITY_LIGHTDMSERVER_H
19+#define UNITY_LIGHTDMSERVER_H
20+
21+#include <QDBusContext>
22+#include <QObject>
23+
24+class LightDMServer: public QObject, protected QDBusContext
25+{
26+ Q_OBJECT
27+
28+public:
29+ explicit LightDMServer(QObject *logind, QObject *parent = nullptr);
30+
31+public Q_SLOTS:
32+ void Lock();
33+
34+private:
35+ QObject *m_logind;
36+};
37+
38+#endif
tests/plugins/Unity/Session/LogindServer.cppnew file+33
@@ -0,0 +1,33 @@
1+/*
2+ * Copyright 2016 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * version 3 along with this program. If not, see
15+ * <http://www.gnu.org/licenses/>
16+ */
17+
18+#include "LogindServer.h"
19+
20+LogindServer::LogindServer(QObject *parent)
21+ : QObject(parent)
22+{
23+}
24+
25+QDBusObjectPath LogindServer::GetSessionByPID(quint32)
26+{
27+ return QDBusObjectPath("/logindsession");
28+}
29+
30+void LogindServer::MockEmitUnlock()
31+{
32+ Q_EMIT Unlock();
33+}
tests/plugins/Unity/Session/LogindServer.hnew file+43
@@ -0,0 +1,43 @@
1+/*
2+ * Copyright 2016 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * version 3 along with this program. If not, see
15+ * <http://www.gnu.org/licenses/>
16+ */
17+
18+#ifndef UNITY_LOGINDSERVER_H
19+#define UNITY_LOGINDSERVER_H
20+
21+#include <QDBusContext>
22+#include <QDBusObjectPath>
23+#include <QObject>
24+
25+class LogindServer: public QObject, protected QDBusContext
26+{
27+ Q_OBJECT
28+
29+public:
30+ explicit LogindServer(QObject *parent = nullptr);
31+
32+public Q_SLOTS:
33+ QDBusObjectPath GetSessionByPID(quint32 pid);
34+
35+ void MockEmitUnlock(); // only in mock
36+
37+Q_SIGNALS:
38+ void Lock();
39+ void Unlock();
40+ void PrepareForSleep();
41+};
42+
43+#endif
tests/plugins/Unity/Session/interfaces.xmlnew file+17
@@ -0,0 +1,17 @@
1+<node>
2+ <interface name="org.freedesktop.DisplayManager.Session">
3+ <method name="Lock" />
4+ </interface>
5+ <interface name="org.freedesktop.login1.Manager">
6+ <method name="GetSessionByPID">
7+ <arg name="pid" type="u" direction="in" />
8+ <arg name="session" type="o" direction="out" />
9+ </method>
10+ <signal name="PrepareForSleep" />
11+ </interface>
12+ <interface name="org.freedesktop.login1.Session">
13+ <method name="MockEmitUnlock" />
14+ <signal name="Lock" />
15+ <signal name="Unlock" />
16+ </interface>
17+</node>
tests/plugins/Unity/Session/server.cppnew file+50
@@ -0,0 +1,50 @@
1+/*
2+ * Copyright 2016 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * version 3 along with this program. If not, see
15+ * <http://www.gnu.org/licenses/>
16+ */
17+
18+#include "LightDMServer.h"
19+#include "LightDMSessionAdaptor.h"
20+#include "LogindManagerAdaptor.h"
21+#include "LogindServer.h"
22+#include "LogindSessionAdaptor.h"
23+#include <QCoreApplication>
24+
25+int main(int argc, char *argv[])
26+{
27+ QCoreApplication a(argc, argv);
28+
29+ auto logind = new LogindServer(&a);
30+ new LogindManagerAdaptor(logind);
31+ new LogindSessionAdaptor(logind);
32+
33+ auto lightdm = new LightDMServer(logind, &a);
34+ new LightDMSessionAdaptor(lightdm);
35+
36+ // We use the session bus for testing. The real plugin uses the system bus
37+ auto connection = QDBusConnection::sessionBus();
38+ if (!connection.registerObject("/org/freedesktop/login1", logind))
39+ return 1;
40+ if (!connection.registerObject("/logindsession", logind))
41+ return 1;
42+ if (!connection.registerService("org.freedesktop.login1"))
43+ return 1;
44+ if (!connection.registerObject("/session", lightdm))
45+ return 1;
46+ if (!connection.registerService("org.freedesktop.DisplayManager"))
47+ return 1;
48+
49+ return a.exec();
50+}
tests/plugins/Unity/Session/sessionbackendtest.cpp+15−1
@@ -61,6 +61,8 @@ private Q_SLOTS:
6161 QTest::newRow("Reboot") << "RequestReboot" << "RebootRequested(bool)";
6262 QTest::newRow("Shutdown") << "RequestShutdown" << "ShutdownRequested(bool)";
6363 QTest::newRow("PromptLock") << "PromptLock" << "LockRequested()";
64+ QTest::newRow("Lock") << "Lock" << "LockRequested()";
65+ QTest::newRow("LockLightDM") << "Lock" << "Locked()"; // happens when we lock LightDM, only for Lock()
6466 }
6567
6668 void testUnitySessionLogoutRequested() {
@@ -76,7 +78,7 @@ private Q_SLOTS:
7678 QDBusReply<void> reply = dbusUnitySession->call(method);
7779 QCOMPARE(reply.isValid(), true);
7880
79− QCOMPARE(spy.count(), 1);
81+ QTRY_COMPARE(spy.count(), 1);
8082 }
8183
8284 void testGnomeSessionWrapper_data() {
@@ -122,6 +124,18 @@ private Q_SLOTS:
122124 QCOMPARE(spy.count(), 1);
123125 }
124126
127+ void testUnlockFromLogind() {
128+ DBusUnitySessionService dbusUnitySessionService;
129+ QCoreApplication::processEvents(); // to let the service register on DBus
130+
131+ QDBusInterface iface("org.freedesktop.login1", "/logindsession", "org.freedesktop.login1.Session");
132+ QVERIFY(iface.isValid());
133+
134+ QSignalSpy spy(&dbusUnitySessionService, SIGNAL(Unlocked()));
135+ QCOMPARE(iface.call("MockEmitUnlock").errorMessage(), QString());
136+ QTRY_COMPARE(spy.count(), 1);
137+ }
138+
125139 void testUserName() {
126140 DBusUnitySessionService dbusUnitySessionService;
127141 QCoreApplication::processEvents(); // to let the service register on DBus