@@ -1,5 +1,5 @@
2− * Copyright (C) 2014 Canonical, Ltd.
2+ * Copyright (C) 2014, 2015 Canonical, Ltd.
4 * This program is free software: you can redistribute it and/or modify it under
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by
5 * the terms of the GNU Lesser General Public License version 3, as published by
@@ -12,6 +12,10 @@
13 * You should have received a copy of the GNU Lesser General Public License
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16+ * Authors: Lukáš Tinkl <ltinkl@canonical.com>
17+ * Christopher Townsend <christopher.townsend@canonical.com>
18+ * Paul Liu <paul.liu@canonical.com>
@@ -26,18 +30,27 @@
26#include <QDebug>
30#include <QDebug>
27#include <QDBusPendingCall>
31#include <QDBusPendingCall>
28#include <QDBusReply>
32#include <QDBusReply>
33+#include <QElapsedTimer>
30#define LOGIN1_SERVICE QStringLiteral("org.freedesktop.login1")
35#define LOGIN1_SERVICE QStringLiteral("org.freedesktop.login1")
31#define LOGIN1_PATH QStringLiteral("/org/freedesktop/login1")
36#define LOGIN1_PATH QStringLiteral("/org/freedesktop/login1")
32#define LOGIN1_IFACE QStringLiteral("org.freedesktop.login1.Manager")
37#define LOGIN1_IFACE QStringLiteral("org.freedesktop.login1.Manager")
33#define LOGIN1_SESSION_IFACE QStringLiteral("org.freedesktop.login1.Session")
38#define LOGIN1_SESSION_IFACE QStringLiteral("org.freedesktop.login1.Session")
40+#define ACTIVE_KEY QStringLiteral("Active")
35class DBusUnitySessionServicePrivate: public QObject
42class DBusUnitySessionServicePrivate: public QObject
38 QString logindSessionPath;
46 QString logindSessionPath;
47+ bool isActive = true;
48+ QElapsedTimer screensaverActiveTimer;
40− DBusUnitySessionServicePrivate(): QObject() { init(); }
50+ DBusUnitySessionServicePrivate(): QObject() {
42 void init()
55 void init()
@@ -51,7 +64,11 @@ public:
51 QDBusReply<QDBusObjectPath> reply = QDBusConnection::systemBus().asyncCall(msg);
64 QDBusReply<QDBusObjectPath> reply = QDBusConnection::systemBus().asyncCall(msg);
52 if (reply.isValid()) {
65 if (reply.isValid()) {
53 logindSessionPath = reply.value().path();
66 logindSessionPath = reply.value().path();
54− qDebug() << "session path" << logindSessionPath;
67+ //qDebug() << "session path" << logindSessionPath;
69+ // start watching the Active property
70+ QDBusConnection::systemBus().connect(LOGIN1_SERVICE, logindSessionPath, "org.freedesktop.DBus.Properties", "PropertiesChanged",
71+ this, SLOT(onPropertiesChanged(QString,QVariantMap,QStringList)));
56 qWarning() << "Failed to get logind session path" << reply.error().message();
73 qWarning() << "Failed to get logind session path" << reply.error().message();
@@ -74,11 +91,11 @@ public:
74 QDBusConnection::systemBus().asyncCall(msg);
91 QDBusConnection::systemBus().asyncCall(msg);
77− bool isActive() const
94+ void checkActive()
79 if (logindSessionPath.isEmpty()) {
96 if (logindSessionPath.isEmpty()) {
80 qWarning() << "Invalid session path";
97 qWarning() << "Invalid session path";
81− return true; //assume active
98+ return;
84 QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE,
101 QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE,
@@ -86,17 +103,39 @@ public:
86 "org.freedesktop.DBus.Properties",
103 "org.freedesktop.DBus.Properties",
88 msg << LOGIN1_SESSION_IFACE;
105 msg << LOGIN1_SESSION_IFACE;
89− msg << QStringLiteral("Active");
106+ msg << ACTIVE_KEY;
91− QDBusReply<bool> reply = QDBusConnection::systemBus().asyncCall(msg);
108+ QDBusReply<QVariant> reply = QDBusConnection::systemBus().asyncCall(msg);
92 if (reply.isValid()) {
109 if (reply.isValid()) {
93− return reply;
110+ isActive = reply.value().toBool();
111+ qDebug() << "Session" << logindSessionPath << "is active:" << isActive;
95 qWarning() << "Failed to get Active property" << reply.error().message();
113 qWarning() << "Failed to get Active property" << reply.error().message();
98− return true; // assume active
117+private Q_SLOTS:
118+ void onPropertiesChanged(const QString &iface, const QVariantMap &changedProps, const QStringList &invalidatedProps)
122+ if (changedProps.contains(ACTIVE_KEY)) {
123+ isActive = changedProps.value(ACTIVE_KEY).toBool();
124+ } else if (invalidatedProps.contains(ACTIVE_KEY)) {
128+ Q_EMIT screensaverActiveChanged(!isActive);
131+ screensaverActiveTimer.invalidate();
133+ screensaverActiveTimer.start();
138+ void screensaverActiveChanged(bool active);
102Q_GLOBAL_STATIC(DBusUnitySessionServicePrivate, d)
141Q_GLOBAL_STATIC(DBusUnitySessionServicePrivate, d)
@@ -219,7 +258,7 @@ void DBusUnitySessionService::Lock()
220bool DBusUnitySessionService::IsLocked() const
259bool DBusUnitySessionService::IsLocked() const
222− return !d->isActive();
261+ return !d->isActive;
225void DBusUnitySessionService::RequestLogout()
264void DBusUnitySessionService::RequestLogout()
@@ -270,12 +309,8 @@ enum class Action : unsigned
273−DBusGnomeSessionManagerWrapper::DBusGnomeSessionManagerWrapper()
274− : UnityDBusObject("/org/gnome/SessionManager/EndSessionDialog", "com.canonical.Unity")
278−void DBusGnomeSessionManagerWrapper::performAsyncCall(const QString &method)
313+void performAsyncUnityCall(const QString &method)
280 const QDBusMessage msg = QDBusMessage::createMethodCall("com.canonical.Unity",
315 const QDBusMessage msg = QDBusMessage::createMethodCall("com.canonical.Unity",
281 "/com/canonical/Unity/Session",
316 "/com/canonical/Unity/Session",
@@ -284,29 +319,67 @@ void DBusGnomeSessionManagerWrapper::performAsyncCall(const QString &method)
284 QDBusConnection::sessionBus().asyncCall(msg);
319 QDBusConnection::sessionBus().asyncCall(msg);
322+DBusGnomeSessionManagerWrapper::DBusGnomeSessionManagerWrapper()
323+ : UnityDBusObject("/org/gnome/SessionManager/EndSessionDialog", "com.canonical.Unity")
287void DBusGnomeSessionManagerWrapper::Open(const unsigned type, const unsigned arg_1, const unsigned max_wait, const QList<QDBusObjectPath> &inhibitors)
327void DBusGnomeSessionManagerWrapper::Open(const unsigned type, const unsigned arg_1, const unsigned max_wait, const QList<QDBusObjectPath> &inhibitors)
289 Q_UNUSED(arg_1);
329 Q_UNUSED(arg_1);
290 Q_UNUSED(max_wait);
330 Q_UNUSED(max_wait);
291 Q_UNUSED(inhibitors);
331 Q_UNUSED(inhibitors);
293− const Action action = (Action)type;
333+ switch (static_cast<Action>(type))
297 case Action::LOGOUT:
335 case Action::LOGOUT:
298− performAsyncCall("RequestLogout");
336+ performAsyncUnityCall("RequestLogout");
301 case Action::REBOOT:
339 case Action::REBOOT:
302− performAsyncCall("RequestReboot");
340+ performAsyncUnityCall("RequestReboot");
305 case Action::SHUTDOWN:
343 case Action::SHUTDOWN:
306− performAsyncCall("RequestShutdown");
344+ performAsyncUnityCall("RequestShutdown");
353+DBusGnomeScreensaverWrapper::DBusGnomeScreensaverWrapper()
354+ : UnityDBusObject("/org/gnome/ScreenSaver", "org.gnome.ScreenSaver")
356+ connect(d, &DBusUnitySessionServicePrivate::screensaverActiveChanged, this, &DBusGnomeScreensaverWrapper::ActiveChanged);
359+bool DBusGnomeScreensaverWrapper::GetActive() const
361+ return !d->isActive; // return whether the session is not active
364+void DBusGnomeScreensaverWrapper::SetActive(bool lock)
371+void DBusGnomeScreensaverWrapper::Lock()
373+ performAsyncUnityCall("Lock");
376+quint32 DBusGnomeScreensaverWrapper::GetActiveTime() const
378+ if (GetActive() && d->screensaverActiveTimer.isValid()) {
379+ return d->screensaverActiveTimer.elapsed() / 1000;
385+#include "dbusunitysessionservice.moc"