on cf40464 help sign in
unity8/plugins/SessionManager/SessionManager.cpp
124 lines 5.2 kB history raw
1/*
2 * Copyright (C) 2013 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Author: Michael Terry <michael.terry@canonical.com>
17 */
19#include "SessionManager.h"
20#include <QtCore/QEvent>
21#include <QtDBus/QDBusPendingReply>
23SessionManager::SessionManager(QObject* parent)
24 : QObject(parent),
25 l1_manager(NULL),
26 l1_session(NULL),
27 ldm_session(NULL),
28 is_active(true) // assume we're active w/o logind
30 l1_manager = new QDBusInterface("org.freedesktop.login1",
31 "/org/freedesktop/login1",
32 "org.freedesktop.login1.Manager",
33 QDBusConnection::SM_BUSNAME(), this);
34 if (l1_manager->isValid() && QString(qgetenv("XDG_SESSION_ID")) != "") {
35 QDBusPendingCall pcall = l1_manager->asyncCall("GetSession", QString(qgetenv("XDG_SESSION_ID")));
36 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this);
37 QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
38 this, SLOT(getSessionSlot(QDBusPendingCallWatcher*)));
39 }
41 if (QString(qgetenv("XDG_SESSION_PATH")) != "") {
42 ldm_session = new QDBusInterface("org.freedesktop.DisplayManager",
43 QString(qgetenv("XDG_SESSION_PATH")),
44 "org.freedesktop.DisplayManager.Session",
45 QDBusConnection::SM_BUSNAME(), this);
46 }
49bool SessionManager::active() const
51 // We cache this value for performance reasons, as QDBusInterface does not
52 // cache for us.
53 return is_active;
56void SessionManager::lock()
58 // We use ldm_session to handle locking rather than l1_session, because
59 // l1_session doesn't have permissions to lock from the user session, but
60 // ldm_session does. This is what the rest of Ubuntu uses to lock.
61 if (ldm_session != NULL && ldm_session->isValid())
62 ldm_session->asyncCall("Lock");
65void SessionManager::getSessionSlot(QDBusPendingCallWatcher *watcher)
67 QDBusPendingReply<QDBusObjectPath> reply = *watcher;
68 if (!reply.isError()) {
69 QDBusObjectPath path = reply.argumentAt<0>();
70 l1_session = new QDBusInterface("org.freedesktop.login1",
71 path.path(),
72 "org.freedesktop.login1.Session",
73 l1_manager->connection(), this);
75 l1_manager->connection().connect("org.freedesktop.login1",
76 path.path(),
77 "org.freedesktop.DBus.Properties",
78 "PropertiesChanged",
79 this,
80 SLOT(propertiesChanged(QString, QVariantMap, QStringList)));
82 // Login1 is very odd about emitting PropertiesChanged. It often does
83 // not do so when active is becoming false. But it always does when
84 // it becomes true. So we watch for the "Lock" signal too, which is a
85 // reliably hint that active is false.
86 l1_manager->connection().connect("org.freedesktop.login1",
87 path.path(),
88 "org.freedesktop.login1.Session",
89 "Lock",
90 this,
91 SLOT(sessionLocked()));
93 propertiesChanged("", QVariantMap(), QStringList() << "Active");
94 }
95 watcher->deleteLater();
98void SessionManager::propertiesChanged(const QString &interface, const QVariantMap &changed, const QStringList &invalid)
100 Q_UNUSED(interface)
102 QVariant value = changed.value("Active");
104 // If Active isn't in changed, check if we were at least notified about it
105 // changing on the server. Also check if IdleHint was modified, because
106 // sometimes logind does not emit a changed signal for Active becoming
107 // false, but will emit for IdleHint when that does happen.
108 if (!value.isValid() && (invalid.contains("Active") || invalid.contains("IdleHint") || changed.contains("IdleHint")) && l1_session->isValid()) {
109 value = l1_session->property("Active");
110 if (!value.isValid())
111 value = QVariant(false);
112 }
114 if (value.isValid() && value.toBool() != is_active) {
115 is_active = value.toBool();
116 Q_EMIT activeChanged();
117 }
120void SessionManager::sessionLocked()
122 is_active = false;
123 Q_EMIT activeChanged();