nixos/modules/bugs/plasma.patch
2024-10-14 11:53:30 +08:00

382 lines
21 KiB
Diff

From 8e698dbcdc9ce95095ea2739713fde05ca4822f5 Mon Sep 17 00:00:00 2001
From: Jakob Petsovits <jpetso@petsovits.com>
Date: Fri, 13 Sep 2024 17:05:35 +0200
Subject: [PATCH] applets/batterymonitor: React to D-Bus service (un)register
events
Previously, the "Power and Battery" applet only checked for the
presence of PowerDevil's D-Bus services once when it starts up.
This appears to (mostly?) work for applets embedded in a panel,
but does not work for applets on the desktop itself.
Likely there's a timing issue and applets on the desktop start
sooner than PowerDevil will advertise its services.
A better way to work is for the applet to monitor the bus for when
the relevant services appear or disappear. When observing a service
registered or unregistered event, the applet gets set up accordingly.
This fixes the race condition for two out of three applet parts
(power profiles, inhibitions) but does not fix battery status;
the data for that is coming from `BatteryControlModel`
in plasma-workspace. A similar fix will have to be implemented there.
CCBUG: 488915
CCBUG: 489003
CCBUG: 492859
CCBUG: 492945
---
.../plugin/powermanagementcontrol.cpp | 100 +++++++++++++++---
.../plugin/powermanagementcontrol.h | 12 ++-
.../plugin/powerprofilescontrol.cpp | 78 +++++++++++++-
.../plugin/powerprofilescontrol.h | 11 +-
4 files changed, 185 insertions(+), 16 deletions(-)
diff --git a/applets/batterymonitor/plugin/powermanagementcontrol.cpp b/applets/batterymonitor/plugin/powermanagementcontrol.cpp
index fa3e59c49..72af079a7 100644
--- a/applets/batterymonitor/plugin/powermanagementcontrol.cpp
+++ b/applets/batterymonitor/plugin/powermanagementcontrol.cpp
@@ -14,6 +14,7 @@
#include <QDBusInterface>
#include <QDBusMetaType>
#include <QDBusReply>
+#include <QDBusServiceWatcher>
#include <QString>
#include <QVariant>
@@ -26,11 +27,53 @@ static constexpr QLatin1StringView FDO_POWERMANAGEMENT_SERVICE("org.freedesktop.
PowerManagementControl::PowerManagementControl(QObject *parent)
: QObject(parent)
+ , m_solidWatcher(new QDBusServiceWatcher)
+ , m_fdoWatcher(new QDBusServiceWatcher)
{
qDBusRegisterMetaType<QList<InhibitionInfo>>();
qDBusRegisterMetaType<InhibitionInfo>();
+ // Watch for PowerDevil's power management service
+ m_solidWatcher->setConnection(QDBusConnection::sessionBus());
+ m_solidWatcher->setWatchMode(QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration);
+ m_solidWatcher->addWatchedService(SOLID_POWERMANAGEMENT_SERVICE);
+
+ connect(m_solidWatcher.get(), &QDBusServiceWatcher::serviceRegistered, this, &PowerManagementControl::onServiceRegistered);
+ connect(m_solidWatcher.get(), &QDBusServiceWatcher::serviceUnregistered, this, &PowerManagementControl::onServiceUnregistered);
+ // If it's up and running already, let's cache it
if (QDBusConnection::sessionBus().interface()->isServiceRegistered(SOLID_POWERMANAGEMENT_SERVICE)) {
+ onServiceRegistered(SOLID_POWERMANAGEMENT_SERVICE);
+ }
+
+ // Watch for the freedesktop.org power management service
+ m_fdoWatcher->setConnection(QDBusConnection::sessionBus());
+ m_fdoWatcher->setWatchMode(QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration);
+ m_fdoWatcher->addWatchedService(FDO_POWERMANAGEMENT_SERVICE);
+
+ connect(m_fdoWatcher.get(), &QDBusServiceWatcher::serviceRegistered, this, &PowerManagementControl::onServiceRegistered);
+ connect(m_fdoWatcher.get(), &QDBusServiceWatcher::serviceUnregistered, this, &PowerManagementControl::onServiceUnregistered);
+ // If it's up and running already, let's cache it
+ if (QDBusConnection::sessionBus().interface()->isServiceRegistered(FDO_POWERMANAGEMENT_SERVICE)) {
+ onServiceRegistered(FDO_POWERMANAGEMENT_SERVICE);
+ }
+}
+
+PowerManagementControl::~PowerManagementControl()
+{
+}
+
+void PowerManagementControl::onServiceRegistered(const QString &serviceName)
+{
+ if (serviceName == FDO_POWERMANAGEMENT_SERVICE) {
+ if (!QDBusConnection::sessionBus().connect(FDO_POWERMANAGEMENT_SERVICE,
+ QStringLiteral("/org/freedesktop/PowerManagement"),
+ QStringLiteral("org.freedesktop.PowerManagement.Inhibit"),
+ QStringLiteral("HasInhibitChanged"),
+ this,
+ SLOT(onHasInhibitionChanged(bool)))) {
+ qCDebug(APPLETS::BATTERYMONITOR) << "Error connecting to fdo inhibition changes via dbus";
+ }
+ } else if (serviceName == SOLID_POWERMANAGEMENT_SERVICE) {
m_isManuallyInhibited = InhibitMonitor::self().getInhibit();
connect(&InhibitMonitor::self(), &InhibitMonitor::isManuallyInhibitedChanged, this, &PowerManagementControl::onIsManuallyInhibitedChanged);
connect(&InhibitMonitor::self(), &InhibitMonitor::isManuallyInhibitedChangeError, this, &PowerManagementControl::onisManuallyInhibitedErrorChanged);
@@ -119,21 +162,54 @@ PowerManagementControl::PowerManagementControl(QObject *parent)
qCDebug(APPLETS::BATTERYMONITOR) << "Error connecting to temporarily blocked inhibition changes via dbus";
}
}
-
- if (QDBusConnection::sessionBus().interface()->isServiceRegistered(FDO_POWERMANAGEMENT_SERVICE)) {
- if (!QDBusConnection::sessionBus().connect(FDO_POWERMANAGEMENT_SERVICE,
- QStringLiteral("/org/freedesktop/PowerManagement"),
- QStringLiteral("org.freedesktop.PowerManagement.Inhibit"),
- QStringLiteral("HasInhibitChanged"),
- this,
- SLOT(onHasInhibitionChanged(bool)))) {
- qCDebug(APPLETS::BATTERYMONITOR) << "Error connecting to fdo inhibition changes via dbus";
- }
- }
}
-PowerManagementControl::~PowerManagementControl()
+void PowerManagementControl::onServiceUnregistered(const QString &serviceName)
{
+ if (serviceName == FDO_POWERMANAGEMENT_SERVICE) {
+ QDBusConnection::sessionBus().disconnect(FDO_POWERMANAGEMENT_SERVICE,
+ QStringLiteral("/org/freedesktop/PowerManagement"),
+ QStringLiteral("org.freedesktop.PowerManagement.Inhibit"),
+ QStringLiteral("HasInhibitChanged"),
+ this,
+ SLOT(onHasInhibitionChanged(bool)));
+ } else if (serviceName == SOLID_POWERMANAGEMENT_SERVICE) {
+ disconnect(&InhibitMonitor::self(), &InhibitMonitor::isManuallyInhibitedChanged, this, &PowerManagementControl::onIsManuallyInhibitedChanged);
+ disconnect(&InhibitMonitor::self(), &InhibitMonitor::isManuallyInhibitedChangeError, this, &PowerManagementControl::onisManuallyInhibitedErrorChanged);
+
+ QDBusConnection::sessionBus().disconnect(SOLID_POWERMANAGEMENT_SERVICE,
+ QStringLiteral("/org/kde/Solid/PowerManagement/Actions/HandleButtonEvents"),
+ QStringLiteral("org.kde.Solid.PowerManagement.Actions.HandleButtonEvents"),
+ QStringLiteral("triggersLidActionChanged"),
+ this,
+ SLOT(triggersLidActionChanged(bool)));
+ QDBusConnection::sessionBus().disconnect(SOLID_POWERMANAGEMENT_SERVICE,
+ QStringLiteral("/org/kde/Solid/PowerManagement/PolicyAgent"),
+ QStringLiteral("org.kde.Solid.PowerManagement.PolicyAgent"),
+ QStringLiteral("InhibitionsChanged"),
+ this,
+ SLOT(onInhibitionsChanged(QList<InhibitionInfo>, QStringList)));
+ QDBusConnection::sessionBus().disconnect(SOLID_POWERMANAGEMENT_SERVICE,
+ QStringLiteral("/org/kde/Solid/PowerManagement/PolicyAgent"),
+ QStringLiteral("org.kde.Solid.PowerManagement.PolicyAgent"),
+ QStringLiteral("PermanentlyBlockedInhibitionsChanged"),
+ this,
+ SLOT(onPermanentlyBlockedInhibitionsChanged(QList<InhibitionInfo>, QList<InhibitionInfo>)));
+ QDBusConnection::sessionBus().disconnect(SOLID_POWERMANAGEMENT_SERVICE,
+ QStringLiteral("/org/kde/Solid/PowerManagement/PolicyAgent"),
+ QStringLiteral("org.kde.Solid.PowerManagement.PolicyAgent"),
+ QStringLiteral("TemporarilyBlockedInhibitionsChanged"),
+ this,
+ SLOT(onTemporarilyBlockedInhibitionsChanged(QList<InhibitionInfo>, QList<InhibitionInfo>)));
+
+ m_inhibitions = QList<QVariantMap>();
+ m_blockedInhibitions = QList<QVariantMap>();
+ m_hasInhibition = false;
+ m_isManuallyInhibited = false;
+ m_isManuallyInhibitedError = false;
+ m_isLidPresent = false;
+ m_triggersLidAction = false;
+ }
}
void PowerManagementControl::inhibit(const QString &reason)
diff --git a/applets/batterymonitor/plugin/powermanagementcontrol.h b/applets/batterymonitor/plugin/powermanagementcontrol.h
index 1057a5569..467993660 100644
--- a/applets/batterymonitor/plugin/powermanagementcontrol.h
+++ b/applets/batterymonitor/plugin/powermanagementcontrol.h
@@ -7,6 +7,8 @@
#pragma once
+#include "applicationdata_p.h"
+
#include <QHash>
#include <QIcon>
#include <QObject>
@@ -16,10 +18,12 @@
#include <qqmlregistration.h>
#include <qtmetamacros.h>
-#include "applicationdata_p.h"
+#include <memory>
using InhibitionInfo = QPair<QString, QString>;
+class QDBusServiceWatcher;
+
class PowerManagementControl : public QObject
{
Q_OBJECT
@@ -53,6 +57,8 @@ Q_SIGNALS:
void isManuallyInhibitedErrorChanged(bool status);
private Q_SLOTS:
+ void onServiceRegistered(const QString &serviceName);
+ void onServiceUnregistered(const QString &serviceName);
void onInhibitionsChanged(const QList<InhibitionInfo> &added, const QStringList &removed);
void onPermanentlyBlockedInhibitionsChanged(const QList<InhibitionInfo> &added, const QList<InhibitionInfo> &removed);
void onTemporarilyBlockedInhibitionsChanged(const QList<InhibitionInfo> &added, const QList<InhibitionInfo> &removed);
@@ -79,7 +85,7 @@ private:
Q_OBJECT_BINDABLE_PROPERTY(PowerManagementControl, QList<QVariantMap>, m_inhibitions, &PowerManagementControl::inhibitionsChanged)
Q_OBJECT_BINDABLE_PROPERTY(PowerManagementControl, QList<QVariantMap>, m_blockedInhibitions, &PowerManagementControl::blockedInhibitionsChanged)
- Q_OBJECT_BINDABLE_PROPERTY(PowerManagementControl, bool, m_hasInhibition, &PowerManagementControl::hasInhibitionChanged)
+ Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(PowerManagementControl, bool, m_hasInhibition, false, &PowerManagementControl::hasInhibitionChanged)
Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(PowerManagementControl, bool, m_isLidPresent, false, &PowerManagementControl::isLidPresentChanged)
Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(PowerManagementControl, bool, m_triggersLidAction, false, &PowerManagementControl::triggersLidActionChanged)
Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(PowerManagementControl, bool, m_isManuallyInhibited, false, &PowerManagementControl::isManuallyInhibitedChanged)
@@ -89,6 +95,8 @@ private:
false,
&PowerManagementControl::isManuallyInhibitedErrorChanged)
+ std::unique_ptr<QDBusServiceWatcher> m_solidWatcher;
+ std::unique_ptr<QDBusServiceWatcher> m_fdoWatcher;
bool m_isSilent = false;
ApplicationData m_data;
diff --git a/applets/batterymonitor/plugin/powerprofilescontrol.cpp b/applets/batterymonitor/plugin/powerprofilescontrol.cpp
index 2c5670b1b..d059095a3 100644
--- a/applets/batterymonitor/plugin/powerprofilescontrol.cpp
+++ b/applets/batterymonitor/plugin/powerprofilescontrol.cpp
@@ -13,6 +13,7 @@
#include <QDBusMetaType>
#include <QDBusPendingCallWatcher>
#include <QDBusReply>
+#include <QDBusServiceWatcher>
#include <QFile>
#include <QFileInfo>
#include <QIcon>
@@ -25,11 +26,31 @@ static constexpr QLatin1StringView SOLID_POWERMANAGEMENT_SERVICE("org.kde.Solid.
PowerProfilesControl::PowerProfilesControl(QObject *parent)
: QObject(parent)
+ , m_solidWatcher(new QDBusServiceWatcher)
{
qDBusRegisterMetaType<QList<QVariantMap>>();
qDBusRegisterMetaType<QVariantMap>();
+ // Watch for PowerDevil's power management service
+ m_solidWatcher->setConnection(QDBusConnection::sessionBus());
+ m_solidWatcher->setWatchMode(QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration);
+ m_solidWatcher->addWatchedService(SOLID_POWERMANAGEMENT_SERVICE);
+
+ connect(m_solidWatcher.get(), &QDBusServiceWatcher::serviceRegistered, this, &PowerProfilesControl::onServiceRegistered);
+ connect(m_solidWatcher.get(), &QDBusServiceWatcher::serviceUnregistered, this, &PowerProfilesControl::onServiceUnregistered);
+ // If it's up and running already, let's cache it
if (QDBusConnection::sessionBus().interface()->isServiceRegistered(SOLID_POWERMANAGEMENT_SERVICE)) {
+ onServiceRegistered(SOLID_POWERMANAGEMENT_SERVICE);
+ }
+}
+
+PowerProfilesControl::~PowerProfilesControl()
+{
+}
+
+void PowerProfilesControl::onServiceRegistered(const QString &serviceName)
+{
+ if (serviceName == SOLID_POWERMANAGEMENT_SERVICE) {
if (QDBusConnection::systemBus().interface()->isServiceRegistered(QStringLiteral("org.freedesktop.UPower.PowerProfiles"))) {
QDBusMessage profileChoices = QDBusMessage::createMethodCall(QStringLiteral("org.kde.Solid.PowerManagement"),
QStringLiteral("/org/kde/Solid/PowerManagement/Actions/PowerProfile"),
@@ -181,6 +202,7 @@ PowerProfilesControl::PowerProfilesControl(QObject *parent)
SLOT(updatePowerProfileHolds(QList<QVariantMap>)))) {
qCDebug(APPLETS::BATTERYMONITOR) << "error connecting to profile hold changes via dbus";
}
+ m_isTlpInstalled = false;
m_isPowerProfileDaemonInstalled = true;
} else {
m_isTlpInstalled = !QStandardPaths::findExecutable(QStringLiteral("tlp")).isEmpty();
@@ -188,8 +210,62 @@ PowerProfilesControl::PowerProfilesControl(QObject *parent)
}
}
-PowerProfilesControl::~PowerProfilesControl()
+void PowerProfilesControl::onServiceUnregistered(const QString &serviceName)
{
+ if (serviceName == SOLID_POWERMANAGEMENT_SERVICE) {
+ m_isPowerProfileDaemonInstalled = false;
+ // leave m_isTlpInstalled as is, it's not going to change just because PowerDevil disappeared
+
+ QDBusConnection::sessionBus().disconnect(SOLID_POWERMANAGEMENT_SERVICE,
+ QStringLiteral("/org/kde/Solid/PowerManagement/Actions/PowerProfile"),
+ QStringLiteral("org.kde.Solid.PowerManagement.Actions.PowerProfile"),
+ QStringLiteral("configuredProfileChanged"),
+ this,
+ SLOT(updatePowerProfileConfiguredProfile(QString)));
+
+ QDBusConnection::sessionBus().disconnect(SOLID_POWERMANAGEMENT_SERVICE,
+ QStringLiteral("/org/kde/Solid/PowerManagement/Actions/PowerProfile"),
+ QStringLiteral("org.kde.Solid.PowerManagement.Actions.PowerProfile"),
+ QStringLiteral("currentProfileChanged"),
+ this,
+ SLOT(updatePowerProfileCurrentProfile(QString)));
+
+ QDBusConnection::sessionBus().disconnect(SOLID_POWERMANAGEMENT_SERVICE,
+ QStringLiteral("/org/kde/Solid/PowerManagement/Actions/PowerProfile"),
+ QStringLiteral("org.kde.Solid.PowerManagement.Actions.PowerProfile"),
+ QStringLiteral("profileChoicesChanged"),
+ this,
+ SLOT(updatePowerProfileChoices(QStringList)));
+
+ QDBusConnection::sessionBus().disconnect(SOLID_POWERMANAGEMENT_SERVICE,
+ QStringLiteral("/org/kde/Solid/PowerManagement/Actions/PowerProfile"),
+ QStringLiteral("org.kde.Solid.PowerManagement.Actions.PowerProfile"),
+ QStringLiteral("performanceInhibitedReasonChanged"),
+ this,
+ SLOT(updatePowerProfilePerformanceInhibitedReason(QString)));
+
+ QDBusConnection::sessionBus().disconnect(SOLID_POWERMANAGEMENT_SERVICE,
+ QStringLiteral("/org/kde/Solid/PowerManagement/Actions/PowerProfile"),
+ QStringLiteral("org.kde.Solid.PowerManagement.Actions.PowerProfile"),
+ QStringLiteral("performanceDegradedReasonChanged"),
+ this,
+ SLOT(updatePowerProfilePerformanceDegradedReason(QString)));
+
+ QDBusConnection::sessionBus().disconnect(SOLID_POWERMANAGEMENT_SERVICE,
+ QStringLiteral("/org/kde/Solid/PowerManagement/Actions/PowerProfile"),
+ QStringLiteral("org.kde.Solid.PowerManagement.Actions.PowerProfile"),
+ QStringLiteral("profileHoldsChanged"),
+ this,
+ SLOT(updatePowerProfileHolds(QList<QVariantMap>)));
+
+ updatePowerProfileHolds({});
+ updatePowerProfilePerformanceDegradedReason(QString());
+ updatePowerProfilePerformanceInhibitedReason(QString());
+ updatePowerProfileChoices({});
+ updatePowerProfileCurrentProfile(QString());
+ updatePowerProfileConfiguredProfile(QString());
+ m_profileError = QString();
+ }
}
bool PowerProfilesControl::isTlpInstalled() const
diff --git a/applets/batterymonitor/plugin/powerprofilescontrol.h b/applets/batterymonitor/plugin/powerprofilescontrol.h
index f54c9e813..dc2fd58a2 100644
--- a/applets/batterymonitor/plugin/powerprofilescontrol.h
+++ b/applets/batterymonitor/plugin/powerprofilescontrol.h
@@ -6,13 +6,17 @@
#pragma once
+#include "applicationdata_p.h"
+
#include <QDBusPendingCall>
#include <QObject>
#include <QObjectBindableProperty>
#include <QStringList>
#include <qqmlregistration.h>
-#include "applicationdata_p.h"
+#include <memory>
+
+class QDBusServiceWatcher;
class PowerProfilesControl : public QObject
{
@@ -52,6 +56,9 @@ private:
QBindable<QList<QVariantMap>> bindableProfileHolds();
private Q_SLOTS:
+ void onServiceRegistered(const QString &serviceName);
+ void onServiceUnregistered(const QString &serviceName);
+
void updatePowerProfileChoices(const QStringList &choices);
void updatePowerProfileConfiguredProfile(const QString &profile);
void updatePowerProfileCurrentProfile(const QString &profile);
@@ -83,6 +90,8 @@ private:
Q_OBJECT_BINDABLE_PROPERTY(PowerProfilesControl, QString, m_degradationReason, &PowerProfilesControl::degradationReasonChanged)
Q_OBJECT_BINDABLE_PROPERTY(PowerProfilesControl, QList<QVariantMap>, m_profileHolds, &PowerProfilesControl::profileHoldsChanged)
+ std::unique_ptr<QDBusServiceWatcher> m_solidWatcher;
+
bool m_isSilent = false;
bool m_isTlpInstalled = false;
--
GitLab