diff --git a/daemon/CMakeLists.txt b/daemon/CMakeLists.txt --- a/daemon/CMakeLists.txt +++ b/daemon/CMakeLists.txt @@ -59,6 +59,8 @@ actions/bundled/wirelesspowersaving.h PowerDevil::BundledActions::WirelessPowerSaving) endif() +qt5_add_dbus_interface(powerdevilcore_SRCS org.freedesktop.ScreenSaver.xml screenlocker_interface) + add_library(powerdevilcore SHARED ${powerdevilcore_SRCS} ${powerdevil_bundled_actions_SRCS}) set_target_properties(powerdevilcore PROPERTIES VERSION ${POWERDEVIL_CORE_VERSION_STRING} SOVERSION ${POWERDEVIL_CORE_VERSION_MAJOR}) diff --git a/daemon/org.freedesktop.ScreenSaver.xml b/daemon/org.freedesktop.ScreenSaver.xml new file mode 100644 --- /dev/null +++ b/daemon/org.freedesktop.ScreenSaver.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/daemon/powerdevilpolicyagent.h b/daemon/powerdevilpolicyagent.h --- a/daemon/powerdevilpolicyagent.h +++ b/daemon/powerdevilpolicyagent.h @@ -34,6 +34,8 @@ class QDBusServiceWatcher; class QDBusInterface; +class OrgFreedesktopScreenSaverInterface; + #define SYSTEMD_LOGIN1_SERVICE "org.freedesktop.login1" #define SYSTEMD_LOGIN1_PATH "/org/freedesktop/login1" #define SYSTEMD_LOGIN1_MANAGER_IFACE "org.freedesktop.login1.Manager" @@ -110,6 +112,14 @@ void addInhibitionTypeHelper(uint cookie, RequiredPolicies types); + // Screen locker integration + void onScreenLockerOwnerChanged(const QString &serviceName, const QString &oldOwner, const QString &newOwner); + QDBusServiceWatcher *m_screenLockerWatcher; + + void onScreenLockerActiveChanged(bool active); + OrgFreedesktopScreenSaverInterface *m_screenLockerInterface = nullptr; + bool m_screenLockerActive = false; + // This function serves solely for fd.o connector uint addInhibitionWithExplicitDBusService(uint types, const QString &appName, const QString &reason, const QString &service); diff --git a/daemon/powerdevilpolicyagent.cpp b/daemon/powerdevilpolicyagent.cpp --- a/daemon/powerdevilpolicyagent.cpp +++ b/daemon/powerdevilpolicyagent.cpp @@ -1,6 +1,7 @@ /*************************************************************************** * Copyright (C) 2010 by Dario Freddi * * Copyright (C) 2012 Lukáš Tinkl * + * Copyright (C) 2016 Kai Uwe Broulik * * * * 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 * @@ -35,6 +36,8 @@ #include "powerdevilpolicyagent.h" #include "powerdevil_debug.h" +#include "screenlocker_interface.h" + struct NamedDBusObjectPath { QString name; @@ -66,6 +69,8 @@ namespace PowerDevil { +static const QString SCREEN_LOCKER_SERVICE_NAME = QStringLiteral("org.freedesktop.ScreenSaver"); + class PolicyAgentHelper { public: @@ -89,6 +94,7 @@ PolicyAgent::PolicyAgent(QObject* parent) : QObject(parent) + , m_screenLockerWatcher(new QDBusServiceWatcher(this)) , m_sdAvailable(false) , m_systemdInhibitFd(-1) , m_ckAvailable(false) @@ -148,6 +154,29 @@ connect(m_busWatcher.data(), SIGNAL(serviceUnregistered(QString)), this, SLOT(onServiceUnregistered(QString))); + + // Setup the screen locker watcher and check whether the screen is currently locked + connect(m_screenLockerWatcher, &QDBusServiceWatcher::serviceOwnerChanged, this, &PolicyAgent::onScreenLockerOwnerChanged); + m_screenLockerWatcher->setWatchMode(QDBusServiceWatcher::WatchForOwnerChange); + m_screenLockerWatcher->addWatchedService(SCREEN_LOCKER_SERVICE_NAME); + + // async variant of QDBusConnectionInterface::serviceOwner ... + auto msg = QDBusMessage::createMethodCall( + QStringLiteral("org.freedesktop.DBus"), + QStringLiteral("/"), + QStringLiteral("org.freedesktop.DBus"), + QStringLiteral("GetNameOwner") + ); + msg.setArguments({SCREEN_LOCKER_SERVICE_NAME}); + + auto *watcher = new QDBusPendingCallWatcher(QDBusConnection::sessionBus().asyncCall(msg), this); + QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) { + QDBusPendingReply reply = *watcher; + if (!reply.isError()) { + onScreenLockerOwnerChanged(SCREEN_LOCKER_SERVICE_NAME, {}, reply.value()); + } + watcher->deleteLater(); + }); } QString PolicyAgent::getNamedPathProperty(const QString &path, const QString &iface, const QString &prop) const @@ -363,7 +392,8 @@ if (!m_typesToCookie[ChangeProfile].isEmpty()) { retpolicies |= ChangeProfile; } - if (!m_typesToCookie[ChangeScreenSettings].isEmpty()) { + // when screen locker is active it makes no sense to keep the screen on + if (!m_screenLockerActive && !m_typesToCookie[ChangeScreenSettings].isEmpty()) { retpolicies |= ChangeScreenSettings; } if (!m_typesToCookie[InterruptSession].isEmpty()) { @@ -430,6 +460,46 @@ m_sessionIsBeingInterrupted = false; } +void PolicyAgent::onScreenLockerOwnerChanged(const QString &serviceName, const QString &oldOwner, const QString &newOwner) +{ + Q_UNUSED(oldOwner); + if (serviceName != SCREEN_LOCKER_SERVICE_NAME) { + return; + } + + delete m_screenLockerInterface; + m_screenLockerInterface = nullptr; + m_screenLockerActive = false; + + if (!newOwner.isEmpty()) { + m_screenLockerInterface = new OrgFreedesktopScreenSaverInterface(newOwner, QStringLiteral("/ScreenSaver"), QDBusConnection::sessionBus(), this); + connect(m_screenLockerInterface, &OrgFreedesktopScreenSaverInterface::ActiveChanged, this, &PolicyAgent::onScreenLockerActiveChanged); + + auto *activeReplyWatcher = new QDBusPendingCallWatcher(m_screenLockerInterface->GetActive()); + connect(activeReplyWatcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) { + QDBusPendingReply reply = *watcher; + if (!reply.isError()) { + onScreenLockerActiveChanged(reply.value()); + } + watcher->deleteLater(); + }); + } +} + +void PolicyAgent::onScreenLockerActiveChanged(bool active) +{ + const auto oldPolicies = unavailablePolicies(); + + m_screenLockerActive = active; + + const auto newPolicies = unavailablePolicies(); + + if (oldPolicies != newPolicies) { + qCDebug(POWERDEVIL) << "Screen saver active" << active << "- we have different inhibition policy now because of that"; + Q_EMIT unavailablePoliciesChanged(newPolicies); + } +} + uint PolicyAgent::addInhibitionWithExplicitDBusService(uint types, const QString &appName, const QString &reason, const QString &service) {