@@ -17,8 +17,38 @@
1717// local
1818#include "dbusunitysessionservice.h"
1919
20+// system
21+#include <sys/types.h>
22+#include <unistd.h>
23+#include <pwd.h>
24+
2025// Qt
26+#include <QDebug>
2127#include <QDBusPendingCall>
28+#include <QDBusReply>
29+
30+#define LOGIN1_SERVICE QStringLiteral("org.freedesktop.login1")
31+#define LOGIN1_PATH QStringLiteral("/org/freedesktop/login1")
32+#define LOGIN1_IFACE QStringLiteral("org.freedesktop.login1.Manager")
33+#define LOGIN1_SESSION_IFACE QStringLiteral("org.freedesktop.login1.Session")
34+
35+bool checkLogin1Call(const QString &method)
36+{
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+}
42+
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+}
2252
2353DBusUnitySessionService::DBusUnitySessionService()
2454 : UnityDBusObject("/com/canonical/Unity/Session", "com.canonical.Unity")
@@ -28,7 +58,7 @@ DBusUnitySessionService::DBusUnitySessionService()
2858void DBusUnitySessionService::Logout()
2959{
3060 // TODO ask the apps to quit and then emit the signal
31− Q_EMIT logoutReady();
61+ Q_EMIT LogoutReady();
3262}
3363
3464void DBusUnitySessionService::EndSession()
@@ -40,39 +70,127 @@ void DBusUnitySessionService::EndSession()
4070 QDBusConnection::sessionBus().asyncCall(msg);
4171}
4272
73+bool DBusUnitySessionService::CanHibernate() const
74+{
75+ return checkLogin1Call("CanHibernate");
76+}
77+
78+bool DBusUnitySessionService::CanSuspend() const
79+{
80+ return checkLogin1Call("CanSuspend");
81+}
82+
83+bool DBusUnitySessionService::CanHybridSleep() const
84+{
85+ return checkLogin1Call("CanHybridSleep");
86+}
87+
88+bool DBusUnitySessionService::CanReboot() const
89+{
90+ return checkLogin1Call("CanReboot");
91+}
92+
93+bool DBusUnitySessionService::CanShutdown() const
94+{
95+ return checkLogin1Call("CanPowerOff");
96+}
97+
98+bool DBusUnitySessionService::CanLock() const
99+{
100+ return true; // FIXME
101+}
102+
103+QString DBusUnitySessionService::UserName() const
104+{
105+ struct passwd *p = getpwuid(getuid());
106+ if (p) {
107+ return QString::fromUtf8(p->pw_name);
108+ }
109+
110+ return QString();
111+}
112+
113+QString DBusUnitySessionService::RealName() const
114+{
115+ struct passwd *p = getpwuid(getuid());
116+ if (p) {
117+ const QString gecos = QString::fromLocal8Bit(p->pw_gecos);
118+ if (!gecos.isEmpty()) {
119+ return gecos.split(QLatin1Char(',')).first();
120+ }
121+ }
122+
123+ return QString();
124+}
125+
126+QString DBusUnitySessionService::HostName() const
127+{
128+ char hostName[512];
129+ if (gethostname(hostName, sizeof(hostName)) == -1) {
130+ qWarning() << "Could not determine local hostname";
131+ return QString();
132+ }
133+ hostName[sizeof(hostName) - 1] = '\0';
134+ return QString::fromLocal8Bit(hostName);
135+}
136+
137+void DBusUnitySessionService::PromptLock()
138+{
139+ Q_EMIT LockRequested();
140+}
141+
142+void DBusUnitySessionService::Lock()
143+{
144+ const QString sessionId = QString::fromLocal8Bit(qgetenv("XDG_SESSION_PATH"));
145+ QDBusMessage msg = QDBusMessage::createMethodCall("org.freedesktop.DisplayManager",
146+ sessionId,
147+ "org.freedesktop.DisplayManager.Session",
148+ "Lock");
149+ qDebug() << "Locking session" << msg.path();
150+ QDBusReply<void> reply = QDBusConnection::systemBus().asyncCall(msg);
151+ if (!reply.isValid()) {
152+ qWarning() << "Lock call failed" << reply.error().message();
153+ }
154+}
155+
43156void DBusUnitySessionService::RequestLogout()
44157{
45− Q_EMIT logoutRequested(false);
158+ Q_EMIT LogoutRequested(false);
46159}
47160
48161void DBusUnitySessionService::Reboot()
49162{
50− QDBusMessage msg = QDBusMessage::createMethodCall("org.freedesktop.login1",
51− "/org/freedesktop/login1",
52− "org.freedesktop.login1.Manager",
53− "Reboot");
54− msg << false;
55− QDBusConnection::systemBus().asyncCall(msg);
163+ makeLogin1Call("Reboot", {false});
56164}
57165
58166void DBusUnitySessionService::RequestReboot()
59167{
60− Q_EMIT rebootRequested(false);
168+ Q_EMIT RebootRequested(false);
61169}
62170
63171void DBusUnitySessionService::Shutdown()
64172{
65− QDBusMessage msg = QDBusMessage::createMethodCall("org.freedesktop.login1",
66− "/org/freedesktop/login1",
67− "org.freedesktop.login1.Manager",
68− "PowerOff");
69− msg << false;
70− QDBusConnection::systemBus().asyncCall(msg);
173+ makeLogin1Call("PowerOff", {false});
174+}
175+
176+void DBusUnitySessionService::Suspend()
177+{
178+ makeLogin1Call("Suspend", {false});
179+}
180+
181+void DBusUnitySessionService::Hibernate()
182+{
183+ makeLogin1Call("Hibernate", {false});
184+}
185+
186+void DBusUnitySessionService::HybridSleep()
187+{
188+ makeLogin1Call("HybridSleep", {false});
71189}
72190
73191void DBusUnitySessionService::RequestShutdown()
74192{
75− Q_EMIT shutdownRequested(false);
193+ Q_EMIT ShutdownRequested(false);
76194}
77195
78196enum class Action : unsigned