/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Author: Michael Terry */ #include "SessionManager.h" #include #include SessionManager::SessionManager(QObject* parent) : QObject(parent), l1_manager(NULL), l1_session(NULL), ldm_session(NULL), is_active(true) // assume we're active w/o logind { l1_manager = new QDBusInterface("org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", QDBusConnection::SM_BUSNAME(), this); if (l1_manager->isValid() && QString(qgetenv("XDG_SESSION_ID")) != "") { QDBusPendingCall pcall = l1_manager->asyncCall("GetSession", QString(qgetenv("XDG_SESSION_ID"))); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this); QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(getSessionSlot(QDBusPendingCallWatcher*))); } if (QString(qgetenv("XDG_SESSION_PATH")) != "") { ldm_session = new QDBusInterface("org.freedesktop.DisplayManager", QString(qgetenv("XDG_SESSION_PATH")), "org.freedesktop.DisplayManager.Session", QDBusConnection::SM_BUSNAME(), this); } } bool SessionManager::active() const { // We cache this value for performance reasons, as QDBusInterface does not // cache for us. return is_active; } void SessionManager::lock() { // We use ldm_session to handle locking rather than l1_session, because // l1_session doesn't have permissions to lock from the user session, but // ldm_session does. This is what the rest of Ubuntu uses to lock. if (ldm_session != NULL && ldm_session->isValid()) ldm_session->asyncCall("Lock"); } void SessionManager::getSessionSlot(QDBusPendingCallWatcher *watcher) { QDBusPendingReply reply = *watcher; if (!reply.isError()) { QDBusObjectPath path = reply.argumentAt<0>(); l1_session = new QDBusInterface("org.freedesktop.login1", path.path(), "org.freedesktop.login1.Session", l1_manager->connection(), this); l1_manager->connection().connect("org.freedesktop.login1", path.path(), "org.freedesktop.DBus.Properties", "PropertiesChanged", this, SLOT(propertiesChanged(QString, QVariantMap, QStringList))); propertiesChanged("", QVariantMap(), QStringList() << "Active"); } watcher->deleteLater(); } void SessionManager::propertiesChanged(const QString &interface, const QVariantMap &changed, const QStringList &invalid) { Q_UNUSED(interface) QVariant value = changed.value("Active"); // If Active isn't in changed, check if we were at least notified about it // changing on the server. Also check if IdleHint was modified, because // sometimes logind does not emit a changed signal for Active becoming // false, but will emit for IdleHint when that does happen. if (!value.isValid() && (invalid.contains("Active") || invalid.contains("IdleHint") || changed.contains("IdleHint")) && l1_session->isValid()) { value = l1_session->property("Active"); if (!value.isValid()) value = QVariant(false); } if (value.isValid() && value.toBool() != is_active) { is_active = value.toBool(); Q_EMIT activeChanged(); } }