File indexing completed on 2024-05-05 17:33:04

0001 /*
0002    SPDX-FileCopyrightText: 2019 (c) Matthieu Gallien <matthieu_gallien@yahoo.fr>
0003 
0004    SPDX-License-Identifier: LGPL-3.0-or-later
0005  */
0006 
0007 #include "PowerManagementInterface.h"
0008 
0009 #include <KLocalizedString>
0010 
0011 #include <QDBusConnection>
0012 #include <QDBusMessage>
0013 #include <QDBusPendingCall>
0014 #include <QDBusPendingCallWatcher>
0015 #include <QDBusPendingReply>
0016 #include <QDBusUnixFileDescriptor>
0017 
0018 #include <QString>
0019 
0020 #include <QGuiApplication>
0021 
0022 #include <QLoggingCategory>
0023 
0024 class PowerManagementInterfacePrivate
0025 {
0026 public:
0027     bool mPreventSleep = false;
0028 
0029     bool mInhibitedSleep = false;
0030 
0031     uint mInhibitSleepCookie = 0;
0032 
0033     QString m_reason;
0034 };
0035 
0036 PowerManagementInterface::PowerManagementInterface(QObject *parent)
0037     : QObject(parent)
0038     , d(std::make_unique<PowerManagementInterfacePrivate>())
0039 {
0040     auto sessionBus = QDBusConnection::sessionBus();
0041 
0042     sessionBus.connect(QStringLiteral("org.freedesktop.PowerManagement.Inhibit"),
0043                        QStringLiteral("/org/freedesktop/PowerManagement/Inhibit"),
0044                        QStringLiteral("org.freedesktop.PowerManagement.Inhibit"),
0045                        QStringLiteral("HasInhibitChanged"),
0046                        this,
0047                        SLOT(hostSleepInhibitChanged()));
0048 }
0049 
0050 PowerManagementInterface::~PowerManagementInterface() = default;
0051 
0052 bool PowerManagementInterface::preventSleep() const
0053 {
0054     return d->mPreventSleep;
0055 }
0056 
0057 bool PowerManagementInterface::sleepInhibited() const
0058 {
0059     return d->mInhibitedSleep;
0060 }
0061 
0062 void PowerManagementInterface::setPreventSleep(bool value)
0063 {
0064     if (d->mPreventSleep == value) {
0065         return;
0066     }
0067 
0068     if (value) {
0069         inhibitSleep();
0070         d->mPreventSleep = true;
0071     } else {
0072         uninhibitSleep();
0073         d->mPreventSleep = false;
0074     }
0075 
0076     Q_EMIT preventSleepChanged();
0077 }
0078 
0079 void PowerManagementInterface::retryInhibitingSleep()
0080 {
0081     if (d->mPreventSleep && !d->mInhibitedSleep) {
0082         inhibitSleep();
0083     }
0084 }
0085 
0086 void PowerManagementInterface::hostSleepInhibitChanged()
0087 {
0088 }
0089 
0090 void PowerManagementInterface::inhibitDBusCallFinished(QDBusPendingCallWatcher *aWatcher)
0091 {
0092     QDBusPendingReply<uint> reply = *aWatcher;
0093     if (reply.isError()) {
0094     } else {
0095         d->mInhibitSleepCookie = reply.argumentAt<0>();
0096         d->mInhibitedSleep = true;
0097 
0098         Q_EMIT sleepInhibitedChanged();
0099     }
0100     aWatcher->deleteLater();
0101 }
0102 
0103 void PowerManagementInterface::uninhibitDBusCallFinished(QDBusPendingCallWatcher *aWatcher)
0104 {
0105     QDBusPendingReply<> reply = *aWatcher;
0106     if (reply.isError()) {
0107         qDebug() << "PowerManagementInterface::uninhibitDBusCallFinished" << reply.error();
0108     } else {
0109         d->mInhibitedSleep = false;
0110 
0111         Q_EMIT sleepInhibitedChanged();
0112     }
0113     aWatcher->deleteLater();
0114 }
0115 
0116 void PowerManagementInterface::inhibitSleep()
0117 {
0118     auto sessionBus = QDBusConnection::sessionBus();
0119 
0120     auto inhibitCall = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.PowerManagement.Inhibit"),
0121                                                       QStringLiteral("/org/freedesktop/PowerManagement/Inhibit"),
0122                                                       QStringLiteral("org.freedesktop.PowerManagement.Inhibit"),
0123                                                       QStringLiteral("Inhibit"));
0124 
0125     inhibitCall.setArguments({{QGuiApplication::desktopFileName()}, {d->m_reason}});
0126 
0127     auto asyncReply = sessionBus.asyncCall(inhibitCall);
0128 
0129     auto replyWatcher = new QDBusPendingCallWatcher(asyncReply, this);
0130 
0131     QObject::connect(replyWatcher, &QDBusPendingCallWatcher::finished, this, &PowerManagementInterface::inhibitDBusCallFinished);
0132 }
0133 
0134 void PowerManagementInterface::uninhibitSleep()
0135 {
0136     auto sessionBus = QDBusConnection::sessionBus();
0137 
0138     auto uninhibitCall = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.PowerManagement.Inhibit"),
0139                                                         QStringLiteral("/org/freedesktop/PowerManagement/Inhibit"),
0140                                                         QStringLiteral("org.freedesktop.PowerManagement.Inhibit"),
0141                                                         QStringLiteral("UnInhibit"));
0142 
0143     uninhibitCall.setArguments({{d->mInhibitSleepCookie}});
0144 
0145     auto asyncReply = sessionBus.asyncCall(uninhibitCall);
0146 
0147     auto replyWatcher = new QDBusPendingCallWatcher(asyncReply, this);
0148 
0149     QObject::connect(replyWatcher, &QDBusPendingCallWatcher::finished, this, &PowerManagementInterface::uninhibitDBusCallFinished);
0150 }
0151 
0152 QString PowerManagementInterface::reason() const
0153 {
0154     return d->m_reason;
0155 }
0156 
0157 void PowerManagementInterface::setReason(const QString &reason)
0158 {
0159     d->m_reason = reason;
0160 }