diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,6 +101,7 @@ logind.cpp waylandserver.cpp powermanagement.cpp + powermanagement_inhibition.cpp ) qt5_add_dbus_adaptor(ksld_SRCS ${screensaver_dbusXML} interface.h ScreenLocker::Interface) qt5_add_dbus_adaptor(ksld_SRCS ${kscreensaver_dbusXML} interface.h ScreenLocker::Interface kscreensaveradaptor KScreenSaverAdaptor) diff --git a/ksldapp.h b/ksldapp.h --- a/ksldapp.h +++ b/ksldapp.h @@ -33,6 +33,7 @@ class LogindIntegration; class QTimer; class KSldTest; +class PowerManagementInhibition; namespace KWayland { @@ -157,6 +158,7 @@ bool m_isWayland; int m_greeterCrashedCounter = 0; QProcessEnvironment m_greeterEnv; + PowerManagementInhibition *m_powerManagementInhibition; // for auto tests friend KSldTest; diff --git a/ksldapp.cpp b/ksldapp.cpp --- a/ksldapp.cpp +++ b/ksldapp.cpp @@ -27,6 +27,7 @@ #include "waylandlocker.h" #include "logind.h" #include "kscreensaversettings.h" +#include "powermanagement_inhibition.h" #include #include #include "waylandserver.h" @@ -90,6 +91,7 @@ , m_inhibitCounter(0) , m_logind(nullptr) , m_greeterEnv(QProcessEnvironment::systemEnvironment()) + , m_powerManagementInhibition(new PowerManagementInhibition(this)) { m_isX11 = QX11Info::isPlatformX11(); m_isWayland = QGuiApplication::platformName().startsWith( QLatin1String("wayland"), Qt::CaseInsensitive); @@ -536,14 +538,7 @@ bool KSldApp::isFdoPowerInhibited() const { - QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.Solid.PowerManagement.PolicyAgent"), - QStringLiteral("/org/kde/Solid/PowerManagement/PolicyAgent"), - QStringLiteral("org.kde.Solid.PowerManagement.PolicyAgent"), - QStringLiteral("HasInhibition")); - msg << (uint) 5; // PowerDevil::PolicyAgent::RequiredPolicy::ChangeScreenSettings | PowerDevil::PolicyAgent::RequiredPolicy::InterruptSession - QDBusReply reply = QDBusConnection::sessionBus().asyncCall(msg); - - return reply.isValid() && reply.value(); + return m_powerManagementInhibition->isInhibited(); } void KSldApp::startLockProcess(EstablishLock establishLock) diff --git a/powermanagement_inhibition.h b/powermanagement_inhibition.h new file mode 100644 --- /dev/null +++ b/powermanagement_inhibition.h @@ -0,0 +1,52 @@ +/******************************************************************** + KSld - the KDE Screenlocker Daemon + This file is part of the KDE project. + + Copyright (C) 2016 Martin Gräßlin + +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; either version 2 of the License, or +(at your option) any later version. + +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 . +*********************************************************************/ +#ifndef POWERMANAGEMENT_INHIBITION_H +#define POWERMANAGEMENT_INHIBITION_H + +#include + +class QDBusServiceWatcher; + +using InhibitionInfo = QPair; + +class PowerManagementInhibition : public QObject +{ + Q_OBJECT +public: + PowerManagementInhibition(QObject *parent = nullptr); + virtual ~PowerManagementInhibition(); + + bool isInhibited() const { + return m_inhibited; + } + +private Q_SLOTS: + void inhibitionsChanged(const QList &added, const QStringList &removed); + +private: + void checkInhibition(); + void update(); + + QDBusServiceWatcher *m_solidPowerServiceWatcher; + bool m_serviceRegistered = false; + bool m_inhibited = false; +}; + +#endif diff --git a/powermanagement_inhibition.cpp b/powermanagement_inhibition.cpp new file mode 100644 --- /dev/null +++ b/powermanagement_inhibition.cpp @@ -0,0 +1,112 @@ +/******************************************************************** + KSld - the KDE Screenlocker Daemon + This file is part of the KDE project. + + Copyright (C) 2016 Martin Gräßlin + +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; either version 2 of the License, or +(at your option) any later version. + +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 . +*********************************************************************/ +#include "powermanagement_inhibition.h" + +#include +#include +#include +#include +#include +#include + +static const QString s_solidPowerService = QStringLiteral("org.kde.Solid.PowerManagement.PolicyAgent"); +static const QString s_solidPath = QStringLiteral("/org/kde/Solid/PowerManagement/PolicyAgent"); + +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(InhibitionInfo) + +PowerManagementInhibition::PowerManagementInhibition(QObject *parent) + : QObject(parent) + , m_solidPowerServiceWatcher(new QDBusServiceWatcher(s_solidPowerService, QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForUnregistration | QDBusServiceWatcher::WatchForRegistration)) +{ + qDBusRegisterMetaType>(); + qDBusRegisterMetaType(); + + connect(m_solidPowerServiceWatcher, &QDBusServiceWatcher::serviceUnregistered, this, + [this] { + m_serviceRegistered = false; + m_inhibited = false; + QDBusConnection::sessionBus().disconnect(s_solidPowerService, s_solidPath, s_solidPowerService, + QStringLiteral("InhibitionsChanged"), + this, SLOT(inhibitionsChanged(QList,QStringList))); + } + ); + connect(m_solidPowerServiceWatcher, &QDBusServiceWatcher::serviceRegistered, this, &PowerManagementInhibition::update); + + + // check whether the service is registered + QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.DBus"), + QStringLiteral("/"), + QStringLiteral("org.freedesktop.DBus"), + QStringLiteral("ListNames")); + QDBusPendingReply async = QDBusConnection::sessionBus().asyncCall(message); + QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(async, this); + connect(callWatcher, &QDBusPendingCallWatcher::finished, this, + [this](QDBusPendingCallWatcher *self) { + QDBusPendingReply reply = *self; + self->deleteLater(); + if (!reply.isValid()) { + return; + } + if (reply.value().contains(s_solidPowerService)) { + update(); + } + } + ); +} + +PowerManagementInhibition::~PowerManagementInhibition() = default; + +void PowerManagementInhibition::update() +{ + m_serviceRegistered = true; + QDBusConnection::sessionBus().connect(s_solidPowerService, s_solidPath, s_solidPowerService, + QStringLiteral("InhibitionsChanged"), + this, SLOT(inhibitionsChanged(QList,QStringList))); + checkInhibition(); +} + +void PowerManagementInhibition::inhibitionsChanged(const QList &added, const QStringList &removed) +{ + Q_UNUSED(added) + Q_UNUSED(removed) + checkInhibition(); +} + +void PowerManagementInhibition::checkInhibition() +{ + QDBusMessage msg = QDBusMessage::createMethodCall(s_solidPowerService, + s_solidPath, + s_solidPowerService, + QStringLiteral("HasInhibition")); + msg << (uint) 5; // PowerDevil::PolicyAgent::RequiredPolicy::ChangeScreenSettings | PowerDevil::PolicyAgent::RequiredPolicy::InterruptSession + QDBusPendingReply pendingReply = QDBusConnection::sessionBus().asyncCall(msg); + QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(pendingReply, this); + connect(callWatcher, &QDBusPendingCallWatcher::finished, this, + [this](QDBusPendingCallWatcher *self) { + QDBusPendingReply reply = *self; + self->deleteLater(); + if (!reply.isValid()) { + return; + } + m_inhibited = reply.value(); + } + ); +}