@@ -32,27 +32,87 @@
3232#define LOGIN1_IFACE QStringLiteral("org.freedesktop.login1.Manager")
3333#define LOGIN1_SESSION_IFACE QStringLiteral("org.freedesktop.login1.Session")
3434
35−bool checkLogin1Call(const QString &method)
35+class DBusUnitySessionServicePrivate: public QObject
3636{
37− QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE, LOGIN1_PATH, LOGIN1_IFACE, method);
38− QDBusReply<QString> reply = QDBusConnection::systemBus().asyncCall(msg);
39− const QString retval = reply.value();
40− return (retval == QStringLiteral("yes") || retval == QStringLiteral("challenge"));
41−}
37+public:
38+ QString logindSessionPath;
4239
43−void makeLogin1Call(const QString &method, const QVariantList &args)
44−{
45− QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE,
46− LOGIN1_PATH,
47− LOGIN1_IFACE,
48− method);
49− msg.setArguments(args);
50− QDBusConnection::systemBus().asyncCall(msg);
51−}
40+ DBusUnitySessionServicePrivate(): QObject() { init(); }
41+
42+ void init()
43+ {
44+ // get our logind session path
45+ QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE,
46+ LOGIN1_PATH,
47+ LOGIN1_IFACE,
48+ "GetSessionByPID");
49+ msg << (quint32) getpid();
50+
51+ QDBusReply<QDBusObjectPath> reply = QDBusConnection::systemBus().asyncCall(msg);
52+ if (reply.isValid()) {
53+ logindSessionPath = reply.value().path();
54+ qDebug() << "session path" << logindSessionPath;
55+ } else {
56+ qWarning() << "Failed to get logind session path" << reply.error().message();
57+ }
58+ }
59+
60+ bool checkLogin1Call(const QString &method) const
61+ {
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"));
65+ }
66+
67+ void makeLogin1Call(const QString &method, const QVariantList &args)
68+ {
69+ QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE,
70+ LOGIN1_PATH,
71+ LOGIN1_IFACE,
72+ method);
73+ msg.setArguments(args);
74+ QDBusConnection::systemBus().asyncCall(msg);
75+ }
76+
77+ bool isActive() const
78+ {
79+ if (logindSessionPath.isEmpty()) {
80+ qWarning() << "Invalid session path";
81+ return true; //assume active
82+ }
83+
84+ QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE,
85+ logindSessionPath,
86+ "org.freedesktop.DBus.Properties",
87+ "Get");
88+ msg << LOGIN1_SESSION_IFACE;
89+ msg << QStringLiteral("Active");
90+
91+ QDBusReply<bool> reply = QDBusConnection::systemBus().asyncCall(msg);
92+ if (reply.isValid()) {
93+ return reply;
94+ } else {
95+ qWarning() << "Failed to get Active property" << reply.error().message();
96+ }
97+
98+ return true; // assume active
99+ }
100+};
101+
102+Q_GLOBAL_STATIC(DBusUnitySessionServicePrivate, d)
52103
53104DBusUnitySessionService::DBusUnitySessionService()
54105 : UnityDBusObject("/com/canonical/Unity/Session", "com.canonical.Unity")
55106{
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()));
113+ } else {
114+ qWarning() << "Failed to connect to logind's session Lock/Unlock signals";
115+ }
56116}
57117
58118void DBusUnitySessionService::Logout()
@@ -72,27 +132,27 @@ void DBusUnitySessionService::EndSession()
72132
73133bool DBusUnitySessionService::CanHibernate() const
74134{
75− return checkLogin1Call("CanHibernate");
135+ return d->checkLogin1Call("CanHibernate");
76136}
77137
78138bool DBusUnitySessionService::CanSuspend() const
79139{
80− return checkLogin1Call("CanSuspend");
140+ return d->checkLogin1Call("CanSuspend");
81141}
82142
83143bool DBusUnitySessionService::CanHybridSleep() const
84144{
85− return checkLogin1Call("CanHybridSleep");
145+ return d->checkLogin1Call("CanHybridSleep");
86146}
87147
88148bool DBusUnitySessionService::CanReboot() const
89149{
90− return checkLogin1Call("CanReboot");
150+ return d->checkLogin1Call("CanReboot");
91151}
92152
93153bool DBusUnitySessionService::CanShutdown() const
94154{
95− return checkLogin1Call("CanPowerOff");
155+ return d->checkLogin1Call("CanPowerOff");
96156}
97157
98158bool DBusUnitySessionService::CanLock() const
@@ -141,18 +201,27 @@ void DBusUnitySessionService::PromptLock()
141201
142202void DBusUnitySessionService::Lock()
143203{
144− const QString sessionId = QString::fromLocal8Bit(qgetenv("XDG_SESSION_PATH"));
204+ // lock the session using the org.freedesktop.DisplayManager system DBUS service
205+ const QString sessionPath = QString::fromLocal8Bit(qgetenv("XDG_SESSION_PATH"));
145206 QDBusMessage msg = QDBusMessage::createMethodCall("org.freedesktop.DisplayManager",
146− sessionId,
207+ sessionPath,
147208 "org.freedesktop.DisplayManager.Session",
148209 "Lock");
149210 qDebug() << "Locking session" << msg.path();
150211 QDBusReply<void> reply = QDBusConnection::systemBus().asyncCall(msg);
151212 if (!reply.isValid()) {
152213 qWarning() << "Lock call failed" << reply.error().message();
214+ } else {
215+ // emit Locked when the call succeeds
216+ Q_EMIT Locked();
153217 }
154218}
155219
220+bool DBusUnitySessionService::IsLocked() const
221+{
222+ return !d->isActive();
223+}
224+
156225void DBusUnitySessionService::RequestLogout()
157226{
158227 Q_EMIT LogoutRequested(false);
@@ -160,7 +229,7 @@ void DBusUnitySessionService::RequestLogout()
160229
161230void DBusUnitySessionService::Reboot()
162231{
163− makeLogin1Call("Reboot", {false});
232+ d->makeLogin1Call("Reboot", {false});
164233}
165234
166235void DBusUnitySessionService::RequestReboot()
@@ -170,22 +239,22 @@ void DBusUnitySessionService::RequestReboot()
170239
171240void DBusUnitySessionService::Shutdown()
172241{
173− makeLogin1Call("PowerOff", {false});
242+ d->makeLogin1Call("PowerOff", {false});
174243}
175244
176245void DBusUnitySessionService::Suspend()
177246{
178− makeLogin1Call("Suspend", {false});
247+ d->makeLogin1Call("Suspend", {false});
179248}
180249
181250void DBusUnitySessionService::Hibernate()
182251{
183− makeLogin1Call("Hibernate", {false});
252+ d->makeLogin1Call("Hibernate", {false});
184253}
185254
186255void DBusUnitySessionService::HybridSleep()
187256{
188− makeLogin1Call("HybridSleep", {false});
257+ d->makeLogin1Call("HybridSleep", {false});
189258}
190259
191260void DBusUnitySessionService::RequestShutdown()