OSDN Git Service

powerdevil: implement ConsoleKit support
authorIvailo Monev <xakepa10@gmail.com>
Mon, 5 Jul 2021 21:07:57 +0000 (21:07 +0000)
committerIvailo Monev <xakepa10@gmail.com>
Mon, 5 Jul 2021 21:08:01 +0000 (21:08 +0000)
fixes suspend/sleep on FreeBSD

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
powerdevil/daemon/BackendConfig.cmake
powerdevil/daemon/backends/upower/consolekitsuspendjob.cpp [new file with mode: 0644]
powerdevil/daemon/backends/upower/consolekitsuspendjob.h [new file with mode: 0644]
powerdevil/daemon/backends/upower/powerdevilupowerbackend.cpp
powerdevil/daemon/backends/upower/powerdevilupowerbackend.h

index 7d27223..d1d24fb 100644 (file)
@@ -16,6 +16,7 @@ endif()
 set(powerdevilupowerbackend_SRCS
     backends/upower/upowersuspendjob.cpp
     backends/upower/login1suspendjob.cpp
+    backends/upower/consolekitsuspendjob.cpp
     backends/upower/powerdevilupowerbackend.cpp
     backends/upower/xrandrbrightness.cpp
     backends/upower/xrandrx11helper.cpp
diff --git a/powerdevil/daemon/backends/upower/consolekitsuspendjob.cpp b/powerdevil/daemon/backends/upower/consolekitsuspendjob.cpp
new file mode 100644 (file)
index 0000000..9d1f18e
--- /dev/null
@@ -0,0 +1,105 @@
+/*  This file is part of the KDE project
+    Copyright (C) 2021 Ivailo Monev <xakepa10@gmail.com>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License version 2 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+
+*/
+
+#include "consolekitsuspendjob.h"
+
+#include <QtDBus/QDBusMessage>
+#include <QtDBus/QDBusReply>
+#include <QTimer>
+#include <KDebug>
+#include <KLocale>
+
+ConsoleKitSuspendJob::ConsoleKitSuspendJob(QDBusInterface *consolekitInterface,
+                                   PowerDevil::BackendInterface::SuspendMethod method,
+                                   PowerDevil::BackendInterface::SuspendMethods supported)
+    : KJob(), m_consolekitInterface(consolekitInterface)
+{
+    kDebug() << "Starting ConsoleKit suspend job";
+    m_method = method;
+    m_supported = supported;
+
+    connect(m_consolekitInterface, SIGNAL(PrepareForSleep(bool)), this, SLOT(slotConsoleKitResuming(bool)));
+}
+
+ConsoleKitSuspendJob::~ConsoleKitSuspendJob()
+{
+
+}
+
+void ConsoleKitSuspendJob::start()
+{
+    QTimer::singleShot(0, this, SLOT(doStart()));
+}
+
+void ConsoleKitSuspendJob::kill(bool /*quietly */)
+{
+
+}
+
+void ConsoleKitSuspendJob::doStart()
+{
+    if (m_supported & m_method)
+    {
+        QVariantList args;
+        args << true; // interactive, ie. with polkit dialogs
+
+        QDBusPendingReply<void> reply;
+        QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this);
+        connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(sendResult(QDBusPendingCallWatcher*)));
+
+        switch(m_method)
+        {
+        case PowerDevil::BackendInterface::ToRam:
+            reply = m_consolekitInterface->asyncCallWithArgumentList("Suspend", args);
+            break;
+        case PowerDevil::BackendInterface::ToDisk:
+            reply = m_consolekitInterface->asyncCallWithArgumentList("Hibernate", args);
+            break;
+        case PowerDevil::BackendInterface::HybridSuspend:
+            reply = m_consolekitInterface->asyncCallWithArgumentList("HybridSleep", args);
+            break;
+        default:
+            kDebug() << "Unsupported suspend method";
+            setError(1);
+            setErrorText(i18n("Unsupported suspend method"));
+            break;
+        }
+    }
+}
+
+void ConsoleKitSuspendJob::sendResult(QDBusPendingCallWatcher *watcher)
+{
+    const QDBusPendingReply<void> reply = *watcher;
+    if (!reply.isError()) {
+        emitResult();
+    } else {
+        kWarning() << "Failed to start suspend job" << reply.error().name() << reply.error().message();
+    }
+
+    watcher->deleteLater();
+}
+
+void ConsoleKitSuspendJob::slotConsoleKitResuming(bool active)
+{
+    if (!active)
+        emitResult();
+}
+
+
+#include "moc_consolekitsuspendjob.cpp"
diff --git a/powerdevil/daemon/backends/upower/consolekitsuspendjob.h b/powerdevil/daemon/backends/upower/consolekitsuspendjob.h
new file mode 100644 (file)
index 0000000..f8daaae
--- /dev/null
@@ -0,0 +1,53 @@
+/*  This file is part of the KDE project
+    Copyright (C) 2021 Ivailo Monev <xakepa10@gmail.com>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License version 2 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef CONSOLEKITSUSPENDJOB_H
+#define CONSOLEKITSUSPENDJOB_H
+
+#include <kjob.h>
+#include <QtDBus/QDBusInterface>
+#include <QtDBus/QDBusMessage>
+#include <QtDBus/qdbuspendingcall.h>
+
+#include "powerdevilbackendinterface.h"
+
+class ConsoleKitSuspendJob : public KJob
+{
+    Q_OBJECT
+public:
+    ConsoleKitSuspendJob(QDBusInterface *consolekitInterface,
+                     PowerDevil::BackendInterface::SuspendMethod method,
+                     PowerDevil::BackendInterface::SuspendMethods supported);
+    virtual ~ConsoleKitSuspendJob();
+
+    void start();
+    void kill(bool quietly);
+
+private Q_SLOTS:
+    void doStart();
+    void sendResult(QDBusPendingCallWatcher* watcher);
+    void slotConsoleKitResuming(bool active);
+
+private:
+    QDBusInterface *m_consolekitInterface;
+    PowerDevil::BackendInterface::SuspendMethod m_method;
+    PowerDevil::BackendInterface::SuspendMethods m_supported;
+};
+
+#endif //CONSOLEKITSUSPENDJOB_H
index 6449145..c570593 100644 (file)
@@ -36,6 +36,7 @@
 #include "xrandrbrightness.h"
 #include "upowersuspendjob.h"
 #include "login1suspendjob.h"
+#include "consolekitsuspendjob.h"
 
 #ifdef HAVE_XF86VMODE
 #include "xf86vmodegamma.h"
@@ -80,79 +81,47 @@ PowerDevilUPowerBackend::~PowerDevilUPowerBackend()
 
 bool PowerDevilUPowerBackend::isAvailable()
 {
-    if (!QDBusConnection::systemBus().interface()->isServiceRegistered(UPOWER_SERVICE)) {
-        // Is it pending activation?
-        kDebug() << "UPower service, " << UPOWER_SERVICE << ", is not registered on the bus. Trying to find out if it is activated.";
-        QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.DBus",
-                                                              "/org/freedesktop/DBus",
-                                                              "org.freedesktop.DBus",
-                                                              "ListActivatableNames");
-
-        QDBusPendingReply< QStringList > reply = QDBusConnection::systemBus().asyncCall(message);
-        reply.waitForFinished();
-
-        if (reply.isValid()) {
-            if (reply.value().contains(UPOWER_SERVICE)) {
-                kDebug() << "UPower was found, activating service...";
-                QDBusConnection::systemBus().interface()->startService(UPOWER_SERVICE);
-                if (!QDBusConnection::systemBus().interface()->isServiceRegistered(UPOWER_SERVICE)) {
-                    // Wait for it
-                    QEventLoop e;
-                    QTimer *timer = new QTimer;
-                    timer->setInterval(10000);
-                    timer->setSingleShot(true);
-
-                    connect(QDBusConnection::systemBus().interface(), SIGNAL(serviceRegistered(QString)),
-                            &e, SLOT(quit()));
-                    connect(timer, SIGNAL(timeout()), &e, SLOT(quit()));
-
-                    timer->start();
-
-                    while (!QDBusConnection::systemBus().interface()->isServiceRegistered(UPOWER_SERVICE)) {
-                        e.exec();
-
-                        if (!timer->isActive()) {
-                            kDebug() << "Activation of UPower timed out. There is likely a problem with your configuration.";
-                            timer->deleteLater();
-                            return false;
-                        }
-                    }
-
-                    timer->deleteLater();
-                }
-                return true;
-            } else {
-                kDebug() << "UPower cannot be found on this system.";
-                return false;
-            }
-        } else {
-            kWarning() << "Could not request activatable names to DBus!";
-            return false;
-        }
-    } else {
-        return true;
-    }
-}
-
-void PowerDevilUPowerBackend::init()
-{
-    // interfaces
     if (!QDBusConnection::systemBus().interface()->isServiceRegistered(LOGIN1_SERVICE)) {
-        // Activate it.
+        kDebug() << "activating" << LOGIN1_SERVICE;
         QDBusConnection::systemBus().interface()->startService(LOGIN1_SERVICE);
     }
 
+    if (!QDBusConnection::systemBus().interface()->isServiceRegistered(CONSOLEKIT_SERVICE)) {
+        kDebug() << "activating" << CONSOLEKIT_SERVICE;
+        QDBusConnection::systemBus().interface()->startService(CONSOLEKIT_SERVICE);
+    }
+
     if (!QDBusConnection::systemBus().interface()->isServiceRegistered(UPOWER_SERVICE)) {
-        // Activate it.
+        kDebug() << "activating" << UPOWER_SERVICE;
         QDBusConnection::systemBus().interface()->startService(UPOWER_SERVICE);
     }
 
+    bool isavailable = QDBusConnection::systemBus().interface()->isServiceRegistered(LOGIN1_SERVICE);
+    isavailable |= QDBusConnection::systemBus().interface()->isServiceRegistered(CONSOLEKIT_SERVICE);
+    isavailable |= QDBusConnection::systemBus().interface()->isServiceRegistered(UPOWER_SERVICE);
+
+    if (!isavailable) {
+        kWarning() << "No service for suspending is available on this system.";
+    }
+
+    return isavailable;
+}
+
+void PowerDevilUPowerBackend::init()
+{
+    // interfaces
     if (QDBusConnection::systemBus().interface()->isServiceRegistered(LOGIN1_SERVICE)) {
-        m_login1Interface = new QDBusInterface(LOGIN1_SERVICE, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", QDBusConnection::systemBus(), this);
+        kDebug() << LOGIN1_SERVICE << "available";
+        m_login1Interface = new QDBusInterface(LOGIN1_SERVICE, LOGIN1_PATH, LOGIN1_IFACE, QDBusConnection::systemBus(), this);
+    }
+
+    if (QDBusConnection::systemBus().interface()->isServiceRegistered(CONSOLEKIT_SERVICE)) {
+        kDebug() << CONSOLEKIT_SERVICE << "available";
+        m_consolekitInterface = new QDBusInterface(CONSOLEKIT_SERVICE, CONSOLEKIT_PATH, CONSOLEKIT_IFACE, QDBusConnection::systemBus(), this);
     }
 
     bool screenBrightnessAvailable = false;
-    m_upowerInterface = new OrgFreedesktopUPowerInterface(UPOWER_SERVICE, "/org/freedesktop/UPower", QDBusConnection::systemBus(), this);
+    m_upowerInterface = new OrgFreedesktopUPowerInterface(UPOWER_SERVICE, UPOWER_PATH, QDBusConnection::systemBus(), this);
     m_brightnessControl = new XRandrBrightness();
     if (m_brightnessControl->isSupported()) {
         kDebug() << "Using XRandR";
@@ -235,6 +204,25 @@ void PowerDevilUPowerBackend::init()
         canHybridSleep.waitForFinished();
         if (canHybridSleep.isValid() && (canHybridSleep.value() == "yes" || canHybridSleep.value() == "challenge"))
             supported |= HybridSuspend;
+
+        kDebug() << LOGIN1_SERVICE << "supported" << supported;
+    } else if (m_consolekitInterface) {
+        QDBusPendingReply<QString> canSuspend = m_consolekitInterface.data()->asyncCall("CanSuspend");
+        canSuspend.waitForFinished();
+        if (canSuspend.isValid() && (canSuspend.value() == "yes" || canSuspend.value() == "challenge"))
+            supported |= ToRam;
+
+        QDBusPendingReply<QString> canHibernate = m_consolekitInterface.data()->asyncCall("CanHibernate");
+        canHibernate.waitForFinished();
+        if (canHibernate.isValid() && (canHibernate.value() == "yes" || canHibernate.value() == "challenge"))
+            supported |= ToDisk;
+
+        QDBusPendingReply<QString> canHybridSleep = m_consolekitInterface.data()->asyncCall("CanHybridSleep");
+        canHybridSleep.waitForFinished();
+        if (canHybridSleep.isValid() && (canHybridSleep.value() == "yes" || canHybridSleep.value() == "challenge"))
+            supported |= HybridSuspend;
+
+        kDebug() << CONSOLEKIT_SERVICE << "supported" << supported;
     } else {
         if (m_upowerInterface->canSuspend() && m_upowerInterface->SuspendAllowed()) {
             kDebug() << "Can suspend";
@@ -250,6 +238,8 @@ void PowerDevilUPowerBackend::init()
     // "resuming" signal
     if (m_login1Interface && checkSystemdVersion(198)) {
         connect(m_login1Interface.data(), SIGNAL(PrepareForSleep(bool)), this, SLOT(slotLogin1Resuming(bool)));
+    } else if (m_consolekitInterface) {
+        connect(m_consolekitInterface.data(), SIGNAL(PrepareForSleep(bool)), this, SLOT(slotConsoleKitResuming(bool)));
     } else {
         connect(m_upowerInterface, SIGNAL(Resuming()), this, SIGNAL(resumeFromSuspend()));
     }
@@ -393,6 +383,8 @@ KJob* PowerDevilUPowerBackend::suspend(PowerDevil::BackendInterface::SuspendMeth
 {
     if (m_login1Interface && checkSystemdVersion(195)) {
         return new Login1SuspendJob(m_login1Interface.data(), method, supportedSuspendMethods());
+    } else if (m_consolekitInterface) {
+        return new ConsoleKitSuspendJob(m_consolekitInterface.data(), method, supportedSuspendMethods());
     } else {
         return new UPowerSuspendJob(m_upowerInterface, method, supportedSuspendMethods());
     }
@@ -527,4 +519,11 @@ void PowerDevilUPowerBackend::slotLogin1Resuming(bool active)
     }
 }
 
+void PowerDevilUPowerBackend::slotConsoleKitResuming(bool active)
+{
+    if (!active) {
+        emit resumeFromSuspend();
+    }
+}
+
 #include "moc_powerdevilupowerbackend.cpp"
index 4837513..8b64bdb 100644 (file)
 #define UPOWER_IFACE_DEVICE "org.freedesktop.UPower.Device"
 
 #define LOGIN1_SERVICE "org.freedesktop.login1"
+#define LOGIN1_PATH "/org/freedesktop/login1"
+#define LOGIN1_IFACE "org.freedesktop.login1.Manager"
+
+#define CONSOLEKIT_SERVICE "org.freedesktop.ConsoleKit"
+#define CONSOLEKIT_PATH "/org/freedesktop/ConsoleKit/Manager"
+#define CONSOLEKIT_IFACE "org.freedesktop.ConsoleKit.Manager"
 
 class UdevHelper;
 class XRandRX11Helper;
@@ -77,6 +83,7 @@ private slots:
     void slotDeviceChanged(const QString &);
     void slotPropertyChanged();
     void slotLogin1Resuming(bool active);
+    void slotConsoleKitResuming(bool active);
     void slotScreenBrightnessChanged();
     void onKeyboardBrightnessChanged(int);
 
@@ -101,6 +108,8 @@ private:
 
     // login1 interface
     QWeakPointer<QDBusInterface> m_login1Interface;
+    // consolekit interface
+    QWeakPointer<QDBusInterface> m_consolekitInterface;
 
     // buttons
     bool m_lidIsPresent;