File indexing completed on 2024-04-21 14:56:11
0001 /* 0002 Copyright 2006-2007 Kevin Ottens <ervin@kde.org> 0003 Copyright 2013 Lukas Tinkl <ltinkl@redhat.com> 0004 0005 This library is free software; you can redistribute it and/or 0006 modify it under the terms of the GNU Lesser General Public 0007 License as published by the Free Software Foundation; either 0008 version 2.1 of the License, or (at your option) version 3, or any 0009 later version accepted by the membership of KDE e.V. (or its 0010 successor approved by the membership of KDE e.V.), which shall 0011 act as a proxy defined in Section 6 of version 3 of the license. 0012 0013 This library is distributed in the hope that it will be useful, 0014 but WITHOUT ANY WARRANTY; without even the implied warranty of 0015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0016 Lesser General Public License for more details. 0017 0018 You should have received a copy of the GNU Lesser General Public 0019 License along with this library. If not, see <http://www.gnu.org/licenses/>. 0020 */ 0021 0022 #include "powermanagement.h" 0023 #include "powermanagement_p.h" 0024 0025 #include <QCoreApplication> 0026 0027 Q_GLOBAL_STATIC(Solid::PowerManagementPrivate, globalPowerManager) 0028 0029 Solid::PowerManagementPrivate::PowerManagementPrivate() 0030 : managerIface("org.freedesktop.PowerManagement", 0031 "/org/freedesktop/PowerManagement", 0032 QDBusConnection::sessionBus()), 0033 policyAgentIface("org.kde.Solid.PowerManagement.PolicyAgent", 0034 "/org/kde/Solid/PowerManagement/PolicyAgent", 0035 QDBusConnection::sessionBus()), 0036 inhibitIface("org.freedesktop.PowerManagement.Inhibit", 0037 "/org/freedesktop/PowerManagement/Inhibit", 0038 QDBusConnection::sessionBus()), 0039 serviceWatcher("org.kde.Solid.PowerManagement", 0040 QDBusConnection::sessionBus(), 0041 QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration), 0042 powerSaveStatus(false) 0043 { 0044 serviceWatcher.addWatchedService(QLatin1String("org.freedesktop.PowerManagement")); 0045 0046 connect(&managerIface, SIGNAL(CanSuspendChanged(bool)), 0047 this, SLOT(slotCanSuspendChanged(bool))); 0048 connect(&managerIface, SIGNAL(CanHibernateChanged(bool)), 0049 this, SLOT(slotCanHibernateChanged(bool))); 0050 connect(&managerIface, SIGNAL(CanHybridSuspendChanged(bool)), 0051 this, SLOT(slotCanHybridSuspendChanged(bool))); 0052 connect(&managerIface, SIGNAL(PowerSaveStatusChanged(bool)), 0053 this, SLOT(slotPowerSaveStatusChanged(bool))); 0054 connect(&serviceWatcher, SIGNAL(serviceRegistered(QString)), 0055 this, SLOT(slotServiceRegistered(QString))); 0056 connect(&serviceWatcher, SIGNAL(serviceUnregistered(QString)), 0057 this, SLOT(slotServiceUnregistered(QString))); 0058 0059 // If the service is registered, trigger the connection immediately 0060 if (QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.Solid.PowerManagement")) { 0061 slotServiceRegistered("org.kde.Solid.PowerManagement"); 0062 } 0063 if (QDBusConnection::sessionBus().interface()->isServiceRegistered(QLatin1String("org.freedesktop.PowerManagement"))) { 0064 slotServiceRegistered(QLatin1String("org.freedesktop.PowerManagement")); 0065 } 0066 } 0067 0068 Solid::PowerManagementPrivate::~PowerManagementPrivate() 0069 { 0070 } 0071 0072 Solid::PowerManagement::Notifier::Notifier() 0073 { 0074 } 0075 0076 bool Solid::PowerManagement::appShouldConserveResources() 0077 { 0078 return globalPowerManager->managerIface.GetPowerSaveStatus(); 0079 } 0080 0081 QSet<Solid::PowerManagement::SleepState> Solid::PowerManagement::supportedSleepStates() 0082 { 0083 return globalPowerManager->supportedSleepStates; 0084 } 0085 0086 void Solid::PowerManagement::requestSleep(SleepState state, QObject *receiver, const char *member) 0087 { 0088 Q_UNUSED(receiver) 0089 Q_UNUSED(member) 0090 0091 if (!globalPowerManager->supportedSleepStates.contains(state)) { 0092 return; 0093 } 0094 0095 switch (state) { 0096 case StandbyState: 0097 case SuspendState: 0098 globalPowerManager->managerIface.Suspend(); 0099 break; 0100 case HibernateState: 0101 globalPowerManager->managerIface.Hibernate(); 0102 break; 0103 } 0104 } 0105 0106 int Solid::PowerManagement::beginSuppressingSleep(const QString &reason) 0107 { 0108 QDBusReply<uint> reply; 0109 if (globalPowerManager->policyAgentIface.isValid()) { 0110 reply = globalPowerManager->policyAgentIface.AddInhibition( 0111 (uint)PowerManagementPrivate::InterruptSession, 0112 QCoreApplication::applicationName(), reason); 0113 } else { 0114 // Fallback to the fd.o Inhibit interface 0115 reply = globalPowerManager->inhibitIface.Inhibit(QCoreApplication::applicationName(), reason); 0116 } 0117 0118 if (reply.isValid()) { 0119 return reply; 0120 } else { 0121 return -1; 0122 } 0123 } 0124 0125 bool Solid::PowerManagement::stopSuppressingSleep(int cookie) 0126 { 0127 if (globalPowerManager->policyAgentIface.isValid()) { 0128 return globalPowerManager->policyAgentIface.ReleaseInhibition(cookie).isValid(); 0129 } else { 0130 // Fallback to the fd.o Inhibit interface 0131 return globalPowerManager->inhibitIface.UnInhibit(cookie).isValid(); 0132 } 0133 } 0134 0135 int Solid::PowerManagement::beginSuppressingScreenPowerManagement(const QString &reason) 0136 { 0137 if (globalPowerManager->policyAgentIface.isValid()) { 0138 QDBusReply<uint> reply = globalPowerManager->policyAgentIface.AddInhibition( 0139 (uint)PowerManagementPrivate::ChangeScreenSettings, 0140 QCoreApplication::applicationName(), reason); 0141 0142 if (reply.isValid()) { 0143 QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.ScreenSaver", "/ScreenSaver", 0144 "org.freedesktop.ScreenSaver", "Inhibit"); 0145 message << QCoreApplication::applicationName(); 0146 message << reason; 0147 0148 QDBusPendingReply<uint> ssReply = QDBusConnection::sessionBus().asyncCall(message); 0149 ssReply.waitForFinished(); 0150 if (ssReply.isValid()) { 0151 globalPowerManager->screensaverCookiesForPowerDevilCookies.insert(reply, ssReply.value()); 0152 } 0153 0154 return reply; 0155 } else { 0156 return -1; 0157 } 0158 } else { 0159 // No way to fallback on something, hence return failure 0160 return -1; 0161 } 0162 } 0163 0164 bool Solid::PowerManagement::stopSuppressingScreenPowerManagement(int cookie) 0165 { 0166 if (globalPowerManager->policyAgentIface.isValid()) { 0167 bool result = globalPowerManager->policyAgentIface.ReleaseInhibition(cookie).isValid(); 0168 0169 if (globalPowerManager->screensaverCookiesForPowerDevilCookies.contains(cookie)) { 0170 QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.ScreenSaver", "/ScreenSaver", 0171 "org.freedesktop.ScreenSaver", "UnInhibit"); 0172 message << globalPowerManager->screensaverCookiesForPowerDevilCookies.take(cookie); 0173 QDBusConnection::sessionBus().asyncCall(message); 0174 } 0175 0176 return result; 0177 } else { 0178 // No way to fallback on something, hence return failure 0179 return false; 0180 } 0181 } 0182 0183 Solid::PowerManagement::Notifier *Solid::PowerManagement::notifier() 0184 { 0185 return globalPowerManager; 0186 } 0187 0188 void Solid::PowerManagementPrivate::slotCanSuspendChanged(bool newState) 0189 { 0190 if (supportedSleepStates.contains(Solid::PowerManagement::SuspendState) == newState) { 0191 return; 0192 } 0193 0194 if (newState) { 0195 supportedSleepStates += Solid::PowerManagement::SuspendState; 0196 } else { 0197 supportedSleepStates -= Solid::PowerManagement::SuspendState; 0198 } 0199 } 0200 0201 void Solid::PowerManagementPrivate::slotCanHibernateChanged(bool newState) 0202 { 0203 if (supportedSleepStates.contains(Solid::PowerManagement::HibernateState) == newState) { 0204 return; 0205 } 0206 0207 if (newState) { 0208 supportedSleepStates += Solid::PowerManagement::HibernateState; 0209 } else { 0210 supportedSleepStates -= Solid::PowerManagement::HibernateState; 0211 } 0212 } 0213 0214 void Solid::PowerManagementPrivate::slotCanHybridSuspendChanged(bool newState) 0215 { 0216 if (supportedSleepStates.contains(Solid::PowerManagement::HybridSuspendState) == newState) { 0217 return; 0218 } 0219 0220 if (newState) { 0221 supportedSleepStates += Solid::PowerManagement::HybridSuspendState; 0222 } else { 0223 supportedSleepStates -= Solid::PowerManagement::HybridSuspendState; 0224 } 0225 } 0226 0227 void Solid::PowerManagementPrivate::slotPowerSaveStatusChanged(bool newState) 0228 { 0229 if (powerSaveStatus == newState) { 0230 return; 0231 } 0232 0233 powerSaveStatus = newState; 0234 emit appShouldConserveResourcesChanged(powerSaveStatus); 0235 } 0236 0237 void Solid::PowerManagementPrivate::slotServiceRegistered(const QString &serviceName) 0238 { 0239 if (serviceName == QLatin1String("org.freedesktop.PowerManagement")) { 0240 // Load all the properties 0241 QDBusPendingReply<bool> suspendReply = managerIface.CanSuspend(); 0242 suspendReply.waitForFinished(); 0243 slotCanSuspendChanged(suspendReply.isValid() ? suspendReply.value() : false); 0244 0245 QDBusPendingReply<bool> hibernateReply = managerIface.CanHibernate(); 0246 hibernateReply.waitForFinished(); 0247 slotCanHibernateChanged(hibernateReply.isValid() ? hibernateReply.value() : false); 0248 0249 QDBusPendingReply<bool> hybridSuspendReply = managerIface.CanHybridSuspend(); 0250 hybridSuspendReply.waitForFinished(); 0251 slotCanHybridSuspendChanged(hybridSuspendReply.isValid() ? hybridSuspendReply.value() : false); 0252 0253 QDBusPendingReply<bool> saveStatusReply = managerIface.GetPowerSaveStatus(); 0254 saveStatusReply.waitForFinished(); 0255 slotPowerSaveStatusChanged(saveStatusReply.isValid() ? saveStatusReply.value() : false); 0256 } else { 0257 // Is the resume signal available? 0258 QDBusMessage call = QDBusMessage::createMethodCall("org.kde.Solid.PowerManagement", 0259 "/org/kde/Solid/PowerManagement", 0260 "org.kde.Solid.PowerManagement", 0261 "backendCapabilities"); 0262 QDBusPendingReply< uint > reply = QDBusConnection::sessionBus().asyncCall(call); 0263 reply.waitForFinished(); 0264 0265 if (reply.isValid() && reply.value() > 0) { 0266 // Connect the signal 0267 QDBusConnection::sessionBus().connect(QLatin1String("org.kde.Solid.PowerManagement"), 0268 QLatin1String("/org/kde/Solid/PowerManagement/Actions/SuspendSession"), 0269 QLatin1String("org.kde.Solid.PowerManagement.Actions.SuspendSession"), 0270 QLatin1String("resumingFromSuspend"), 0271 this, 0272 SIGNAL(resumingFromSuspend())); 0273 } 0274 } 0275 } 0276 0277 void Solid::PowerManagementPrivate::slotServiceUnregistered(const QString &serviceName) 0278 { 0279 if (serviceName == QLatin1String("org.freedesktop.PowerManagement")) { 0280 // Reset the values 0281 slotCanSuspendChanged(false); 0282 slotCanHibernateChanged(false); 0283 slotCanHybridSuspendChanged(false); 0284 slotPowerSaveStatusChanged(false); 0285 } else { 0286 // Disconnect the signal 0287 QDBusConnection::sessionBus().disconnect(QLatin1String("org.kde.Solid.PowerManagement"), 0288 QLatin1String("/org/kde/Solid/PowerManagement"), 0289 QLatin1String("org.kde.Solid.PowerManagement"), 0290 QLatin1String("resumingFromSuspend"), 0291 this, 0292 SIGNAL(resumingFromSuspend())); 0293 } 0294 } 0295 0296 #include "moc_powermanagement.cpp" 0297 #include "moc_powermanagement_p.cpp"