File indexing completed on 2025-01-05 04:29:51
0001 /** 0002 * SPDX-FileCopyrightText: 2019 Matthieu Gallien <matthieu_gallien@yahoo.fr> 0003 * SPDX-FileCopyrightText: 2021-2023 Bart De Vries <bart@mogwai.be> 0004 * 0005 * SPDX-License-Identifier: LGPL-3.0-or-later 0006 */ 0007 0008 #include "powermanagementinterface.h" 0009 #include "powermanagementinterfacelogging.h" 0010 0011 #include <KLocalizedString> 0012 0013 #if !defined Q_OS_ANDROID && !defined Q_OS_WIN 0014 #include <QDBusConnection> 0015 #include <QDBusPendingCallWatcher> 0016 #include <QDBusPendingReply> 0017 #endif 0018 0019 #if defined Q_OS_WIN 0020 #include <windows.h> 0021 #endif 0022 0023 #include <QCoreApplication> 0024 #include <QDebug> 0025 #include <QString> 0026 0027 #if !defined Q_OS_ANDROID && !defined Q_OS_WIN 0028 #include "gnomesessioninterface.h" 0029 #include "inhibitinterface.h" 0030 #endif 0031 0032 class PowerManagementInterfacePrivate 0033 { 0034 public: 0035 bool mPreventSleep = false; 0036 0037 bool mInhibitedSleep = false; 0038 0039 uint mInhibitSleepCookie = 0; 0040 0041 uint mGnomeSleepCookie = 0; 0042 0043 #if !defined Q_OS_ANDROID && !defined Q_OS_WIN 0044 OrgFreedesktopPowerManagementInhibitInterface *mInhibitInterface; 0045 OrgGnomeSessionManagerInterface *mGnomeInterface; 0046 #endif 0047 }; 0048 0049 PowerManagementInterface::PowerManagementInterface(QObject *parent) 0050 : QObject(parent) 0051 , d(std::make_unique<PowerManagementInterfacePrivate>()) 0052 { 0053 #if !defined Q_OS_ANDROID && !defined Q_OS_WIN 0054 d->mInhibitInterface = new OrgFreedesktopPowerManagementInhibitInterface(QStringLiteral("org.freedesktop.PowerManagement.Inhibit"), 0055 QStringLiteral("/org/freedesktop/PowerManagement/Inhibit"), 0056 QDBusConnection::sessionBus(), 0057 this); 0058 0059 d->mGnomeInterface = new OrgGnomeSessionManagerInterface(QStringLiteral("org.gnome.SessionManager"), 0060 QStringLiteral("/org/gnome/SessionManager"), 0061 QDBusConnection::sessionBus(), 0062 this); 0063 #endif 0064 } 0065 0066 PowerManagementInterface::~PowerManagementInterface() 0067 { 0068 #if !defined Q_OS_ANDROID && !defined Q_OS_WIN 0069 delete d->mInhibitInterface; 0070 delete d->mGnomeInterface; 0071 #endif 0072 } 0073 0074 bool PowerManagementInterface::preventSleep() const 0075 { 0076 return d->mPreventSleep; 0077 } 0078 0079 bool PowerManagementInterface::sleepInhibited() const 0080 { 0081 return d->mInhibitedSleep; 0082 } 0083 0084 void PowerManagementInterface::setPreventSleep(bool value) 0085 { 0086 if (d->mPreventSleep == value) { 0087 return; 0088 } 0089 0090 if (value) { 0091 inhibitSleepPlasmaWorkspace(); 0092 inhibitSleepGnomeWorkspace(); 0093 d->mPreventSleep = true; 0094 } else { 0095 uninhibitSleepPlasmaWorkspace(); 0096 uninhibitSleepGnomeWorkspace(); 0097 d->mPreventSleep = false; 0098 } 0099 0100 Q_EMIT preventSleepChanged(); 0101 } 0102 0103 void PowerManagementInterface::retryInhibitingSleep() 0104 { 0105 if (d->mPreventSleep && !d->mInhibitedSleep) { 0106 inhibitSleepPlasmaWorkspace(); 0107 inhibitSleepGnomeWorkspace(); 0108 } 0109 } 0110 0111 void PowerManagementInterface::hostSleepInhibitChanged() 0112 { 0113 } 0114 0115 void PowerManagementInterface::inhibitDBusCallFinishedPlasmaWorkspace(QDBusPendingCallWatcher *aWatcher) 0116 { 0117 #if !defined Q_OS_ANDROID && !defined Q_OS_WIN 0118 QDBusPendingReply<uint> reply = *aWatcher; 0119 if (reply.isError()) { 0120 } else { 0121 d->mInhibitSleepCookie = reply.argumentAt<0>(); 0122 d->mInhibitedSleep = true; 0123 0124 Q_EMIT sleepInhibitedChanged(); 0125 } 0126 aWatcher->deleteLater(); 0127 #else 0128 Q_UNUSED(aWatcher) 0129 #endif 0130 } 0131 0132 void PowerManagementInterface::uninhibitDBusCallFinishedPlasmaWorkspace(QDBusPendingCallWatcher *aWatcher) 0133 { 0134 #if !defined Q_OS_ANDROID && !defined Q_OS_WIN 0135 QDBusPendingReply<> reply = *aWatcher; 0136 if (reply.isError()) { 0137 qCDebug(KMediaSessionPowerManagementInterface) << "PowerManagementInterface::uninhibitDBusCallFinished" << reply.error(); 0138 } else { 0139 d->mInhibitedSleep = false; 0140 0141 Q_EMIT sleepInhibitedChanged(); 0142 } 0143 aWatcher->deleteLater(); 0144 #else 0145 Q_UNUSED(aWatcher) 0146 #endif 0147 } 0148 0149 void PowerManagementInterface::inhibitDBusCallFinishedGnomeWorkspace(QDBusPendingCallWatcher *aWatcher) 0150 { 0151 #if !defined Q_OS_ANDROID && !defined Q_OS_WIN 0152 QDBusPendingReply<uint> reply = *aWatcher; 0153 if (reply.isError()) { 0154 qCDebug(KMediaSessionPowerManagementInterface) << "PowerManagementInterface::inhibitDBusCallFinishedGnomeWorkspace" << reply.error(); 0155 } else { 0156 d->mGnomeSleepCookie = reply.argumentAt<0>(); 0157 d->mInhibitedSleep = true; 0158 0159 Q_EMIT sleepInhibitedChanged(); 0160 } 0161 aWatcher->deleteLater(); 0162 #else 0163 Q_UNUSED(aWatcher) 0164 #endif 0165 } 0166 0167 void PowerManagementInterface::uninhibitDBusCallFinishedGnomeWorkspace(QDBusPendingCallWatcher *aWatcher) 0168 { 0169 #if !defined Q_OS_ANDROID && !defined Q_OS_WIN 0170 QDBusPendingReply<> reply = *aWatcher; 0171 if (reply.isError()) { 0172 qCDebug(KMediaSessionPowerManagementInterface) << "PowerManagementInterface::uninhibitDBusCallFinished" << reply.error(); 0173 } else { 0174 d->mInhibitedSleep = false; 0175 0176 Q_EMIT sleepInhibitedChanged(); 0177 } 0178 aWatcher->deleteLater(); 0179 #else 0180 Q_UNUSED(aWatcher) 0181 #endif 0182 } 0183 0184 void PowerManagementInterface::inhibitSleepPlasmaWorkspace() 0185 { 0186 #if !defined Q_OS_ANDROID && !defined Q_OS_WIN 0187 auto asyncReply = 0188 d->mInhibitInterface->Inhibit(QCoreApplication::applicationName(), i18nc("Explanation for sleep inhibit during media playback", "Playing Media")); 0189 0190 auto replyWatcher = new QDBusPendingCallWatcher(asyncReply, this); 0191 0192 QObject::connect(replyWatcher, &QDBusPendingCallWatcher::finished, this, &PowerManagementInterface::inhibitDBusCallFinishedPlasmaWorkspace); 0193 #endif 0194 } 0195 0196 void PowerManagementInterface::uninhibitSleepPlasmaWorkspace() 0197 { 0198 #if !defined Q_OS_ANDROID && !defined Q_OS_WIN 0199 auto asyncReply = d->mInhibitInterface->UnInhibit(d->mInhibitSleepCookie); 0200 0201 auto replyWatcher = new QDBusPendingCallWatcher(asyncReply, this); 0202 0203 QObject::connect(replyWatcher, &QDBusPendingCallWatcher::finished, this, &PowerManagementInterface::uninhibitDBusCallFinishedPlasmaWorkspace); 0204 #endif 0205 } 0206 0207 void PowerManagementInterface::inhibitSleepGnomeWorkspace() 0208 { 0209 #if !defined Q_OS_ANDROID && !defined Q_OS_WIN 0210 // flags are: 4 = "Inhibit suspending the session or computer" 0211 // 8 = "Inhibit the session being marked as idle" 0212 auto asyncReply = d->mGnomeInterface->Inhibit(QCoreApplication::applicationName(), 0213 uint(0), 0214 i18nc("Explanation for sleep inhibit during media playback", "Playing Media"), 0215 uint(12)); 0216 0217 auto replyWatcher = new QDBusPendingCallWatcher(asyncReply, this); 0218 0219 QObject::connect(replyWatcher, &QDBusPendingCallWatcher::finished, this, &PowerManagementInterface::inhibitDBusCallFinishedGnomeWorkspace); 0220 #endif 0221 } 0222 0223 void PowerManagementInterface::uninhibitSleepGnomeWorkspace() 0224 { 0225 #if !defined Q_OS_ANDROID && !defined Q_OS_WIN 0226 auto asyncReply = d->mGnomeInterface->Uninhibit(d->mGnomeSleepCookie); 0227 0228 auto replyWatcher = new QDBusPendingCallWatcher(asyncReply, this); 0229 0230 QObject::connect(replyWatcher, &QDBusPendingCallWatcher::finished, this, &PowerManagementInterface::uninhibitDBusCallFinishedGnomeWorkspace); 0231 #endif 0232 } 0233 0234 void PowerManagementInterface::inhibitSleepWindowsWorkspace() 0235 { 0236 #if defined Q_OS_WIN 0237 SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED); 0238 #endif 0239 } 0240 0241 void PowerManagementInterface::uninhibitSleepWindowsWorkspace() 0242 { 0243 #if defined Q_OS_WIN 0244 SetThreadExecutionState(ES_CONTINUOUS); 0245 #endif 0246 }