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"