diff --git a/modules/bugs/425.patch b/modules/bugs/425.patch new file mode 100644 index 00000000..37f238b7 --- /dev/null +++ b/modules/bugs/425.patch @@ -0,0 +1,381 @@ +From 8e698dbcdc9ce95095ea2739713fde05ca4822f5 Mon Sep 17 00:00:00 2001 +From: Jakob Petsovits +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 + #include + #include ++#include + #include + #include + +@@ -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>(); + qDBusRegisterMetaType(); + ++ // 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, 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, QList))); ++ QDBusConnection::sessionBus().disconnect(SOLID_POWERMANAGEMENT_SERVICE, ++ QStringLiteral("/org/kde/Solid/PowerManagement/PolicyAgent"), ++ QStringLiteral("org.kde.Solid.PowerManagement.PolicyAgent"), ++ QStringLiteral("TemporarilyBlockedInhibitionsChanged"), ++ this, ++ SLOT(onTemporarilyBlockedInhibitionsChanged(QList, QList))); ++ ++ m_inhibitions = QList(); ++ m_blockedInhibitions = QList(); ++ 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 + #include + #include +@@ -16,10 +18,12 @@ + #include + #include + +-#include "applicationdata_p.h" ++#include + + using InhibitionInfo = QPair; + ++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 &added, const QStringList &removed); + void onPermanentlyBlockedInhibitionsChanged(const QList &added, const QList &removed); + void onTemporarilyBlockedInhibitionsChanged(const QList &added, const QList &removed); +@@ -79,7 +85,7 @@ private: + + Q_OBJECT_BINDABLE_PROPERTY(PowerManagementControl, QList, m_inhibitions, &PowerManagementControl::inhibitionsChanged) + Q_OBJECT_BINDABLE_PROPERTY(PowerManagementControl, QList, 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 m_solidWatcher; ++ std::unique_ptr 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 + #include + #include ++#include + #include + #include + #include +@@ -25,11 +26,31 @@ static constexpr QLatin1StringView SOLID_POWERMANAGEMENT_SERVICE("org.kde.Solid. + + PowerProfilesControl::PowerProfilesControl(QObject *parent) + : QObject(parent) ++ , m_solidWatcher(new QDBusServiceWatcher) + { + qDBusRegisterMetaType>(); + qDBusRegisterMetaType(); + ++ // 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)))) { + 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))); ++ ++ 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 + #include + #include + #include + #include + +-#include "applicationdata_p.h" ++#include ++ ++class QDBusServiceWatcher; + + class PowerProfilesControl : public QObject + { +@@ -52,6 +56,9 @@ private: + QBindable> 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, m_profileHolds, &PowerProfilesControl::profileHoldsChanged) + ++ std::unique_ptr m_solidWatcher; ++ + bool m_isSilent = false; + bool m_isTlpInstalled = false; + +-- +GitLab + diff --git a/modules/bugs/default.nix b/modules/bugs/default.nix index 801f422b..32611950 100644 --- a/modules/bugs/default.nix +++ b/modules/bugs/default.nix @@ -42,7 +42,10 @@ inputs: let modprobe = "${inputs.pkgs.kmod}/bin/modprobe"; in "${modprobe} -r -w 3000 mt7921e && ${modprobe} mt7921e"; # https://discuss.kde.org/t/bug-power-profiles-daemon-0-23-seems-starts-too-late-for-powerdevil/21416 # remove in plasma 6.2 - plasma.systemd.services.display-manager.after = [ "power-profiles-daemon.service" ]; + plasma.nixpkgs.overlays = [(final: prev: { kdePackages = prev.kdePackages.overrideScope (final: prev: { + power-profiles-daemon = prev.power-profiles-daemon.overrideAttrs (prev: { + patches = prev.patches ++ [ ./plasma.patch ]; + });});})]; }; in {