@@ -32,27 +32,87 @@
32#define LOGIN1_IFACE QStringLiteral("org.freedesktop.login1.Manager")
32#define LOGIN1_IFACE QStringLiteral("org.freedesktop.login1.Manager")
33#define LOGIN1_SESSION_IFACE QStringLiteral("org.freedesktop.login1.Session")
33#define LOGIN1_SESSION_IFACE QStringLiteral("org.freedesktop.login1.Session")
35−bool checkLogin1Call(const QString &method)
35+class DBusUnitySessionServicePrivate: public QObject
37− QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE, LOGIN1_PATH, LOGIN1_IFACE, method);
37+public:
38− QDBusReply<QString> reply = QDBusConnection::systemBus().asyncCall(msg);
38+ QString logindSessionPath;
39− const QString retval = reply.value();
40− return (retval == QStringLiteral("yes") || retval == QStringLiteral("challenge"));
40+ DBusUnitySessionServicePrivate(): QObject() { init(); }
44+ // get our logind session path
45+ QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE,
49+ msg << (quint32) getpid();
51+ QDBusReply<QDBusObjectPath> reply = QDBusConnection::systemBus().asyncCall(msg);
52+ if (reply.isValid()) {
53+ logindSessionPath = reply.value().path();
54+ qDebug() << "session path" << logindSessionPath;
56+ qWarning() << "Failed to get logind session path" << reply.error().message();
60+ bool checkLogin1Call(const QString &method) const
62+ QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE, LOGIN1_PATH, LOGIN1_IFACE, method);
63+ QDBusReply<QString> reply = QDBusConnection::systemBus().asyncCall(msg);
64+ return reply.isValid() && (reply == QStringLiteral("yes") || reply == QStringLiteral("challenge"));
43−void makeLogin1Call(const QString &method, const QVariantList &args)
67+ void makeLogin1Call(const QString &method, const QVariantList &args)
45− QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE,
69+ QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE,
46− LOGIN1_PATH,
70+ LOGIN1_PATH,
47− LOGIN1_IFACE,
71+ LOGIN1_IFACE,
49− msg.setArguments(args);
73+ msg.setArguments(args);
74+ QDBusConnection::systemBus().asyncCall(msg);
77+ bool isActive() const
79+ if (logindSessionPath.isEmpty()) {
80+ qWarning() << "Invalid session path";
81+ return true; //assume active
84+ QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE,
86+ "org.freedesktop.DBus.Properties",
88+ msg << LOGIN1_SESSION_IFACE;
89+ msg << QStringLiteral("Active");
50− QDBusConnection::systemBus().asyncCall(msg);
91+ QDBusReply<bool> reply = QDBusConnection::systemBus().asyncCall(msg);
92+ if (reply.isValid()) {
95+ qWarning() << "Failed to get Active property" << reply.error().message();
98+ return true; // assume active
102+Q_GLOBAL_STATIC(DBusUnitySessionServicePrivate, d)
53DBusUnitySessionService::DBusUnitySessionService()
104DBusUnitySessionService::DBusUnitySessionService()
54 : UnityDBusObject("/com/canonical/Unity/Session", "com.canonical.Unity")
105 : UnityDBusObject("/com/canonical/Unity/Session", "com.canonical.Unity")
107+ if (!d->logindSessionPath.isEmpty()) {
108+ // connect our Lock() slot to the logind's session Lock() signal
109+ QDBusConnection::systemBus().connect(LOGIN1_SERVICE, d->logindSessionPath, LOGIN1_SESSION_IFACE, "Lock", this, SLOT(Lock()));
110+ // ... and our Unlocked() signal to the logind's session Unlock() signal
111+ // (lightdm handles the unlocking by calling logind's Unlock method which in turn emits this signal we connect to)
112+ QDBusConnection::systemBus().connect(LOGIN1_SERVICE, d->logindSessionPath, LOGIN1_SESSION_IFACE, "Unlock", this, SIGNAL(Unlocked()));
114+ qWarning() << "Failed to connect to logind's session Lock/Unlock signals";
58void DBusUnitySessionService::Logout()
118void DBusUnitySessionService::Logout()
@@ -72,27 +132,27 @@ void DBusUnitySessionService::EndSession()
73bool DBusUnitySessionService::CanHibernate() const
133bool DBusUnitySessionService::CanHibernate() const
75− return checkLogin1Call("CanHibernate");
135+ return d->checkLogin1Call("CanHibernate");
78bool DBusUnitySessionService::CanSuspend() const
138bool DBusUnitySessionService::CanSuspend() const
80− return checkLogin1Call("CanSuspend");
140+ return d->checkLogin1Call("CanSuspend");
83bool DBusUnitySessionService::CanHybridSleep() const
143bool DBusUnitySessionService::CanHybridSleep() const
85− return checkLogin1Call("CanHybridSleep");
145+ return d->checkLogin1Call("CanHybridSleep");
88bool DBusUnitySessionService::CanReboot() const
148bool DBusUnitySessionService::CanReboot() const
90− return checkLogin1Call("CanReboot");
150+ return d->checkLogin1Call("CanReboot");
93bool DBusUnitySessionService::CanShutdown() const
153bool DBusUnitySessionService::CanShutdown() const
95− return checkLogin1Call("CanPowerOff");
155+ return d->checkLogin1Call("CanPowerOff");
98bool DBusUnitySessionService::CanLock() const
158bool DBusUnitySessionService::CanLock() const
@@ -141,18 +201,27 @@ void DBusUnitySessionService::PromptLock()
142void DBusUnitySessionService::Lock()
202void DBusUnitySessionService::Lock()
204+ // lock the session using the org.freedesktop.DisplayManager system DBUS service
144− const QString sessionId = QString::fromLocal8Bit(qgetenv("XDG_SESSION_PATH"));
205+ const QString sessionPath = QString::fromLocal8Bit(qgetenv("XDG_SESSION_PATH"));
145 QDBusMessage msg = QDBusMessage::createMethodCall("org.freedesktop.DisplayManager",
206 QDBusMessage msg = QDBusMessage::createMethodCall("org.freedesktop.DisplayManager",
146− sessionId,
207+ sessionPath,
147 "org.freedesktop.DisplayManager.Session",
208 "org.freedesktop.DisplayManager.Session",
149 qDebug() << "Locking session" << msg.path();
210 qDebug() << "Locking session" << msg.path();
150 QDBusReply<void> reply = QDBusConnection::systemBus().asyncCall(msg);
211 QDBusReply<void> reply = QDBusConnection::systemBus().asyncCall(msg);
151 if (!reply.isValid()) {
212 if (!reply.isValid()) {
152 qWarning() << "Lock call failed" << reply.error().message();
213 qWarning() << "Lock call failed" << reply.error().message();
215+ // emit Locked when the call succeeds
220+bool DBusUnitySessionService::IsLocked() const
222+ return !d->isActive();
156void DBusUnitySessionService::RequestLogout()
225void DBusUnitySessionService::RequestLogout()
158 Q_EMIT LogoutRequested(false);
227 Q_EMIT LogoutRequested(false);
@@ -160,7 +229,7 @@ void DBusUnitySessionService::RequestLogout()
161void DBusUnitySessionService::Reboot()
230void DBusUnitySessionService::Reboot()
163− makeLogin1Call("Reboot", {false});
232+ d->makeLogin1Call("Reboot", {false});
166void DBusUnitySessionService::RequestReboot()
235void DBusUnitySessionService::RequestReboot()
@@ -170,22 +239,22 @@ void DBusUnitySessionService::RequestReboot()
171void DBusUnitySessionService::Shutdown()
240void DBusUnitySessionService::Shutdown()
173− makeLogin1Call("PowerOff", {false});
242+ d->makeLogin1Call("PowerOff", {false});
176void DBusUnitySessionService::Suspend()
245void DBusUnitySessionService::Suspend()
178− makeLogin1Call("Suspend", {false});
247+ d->makeLogin1Call("Suspend", {false});
181void DBusUnitySessionService::Hibernate()
250void DBusUnitySessionService::Hibernate()
183− makeLogin1Call("Hibernate", {false});
252+ d->makeLogin1Call("Hibernate", {false});
186void DBusUnitySessionService::HybridSleep()
255void DBusUnitySessionService::HybridSleep()
188− makeLogin1Call("HybridSleep", {false});
257+ d->makeLogin1Call("HybridSleep", {false});
191void DBusUnitySessionService::RequestShutdown()
260void DBusUnitySessionService::RequestShutdown()