File indexing completed on 2024-04-14 04:44:03

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 "config-upnp-qt.h"
0010 
0011 #include "powerManagementLogging.h"
0012 
0013 #include <KLocalizedString>
0014 
0015 #if QtDBus_FOUND
0016 #include <QDBusConnection>
0017 #include <QDBusMessage>
0018 #include <QDBusPendingCall>
0019 #include <QDBusPendingCallWatcher>
0020 #include <QDBusPendingReply>
0021 #endif
0022 
0023 #if defined Q_OS_WIN
0024 #include <windows.h>
0025 #include <winbase.h>
0026 #endif
0027 
0028 #include <QString>
0029 
0030 #include <QGuiApplication>
0031 
0032 
0033 class PowerManagementInterfacePrivate
0034 {
0035 public:
0036 
0037     bool mPreventSleep = false;
0038 
0039     bool mInhibitedSleep = false;
0040 
0041     uint mInhibitSleepCookie = 0;
0042 
0043 };
0044 
0045 PowerManagementInterface::PowerManagementInterface(QObject *parent) : QObject(parent), d(std::make_unique<PowerManagementInterfacePrivate>())
0046 {
0047 #if QtDBus_FOUND
0048     auto sessionBus = QDBusConnection::sessionBus();
0049 
0050     sessionBus.connect(QStringLiteral("org.freedesktop.PowerManagement.Inhibit"),
0051                        QStringLiteral("/org/freedesktop/PowerManagement/Inhibit"),
0052                        QStringLiteral("org.freedesktop.PowerManagement.Inhibit"),
0053                        QStringLiteral("HasInhibitChanged"), this, SLOT(hostSleepInhibitChanged()));
0054 #endif
0055 }
0056 
0057 PowerManagementInterface::~PowerManagementInterface() = default;
0058 
0059 bool PowerManagementInterface::preventSleep() const
0060 {
0061     return d->mPreventSleep;
0062 }
0063 
0064 bool PowerManagementInterface::sleepInhibited() const
0065 {
0066     return d->mInhibitedSleep;
0067 }
0068 
0069 void PowerManagementInterface::setPreventSleep(bool value)
0070 {
0071     if (d->mPreventSleep == value) {
0072         return;
0073     }
0074 
0075     if (value) {
0076         inhibitSleepPlasmaWorkspace();
0077         inhibitSleepGnomeWorkspace();
0078         d->mPreventSleep = true;
0079     } else {
0080         uninhibitSleepPlasmaWorkspace();
0081         uninhibitSleepGnomeWorkspace();
0082         d->mPreventSleep = false;
0083     }
0084 
0085     Q_EMIT preventSleepChanged();
0086 }
0087 
0088 void PowerManagementInterface::retryInhibitingSleep()
0089 {
0090     if (d->mPreventSleep && !d->mInhibitedSleep) {
0091         inhibitSleepPlasmaWorkspace();
0092         inhibitSleepGnomeWorkspace();
0093     }
0094 }
0095 
0096 void PowerManagementInterface::hostSleepInhibitChanged()
0097 {
0098 }
0099 
0100 void PowerManagementInterface::inhibitDBusCallFinishedPlasmaWorkspace(QDBusPendingCallWatcher *aWatcher)
0101 {
0102 #if QtDBus_FOUND
0103     QDBusPendingReply<uint> reply = *aWatcher;
0104     if (reply.isError()) {
0105     } else {
0106         d->mInhibitSleepCookie = reply.argumentAt<0>();
0107         d->mInhibitedSleep = true;
0108 
0109         Q_EMIT sleepInhibitedChanged();
0110     }
0111     aWatcher->deleteLater();
0112 #endif
0113 }
0114 
0115 void PowerManagementInterface::uninhibitDBusCallFinishedPlasmaWorkspace(QDBusPendingCallWatcher *aWatcher)
0116 {
0117 #if QtDBus_FOUND
0118     QDBusPendingReply<> reply = *aWatcher;
0119     if (reply.isError()) {
0120         qCDebug(orgKdeElisaPowerManagement()) << "PowerManagementInterface::uninhibitDBusCallFinished" << reply.error();
0121     } else {
0122         d->mInhibitedSleep = false;
0123 
0124         Q_EMIT sleepInhibitedChanged();
0125     }
0126     aWatcher->deleteLater();
0127 #endif
0128 }
0129 
0130 void PowerManagementInterface::inhibitDBusCallFinishedGnomeWorkspace(QDBusPendingCallWatcher *aWatcher)
0131 {
0132 #if QtDBus_FOUND
0133     QDBusPendingReply<uint> reply = *aWatcher;
0134     if (reply.isError()) {
0135         qCDebug(orgKdeElisaPowerManagement()) << "PowerManagementInterface::inhibitDBusCallFinishedGnomeWorkspace" << reply.error();
0136     } else {
0137         d->mInhibitSleepCookie = reply.argumentAt<0>();
0138         d->mInhibitedSleep = true;
0139 
0140         Q_EMIT sleepInhibitedChanged();
0141     }
0142     aWatcher->deleteLater();
0143 #endif
0144 }
0145 
0146 void PowerManagementInterface::uninhibitDBusCallFinishedGnomeWorkspace(QDBusPendingCallWatcher *aWatcher)
0147 {
0148 #if QtDBus_FOUND
0149     QDBusPendingReply<> reply = *aWatcher;
0150     if (reply.isError()) {
0151         qCDebug(orgKdeElisaPowerManagement()) << "PowerManagementInterface::uninhibitDBusCallFinished" << reply.error();
0152     } else {
0153         d->mInhibitedSleep = false;
0154 
0155         Q_EMIT sleepInhibitedChanged();
0156     }
0157     aWatcher->deleteLater();
0158 #endif
0159 }
0160 
0161 void PowerManagementInterface::inhibitSleepPlasmaWorkspace()
0162 {
0163 #if QtDBus_FOUND
0164     auto sessionBus = QDBusConnection::sessionBus();
0165 
0166     auto inhibitCall = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.PowerManagement.Inhibit"),
0167                                                       QStringLiteral("/org/freedesktop/PowerManagement/Inhibit"),
0168                                                       QStringLiteral("org.freedesktop.PowerManagement.Inhibit"),
0169                                                       QStringLiteral("Inhibit"));
0170 
0171     inhibitCall.setArguments({{QGuiApplication::desktopFileName()}, {i18nc("@info:status  explanation for sleep inhibit during play of music", "Playing music")}});
0172 
0173     auto asyncReply = sessionBus.asyncCall(inhibitCall);
0174 
0175     auto replyWatcher = new QDBusPendingCallWatcher(asyncReply, this);
0176 
0177     QObject::connect(replyWatcher, &QDBusPendingCallWatcher::finished,
0178                      this, &PowerManagementInterface::inhibitDBusCallFinishedPlasmaWorkspace);
0179 #endif
0180 }
0181 
0182 void PowerManagementInterface::uninhibitSleepPlasmaWorkspace()
0183 {
0184 #if QtDBus_FOUND
0185     auto sessionBus = QDBusConnection::sessionBus();
0186 
0187     auto uninhibitCall = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.PowerManagement.Inhibit"),
0188                                                       QStringLiteral("/org/freedesktop/PowerManagement/Inhibit"),
0189                                                       QStringLiteral("org.freedesktop.PowerManagement.Inhibit"),
0190                                                       QStringLiteral("UnInhibit"));
0191 
0192     uninhibitCall.setArguments({{d->mInhibitSleepCookie}});
0193 
0194     auto asyncReply = sessionBus.asyncCall(uninhibitCall);
0195 
0196     auto replyWatcher = new QDBusPendingCallWatcher(asyncReply, this);
0197 
0198     QObject::connect(replyWatcher, &QDBusPendingCallWatcher::finished,
0199                      this, &PowerManagementInterface::uninhibitDBusCallFinishedPlasmaWorkspace);
0200 #endif
0201 }
0202 
0203 void PowerManagementInterface::inhibitSleepGnomeWorkspace()
0204 {
0205 #if QtDBus_FOUND
0206     auto sessionBus = QDBusConnection::sessionBus();
0207 
0208     auto inhibitCall = QDBusMessage::createMethodCall(QStringLiteral("org.gnome.SessionManager"),
0209                                                       QStringLiteral("/org/gnome/SessionManager"),
0210                                                       QStringLiteral("org.gnome.SessionManager"),
0211                                                       QStringLiteral("Inhibit"));
0212 
0213     // See: https://gitlab.gnome.org/GNOME/gnome-session/-/blob/master/gnome-session/org.gnome.SessionManager.xml
0214     // The last argument are flag settings to specify what should be inhibited:
0215     //    1  = Inhibit logging out
0216     //    2  = Inhibit user switching
0217     //    4  = Inhibit suspending the session or computer
0218     //    8  = Inhibit the session being marked as idle
0219     //    16 = Inhibit auto-mounting removable media for the session
0220     inhibitCall.setArguments({{QCoreApplication::applicationName()}, {uint(0)},
0221                               {i18nc("@info:status explanation for sleep inhibit during play of music", "Playing music")}, {uint(12)}});
0222 
0223     auto asyncReply = sessionBus.asyncCall(inhibitCall);
0224 
0225     auto replyWatcher = new QDBusPendingCallWatcher(asyncReply, this);
0226 
0227     QObject::connect(replyWatcher, &QDBusPendingCallWatcher::finished,
0228                      this, &PowerManagementInterface::inhibitDBusCallFinishedGnomeWorkspace);
0229 #endif
0230 }
0231 
0232 void PowerManagementInterface::uninhibitSleepGnomeWorkspace()
0233 {
0234 #if QtDBus_FOUND
0235     auto sessionBus = QDBusConnection::sessionBus();
0236 
0237     auto uninhibitCall = QDBusMessage::createMethodCall(QStringLiteral("org.gnome.SessionManager"),
0238                                                         QStringLiteral("/org/gnome/SessionManager"),
0239                                                         QStringLiteral("org.gnome.SessionManager"),
0240                                                         QStringLiteral("UnInhibit"));
0241 
0242     uninhibitCall.setArguments({{d->mInhibitSleepCookie}});
0243 
0244     auto asyncReply = sessionBus.asyncCall(uninhibitCall);
0245 
0246     auto replyWatcher = new QDBusPendingCallWatcher(asyncReply, this);
0247 
0248     QObject::connect(replyWatcher, &QDBusPendingCallWatcher::finished,
0249                      this, &PowerManagementInterface::uninhibitDBusCallFinishedGnomeWorkspace);
0250 #endif
0251 }
0252 
0253 void PowerManagementInterface::inhibitSleepWindowsWorkspace()
0254 {
0255 #if defined Q_OS_WIN
0256     SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED);
0257 #endif
0258 }
0259 
0260 void PowerManagementInterface::uninhibitSleepWindowsWorkspace()
0261 {
0262 #if defined Q_OS_WIN
0263     SetThreadExecutionState(ES_CONTINUOUS);
0264 #endif
0265 }
0266 
0267 
0268 #include "moc_powermanagementinterface.cpp"