SVN commit 866447 by dafre: Moving most stuff from PowerManagementConnector to the new SuspensionLockHandler. Result? Now inhibiting suspension works. Application developers, you can now easily prevent the PC from suspending. It's enough to call the method "Inhibit" on org.kde.Solid.PowerManagement.Inhibit, specifying your application name and the reason why you want to inhibit. PowerDevil will take care of the rest, including notifying the user when the system tries to suspend. The method returns an int, that you can use as argument when calling "Uninhibit" on the same interface to get suspension back working. I'm forwarding this to kde-devel since it might interest someone. P.S.: Kevin, I definitely love when a plan comes together too :) -- Dario CCMAIL: ervin@kde.org CCMAIL: kde-devel@kde.org M +4 -6 daemon/PowerDevilDaemon.cpp M +7 -3 daemon/PowerDevilDaemon.h M +10 -20 daemon/PowerManagementConnector.cpp M +2 -9 daemon/PowerManagementConnector.h M +44 -4 daemon/SuspensionLockHandler.cpp M +21 -1 daemon/SuspensionLockHandler.h M +7 -0 powerdevil.notifyrc --- trunk/KDE/kdebase/workspace/powerdevil/daemon/PowerDevilDaemon.cpp #866446:866447 @@ -151,6 +151,10 @@ QDBusConnection::sessionBus(), this); connect(m_notifier, SIGNAL(buttonPressed(int)), this, SLOT(buttonPressed(int))); + connect(m_lockHandler, SIGNAL(streamCriticalNotification(const QString&, const QString&, + const char*, const QString&)), + SLOT(emitCriticalNotification(const QString&, const QString&, + const char*, const QString&))); /* Those slots are relevant only if we're on a system that has a battery. If not, we simply don't care * about them. @@ -648,14 +652,8 @@ void PowerDevilDaemon::shutdownDialog() { - if (!m_lockHandler->setJobLock()) { - return; - } - m_ksmServerIface->logout((int)KWorkSpace::ShutdownConfirmYes, (int)KWorkSpace::ShutdownTypeNone, (int)KWorkSpace::ShutdownModeDefault); - - m_lockHandler->releaseAllLocks(); } void PowerDevilDaemon::suspendToDisk() --- trunk/KDE/kdebase/workspace/powerdevil/daemon/PowerDevilDaemon.h #866446:866447 @@ -70,6 +70,10 @@ QVariantMap getSupportedSuspendMethods(); QVariantMap getSupportedPollingSystems(); + SuspensionLockHandler *lockHandler() { + return m_lockHandler; + }; + private Q_SLOTS: void acAdapterStateChanged(int state, bool forced = false); void batteryChargePercentChanged(int percent, const QString &udi); @@ -110,6 +114,9 @@ void setUpDPMS(); + void emitCriticalNotification(const QString &evid, const QString &message = QString(), + const char *slot = 0, const QString &iconname = "dialog-error"); + Q_SIGNALS: void lidClosed(int code, const QString &action); void errorTriggered(const QString &error); @@ -125,9 +132,6 @@ void setUpNextTimeout(int idle, int minDimEvent); - void emitCriticalNotification(const QString &evid, const QString &message = QString(), - const char *slot = 0, const QString &iconname = "dialog-error"); - void profileFirstLoad(); void restoreDefaultProfiles(); --- trunk/KDE/kdebase/workspace/powerdevil/daemon/PowerManagementConnector.cpp #866446:866447 @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright (C) 2008 by Kevin Ottens * + * Copyright (C) 2008 by Dario Freddi * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -19,13 +20,15 @@ #include "PowerManagementConnector.h" +#include "SuspensionLockHandler.h" + #include #include "powermanagementadaptor.h" #include "powermanagementinhibitadaptor.h" PowerManagementConnector::PowerManagementConnector(PowerDevilDaemon *parent) - : QObject(parent), m_daemon(parent), m_latestInhibitCookie(0) + : QObject(parent), m_daemon(parent) { new PowerManagementAdaptor(this); new PowerManagementInhibitAdaptor(this); @@ -65,45 +68,32 @@ void PowerManagementConnector::Suspend() { - if (!HasInhibit()) { - m_daemon->suspend(PowerDevilDaemon::S2Ram); - } - //TODO: Notify the user in case of inhibit? + m_daemon->suspend(PowerDevilDaemon::S2Ram); } void PowerManagementConnector::Hibernate() { - if (!HasInhibit()) { - m_daemon->suspend(PowerDevilDaemon::S2Disk); - } - //TODO: Notify the user in case of inhibit? + m_daemon->suspend(PowerDevilDaemon::S2Disk); } bool PowerManagementConnector::HasInhibit() { - return !m_inhibitRequests.isEmpty(); + return m_daemon->lockHandler()->hasInhibit(); } int PowerManagementConnector::Inhibit(const QString &application, const QString &reason) { - m_latestInhibitCookie++; - - InhibitRequest req; - //TODO: Keep track of the service name too, to cleanup cookie in case of a crash. - req.application = application; - req.reason = reason; - m_inhibitRequests[m_latestInhibitCookie] = req; - - return m_latestInhibitCookie; + return m_daemon->lockHandler()->inhibit(application, reason); } void PowerManagementConnector::UnInhibit(int cookie) { - m_inhibitRequests.remove(cookie); + return m_daemon->lockHandler()->releaseInhibiton(cookie); } void PowerManagementConnector::_k_stateChanged(int battery, bool plugged) { + Q_UNUSED(battery) emit PowerSaveStatusChanged(!plugged); } --- trunk/KDE/kdebase/workspace/powerdevil/daemon/PowerManagementConnector.h #866446:866447 @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright (C) 2008 by Kevin Ottens * + * Copyright (C) 2008 by Dario Freddi * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -28,13 +29,6 @@ #include "PowerDevilDaemon.h" -class InhibitRequest -{ -public: - QString application; - QString reason; -}; - class PowerManagementConnector : public QObject { Q_OBJECT @@ -68,8 +62,7 @@ private: PowerDevilDaemon *m_daemon; - int m_latestInhibitCookie; - QMap m_inhibitRequests; + }; #endif /*POWERMANAGEMENTCONNECTOR_H*/ --- trunk/KDE/kdebase/workspace/powerdevil/daemon/SuspensionLockHandler.cpp #866446:866447 @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright (C) 2008 by Dario Freddi * + * Copyright (C) 2008 by Kevin Ottens * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -20,11 +21,13 @@ #include "SuspensionLockHandler.h" #include +#include SuspensionLockHandler::SuspensionLockHandler(QObject *parent) : QObject(parent), m_isJobOngoing(false), - m_isOnNotification(false) + m_isOnNotification(false), + m_latestInhibitCookie(0) { } @@ -34,11 +37,19 @@ bool SuspensionLockHandler::canStartSuspension() { + if (hasInhibit()) { + return false; + } + return !m_isJobOngoing; } bool SuspensionLockHandler::canStartNotification() { + if (hasInhibit()) { + return false; + } + if (!m_isJobOngoing && !m_isOnNotification) { return true; } else { @@ -46,6 +57,22 @@ } } +bool SuspensionLockHandler::hasInhibit() +{ + if (m_inhibitRequests.isEmpty()) { + return false; + } else { + kDebug() << "Inhibition detected!!"; + // TODO: uhm... maybe a better notification here? + emit streamCriticalNotification("inhibition", i18n("The application %1 " + "is inhibiting suspension for the following reason:\n%2", + m_inhibitRequests[m_latestInhibitCookie].application, + m_inhibitRequests[m_latestInhibitCookie].reason), + 0, "dialog-cancel"); + return true; + } +} + bool SuspensionLockHandler::setNotificationLock() { if (!canStartNotification()) { @@ -70,6 +97,19 @@ return true; } +int SuspensionLockHandler::inhibit(const QString &application, const QString &reason) +{ + m_latestInhibitCookie++; + + InhibitRequest req; + //TODO: Keep track of the service name too, to cleanup cookie in case of a crash. + req.application = application; + req.reason = reason; + m_inhibitRequests[m_latestInhibitCookie] = req; + + return m_latestInhibitCookie; +} + void SuspensionLockHandler::releaseNotificationLock() { kDebug() << "Releasing notification lock"; @@ -85,12 +125,12 @@ void SuspensionLockHandler::releaseAllInhibitions() { - + m_inhibitRequests.clear(); } -void SuspensionLockHandler::releaseInhibiton(const QString &id) +void SuspensionLockHandler::releaseInhibiton(int cookie) { - + m_inhibitRequests.remove(cookie); } #include "SuspensionLockHandler.moc" --- trunk/KDE/kdebase/workspace/powerdevil/daemon/SuspensionLockHandler.h #866446:866447 @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright (C) 2008 by Dario Freddi * + * Copyright (C) 2008 by Kevin Ottens * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -21,7 +22,15 @@ #define SUSPENSIONLOCKHANDLER_H #include +#include +class InhibitRequest +{ +public: + QString application; + QString reason; +}; + class SuspensionLockHandler : public QObject { Q_OBJECT @@ -34,17 +43,28 @@ bool canStartSuspension(); bool canStartNotification(); + bool hasInhibit(); + bool setNotificationLock(); bool setJobLock(); + int inhibit(const QString &application, const QString &reason); + void releaseAllLocks(); void releaseNotificationLock(); void releaseAllInhibitions(); - void releaseInhibiton(const QString &id = QString()); + void releaseInhibiton(int cookie); +signals: + void streamCriticalNotification(const QString &evid, const QString &message, + const char *slot, const QString &iconname); + private: bool m_isJobOngoing; bool m_isOnNotification; + + int m_latestInhibitCookie; + QMap m_inhibitRequests; }; #endif /* SUSPENSIONLOCKHANDLER_H */ --- trunk/KDE/kdebase/workspace/powerdevil/powerdevil.notifyrc #866446:866447 @@ -478,3 +478,10 @@ Contexts=criticalnot Sound=KDE-Sys-App-Error-Critical.ogg Action=Sound|Popup + +[Event/inhibition] +Name=Suspension inhibited +Comment=The suspension has been inhibited because an application requested it +Contexts=criticalnot +Sound=KDE-Sys-App-Error-Critical.ogg +Action=Sound|Popup