18 #include "dbusunitysessionservice.h"
21 #include <sys/types.h>
27 #include <QDBusPendingCall>
29 #include <QElapsedTimer>
32 #define LOGIN1_SERVICE QStringLiteral("org.freedesktop.login1")
33 #define LOGIN1_PATH QStringLiteral("/org/freedesktop/login1")
34 #define LOGIN1_IFACE QStringLiteral("org.freedesktop.login1.Manager")
35 #define LOGIN1_SESSION_IFACE QStringLiteral("org.freedesktop.login1.Session")
37 #define ACTIVE_KEY QStringLiteral("Active")
38 #define IDLE_SINCE_KEY QStringLiteral("IdleSinceHint")
40 class DBusUnitySessionServicePrivate:
public QObject
44 QString logindSessionPath;
45 bool isSessionActive =
true;
46 QElapsedTimer screensaverActiveTimer;
48 DBusUnitySessionServicePrivate(): QObject() {
56 QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE,
60 msg << (quint32) getpid();
62 QDBusReply<QDBusObjectPath> reply = QDBusConnection::systemBus().asyncCall(msg);
63 if (reply.isValid()) {
64 logindSessionPath = reply.value().path();
67 QDBusConnection::systemBus().connect(LOGIN1_SERVICE, logindSessionPath,
"org.freedesktop.DBus.Properties",
"PropertiesChanged",
68 this, SLOT(onPropertiesChanged(QString,QVariantMap,QStringList)));
70 qWarning() <<
"Failed to get logind session path" << reply.error().message();
74 bool checkLogin1Call(
const QString &method)
const
76 QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE, LOGIN1_PATH, LOGIN1_IFACE, method);
77 QDBusReply<QString> reply = QDBusConnection::systemBus().asyncCall(msg);
78 return reply.isValid() && (reply == QStringLiteral(
"yes") || reply == QStringLiteral(
"challenge"));
81 void makeLogin1Call(
const QString &method,
const QVariantList &args)
83 QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE,
87 msg.setArguments(args);
88 QDBusConnection::systemBus().asyncCall(msg);
93 if (logindSessionPath.isEmpty()) {
94 qWarning() <<
"Invalid session path";
98 QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE,
100 "org.freedesktop.DBus.Properties",
102 msg << LOGIN1_SESSION_IFACE;
105 QDBusReply<QVariant> reply = QDBusConnection::systemBus().asyncCall(msg);
106 if (reply.isValid()) {
107 isSessionActive = reply.value().toBool();
108 qDebug() <<
"Session" << logindSessionPath <<
"is active:" << isSessionActive;
110 qWarning() <<
"Failed to get Active property" << reply.error().message();
114 quint32 screensaverActiveTime()
const
116 if (!isSessionActive && screensaverActiveTimer.isValid()) {
117 return screensaverActiveTimer.elapsed() / 1000;
123 quint64 idleSinceUSecTimestamp()
const
125 QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE,
127 "org.freedesktop.DBus.Properties",
129 msg << LOGIN1_SESSION_IFACE;
130 msg << IDLE_SINCE_KEY;
132 QDBusReply<QVariant> reply = QDBusConnection::systemBus().asyncCall(msg);
133 if (reply.isValid()) {
134 return reply.value().value<quint64>();
136 qWarning() <<
"Failed to get IdleSinceHint property" << reply.error().message();
142 void setIdleHint(
bool idle)
144 QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE,
146 LOGIN1_SESSION_IFACE,
149 QDBusConnection::systemBus().asyncCall(msg);
153 void onPropertiesChanged(
const QString &iface,
const QVariantMap &changedProps,
const QStringList &invalidatedProps)
157 if (changedProps.contains(ACTIVE_KEY) || invalidatedProps.contains(ACTIVE_KEY)) {
158 if (changedProps.value(ACTIVE_KEY).isValid()) {
159 isSessionActive = changedProps.value(ACTIVE_KEY).toBool();
164 Q_EMIT screensaverActiveChanged(!isSessionActive);
166 if (isSessionActive) {
167 screensaverActiveTimer.invalidate();
170 screensaverActiveTimer.start();
177 void screensaverActiveChanged(
bool active);
180 Q_GLOBAL_STATIC(DBusUnitySessionServicePrivate, d)
183 : UnityDBusObject("/
com/canonical/Unity/Session", "
com.canonical.Unity")
185 if (!d->logindSessionPath.isEmpty()) {
187 QDBusConnection::systemBus().connect(LOGIN1_SERVICE, d->logindSessionPath, LOGIN1_SESSION_IFACE,
"Lock",
this, SLOT(Lock()));
190 QDBusConnection::systemBus().connect(LOGIN1_SERVICE, d->logindSessionPath, LOGIN1_SESSION_IFACE,
"Unlock",
this, SIGNAL(Unlocked()));
192 qWarning() <<
"Failed to connect to logind's session Lock/Unlock signals";
200 Q_EMIT logoutReady();
205 const QDBusMessage msg = QDBusMessage::createMethodCall(
"com.ubuntu.Upstart",
206 "/com/ubuntu/Upstart",
207 "com.ubuntu.Upstart0_6",
209 QDBusConnection::sessionBus().asyncCall(msg);
214 return d->checkLogin1Call(
"CanHibernate");
219 return d->checkLogin1Call(
"CanSuspend");
224 return d->checkLogin1Call(
"CanHybridSleep");
229 return d->checkLogin1Call(
"CanReboot");
234 return d->checkLogin1Call(
"CanPowerOff");
244 struct passwd *p = getpwuid(geteuid());
246 return QString::fromUtf8(p->pw_name);
254 struct passwd *p = getpwuid(geteuid());
256 const QString gecos = QString::fromLocal8Bit(p->pw_gecos);
257 if (!gecos.isEmpty()) {
258 return gecos.split(QLatin1Char(
',')).first();
268 if (gethostname(hostName,
sizeof(hostName)) == -1) {
269 qWarning() <<
"Could not determine local hostname";
272 hostName[
sizeof(hostName) - 1] =
'\0';
273 return QString::fromLocal8Bit(hostName);
279 Q_EMIT lockRequested();
285 const QString sessionPath = QString::fromLocal8Bit(qgetenv(
"XDG_SESSION_PATH"));
286 QDBusMessage msg = QDBusMessage::createMethodCall(
"org.freedesktop.DisplayManager",
288 "org.freedesktop.DisplayManager.Session",
290 qDebug() <<
"Locking session" << msg.path();
291 QDBusReply<void> reply = QDBusConnection::systemBus().asyncCall(msg);
292 if (!reply.isValid()) {
293 qWarning() <<
"Lock call failed" << reply.error().message();
302 return !d->isSessionActive;
308 Q_EMIT logoutRequested(
false);
313 d->makeLogin1Call(
"Reboot", {
false});
319 Q_EMIT rebootRequested(
false);
324 d->makeLogin1Call(
"PowerOff", {
false});
329 d->makeLogin1Call(
"Suspend", {
false});
334 d->makeLogin1Call(
"Hibernate", {
false});
339 d->makeLogin1Call(
"HybridSleep", {
false});
345 Q_EMIT shutdownRequested(
false);
348 enum class Action : unsigned
357 void performAsyncUnityCall(
const QString &method)
359 const QDBusMessage msg = QDBusMessage::createMethodCall(
"com.canonical.Unity",
360 "/com/canonical/Unity/Session",
361 "com.canonical.Unity.Session",
363 QDBusConnection::sessionBus().asyncCall(msg);
367 DBusGnomeSessionManagerWrapper::DBusGnomeSessionManagerWrapper()
368 : UnityDBusObject(
"/org/gnome/SessionManager/EndSessionDialog",
"com.canonical.Unity")
372 void DBusGnomeSessionManagerWrapper::Open(
const unsigned type,
const unsigned arg_1,
const unsigned max_wait,
const QList<QDBusObjectPath> &inhibitors)
376 Q_UNUSED(inhibitors);
378 switch (static_cast<Action>(type))
381 performAsyncUnityCall(
"RequestLogout");
385 performAsyncUnityCall(
"RequestReboot");
388 case Action::SHUTDOWN:
389 performAsyncUnityCall(
"RequestShutdown");
398 DBusGnomeScreensaverWrapper::DBusGnomeScreensaverWrapper()
399 : UnityDBusObject(
"/org/gnome/ScreenSaver",
"org.gnome.ScreenSaver")
401 connect(d, &DBusUnitySessionServicePrivate::screensaverActiveChanged,
this, &DBusGnomeScreensaverWrapper::ActiveChanged);
404 bool DBusGnomeScreensaverWrapper::GetActive()
const
406 return !d->isSessionActive;
409 void DBusGnomeScreensaverWrapper::SetActive(
bool lock)
416 void DBusGnomeScreensaverWrapper::Lock()
418 performAsyncUnityCall(
"Lock");
421 quint32 DBusGnomeScreensaverWrapper::GetActiveTime()
const
423 return d->screensaverActiveTime();
426 void DBusGnomeScreensaverWrapper::SimulateUserActivity()
428 d->setIdleHint(
false);
432 DBusScreensaverWrapper::DBusScreensaverWrapper()
433 : UnityDBusObject(
"/org/freedesktop/ScreenSaver",
"org.freedesktop.ScreenSaver")
435 QDBusConnection::sessionBus().registerObject(
"/ScreenSaver",
this, QDBusConnection::ExportScriptableContents);
436 connect(d, &DBusUnitySessionServicePrivate::screensaverActiveChanged,
this, &DBusScreensaverWrapper::ActiveChanged);
439 bool DBusScreensaverWrapper::GetActive()
const
441 return !d->isSessionActive;
444 bool DBusScreensaverWrapper::SetActive(
bool lock)
453 void DBusScreensaverWrapper::Lock()
455 performAsyncUnityCall(
"Lock");
458 quint32 DBusScreensaverWrapper::GetActiveTime()
const
460 return d->screensaverActiveTime();
463 quint32 DBusScreensaverWrapper::GetSessionIdleTime()
const
465 return QDateTime::fromMSecsSinceEpoch(d->idleSinceUSecTimestamp()/1000).secsTo(QDateTime::currentDateTime());
468 void DBusScreensaverWrapper::SimulateUserActivity()
470 d->setIdleHint(
false);
473 #include "dbusunitysessionservice.moc"
Q_SCRIPTABLE void LogoutReady()
Q_SCRIPTABLE bool CanShutdown() const
Q_SCRIPTABLE void Reboot()
Q_SCRIPTABLE void RebootRequested(bool have_inhibitors)
Q_SCRIPTABLE void RequestLogout()
Q_SCRIPTABLE QString RealName() const
Q_SCRIPTABLE bool CanLock() const
Q_SCRIPTABLE void RequestReboot()
Q_SCRIPTABLE void RequestShutdown()
Q_SCRIPTABLE void HybridSleep()
Q_SCRIPTABLE bool CanHibernate() const
Q_SCRIPTABLE void ShutdownRequested(bool have_inhibitors)
Q_SCRIPTABLE void Hibernate()
Q_SCRIPTABLE void Locked()
Q_SCRIPTABLE QString UserName() const
Q_SCRIPTABLE bool CanSuspend() const
Q_SCRIPTABLE bool IsLocked() const
Q_SCRIPTABLE void Shutdown()
Q_SCRIPTABLE void PromptLock()
Q_SCRIPTABLE void LogoutRequested(bool have_inhibitors)
Q_SCRIPTABLE bool CanReboot() const
Q_SCRIPTABLE void Suspend()
Q_SCRIPTABLE void LockRequested()
Q_SCRIPTABLE QString HostName() const
Q_SCRIPTABLE bool CanHybridSleep() const
Q_SCRIPTABLE void EndSession()
Q_SCRIPTABLE void Logout()