From ae9a80c1f012686c1f65fce7ce76fdd1b77b0b71 Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Wed, 23 Sep 2026 21:08:35 +0200 Subject: ... --- .../shell/quickshell-plugins/Systemd.cpp | 288 +++++++++++++++++++++ 1 file changed, 288 insertions(+) create mode 100644 accounts/gkleen@skadhi/shell/quickshell-plugins/Systemd.cpp (limited to 'accounts/gkleen@skadhi/shell/quickshell-plugins/Systemd.cpp') diff --git a/accounts/gkleen@skadhi/shell/quickshell-plugins/Systemd.cpp b/accounts/gkleen@skadhi/shell/quickshell-plugins/Systemd.cpp new file mode 100644 index 00000000..6376b527 --- /dev/null +++ b/accounts/gkleen@skadhi/shell/quickshell-plugins/Systemd.cpp @@ -0,0 +1,288 @@ +#include "Systemd.hpp" + +#include + +#include +#include +#include +#include +#include + +#include + +Systemd::Systemd(QObject* parent) : QObject(parent) { + ListUnitsEntry::registerMetaType(); + qDBusRegisterMetaType(); + + this->systemdManager = new DBusSystemdManager( + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + QDBusConnection::sessionBus(), + this + ); + this->logindManager = new DBusLogindManager( + "org.freedesktop.login1", + "/org/freedesktop/login1", + QDBusConnection::systemBus(), + this + ); + + + QDBusReply sessionPath = this->logindManager->GetSession("auto"); + // qDebug() << sessionPath; + this->logindSession = new DBusLogindSession( + "org.freedesktop.login1", + sessionPath.value().path(), + QDBusConnection::systemBus(), + this + ); + this->logindSessionProperties = new DBusProperties( + "org.freedesktop.login1", + sessionPath.value().path(), + QDBusConnection::systemBus(), + this + ); + + QObject::connect(this->logindManager, &DBusLogindManager::PrepareForShutdown, this, &Systemd::shutdown); + QObject::connect(this->logindManager, &DBusLogindManager::PrepareForSleep, this, &Systemd::sleep); + QObject::connect(this->logindSession, &DBusLogindSession::Lock, this, &Systemd::lock); + QObject::connect(this->logindSession, &DBusLogindSession::Unlock, this, &Systemd::unlock); + QObject::connect(this->logindSessionProperties, &DBusProperties::PropertiesChanged, this, &Systemd::onLogindSessionPropertiesChanged); + this->systemdManager->Subscribe(); + QObject::connect(this->systemdManager, &DBusSystemdManager::UnitNew, this, &Systemd::onUserUnitNew); + QObject::connect(this->systemdManager, &DBusSystemdManager::UnitRemoved, this, &Systemd::onUserUnitRemoved); + + for (const auto& unit: this->systemdManager->ListUnits().value()) + this->onUserUnitNew(unit.primaryName, unit.unitPath); +} + +void Systemd::onLogindSessionPropertiesChanged(const QString& interface_name, const QVariantMap& changed_properties, const QStringList& invalidated_properties) { + if (changed_properties.contains("IdleHint") || invalidated_properties.contains("IdleHint")) + emit this->idleHintChanged(); + if (changed_properties.contains("LockedHint") || invalidated_properties.contains("LockedHint")) + emit this->lockedHintChanged(); +} +void Systemd::onUserUnitNew(const QString& id, const QDBusObjectPath& object_path) { + for (auto unit: this->mUserUnits.valueList()) + if (unit->path() == object_path) + return; + + for (const auto& unit: this->systemdManager->ListUnits().value()) + if (unit.unitPath == object_path) { + this->mUserUnits.insertObject(new SystemdUnit(this, object_path, id)); + return; + } +} +void Systemd::onUserUnitRemoved(const QString& id, const QDBusObjectPath& object_path) { + std::set toRemove; + for (auto unit: this->mUserUnits.valueList()) + if (unit->path() == object_path) + toRemove.insert(unit); + + for (auto unit: toRemove) { + this->mUserUnits.removeObject(unit); + delete unit; + } +} + +SystemdUnit::SystemdUnit(QObject* parent, const QDBusObjectPath& path, const QString& id): QObject(parent), mPath(path), mId(id) { + this->mUnitProperties = new DBusProperties( + "org.freedesktop.systemd1", + this->path().path(), + QDBusConnection::sessionBus(), + this + ); +} +std::unique_ptr SystemdUnit::systemdUnit() { + return std::make_unique( + "org.freedesktop.systemd1", + this->path().path(), + QDBusConnection::sessionBus(), + nullptr + ); +} +std::unique_ptr SystemdUnit::systemdService() { + if (!this->id().endsWith(".service")) + return std::unique_ptr(); + + return std::make_unique( + "org.freedesktop.systemd1", + this->path().path(), + QDBusConnection::sessionBus(), + nullptr + ); +} +QList SystemdUnit::runtimeDirectory() { + if (std::unique_ptr systemdService = this->systemdService()) { + if (!this->mRuntimeDirectory) + this->mRuntimeDirectory = systemdService->runtimeDirectory(); + return *this->mRuntimeDirectory; + } + + return QList{}; +} +QString SystemdUnit::activeState() { + if (!this->mActiveState) { + QObject::connect(this->mUnitProperties, &DBusProperties::PropertiesChanged, this, &SystemdUnit::onUnitPropertiesChanged); + this->mActiveState = this->systemdUnit()->activeState(); + } + + return *this->mActiveState; +} + +const QDBusObjectPath& SystemdUnit::path() const { return this->mPath; } +const QString& SystemdUnit::id() const { return this->mId; } +void SystemdUnit::onUnitPropertiesChanged(const QString& interface_name, const QVariantMap& changed_properties, const QStringList& invalidated_properties) { + if (changed_properties.contains("ActiveState") || invalidated_properties.contains("ActiveState")) { + this->mActiveState = this->systemdUnit()->activeState(); + emit this->activeStateChanged(); + } +} + +void Systemd::stopUserUnit(const QString& unit, const QString& mode) { this->systemdManager->StopUnit(unit, mode); } + +void Systemd::setBrightness(const QString& subsystem, const QString& name, quint32 brightness) { this->logindSession->SetBrightness(subsystem, name, brightness); } + +bool Systemd::idleHint() { return this->logindSession->idleHint(); } +void Systemd::setIdleHint(bool idle) { this->logindSession->SetIdleHint(idle); } +bool Systemd::lockedHint() { return this->logindSession->lockedHint(); } +void Systemd::setLockedHint(bool locked) { this->logindSession->SetLockedHint(locked); } +void Systemd::lockSession() { this->logindSession->call("Lock"); } +void Systemd::suspend() { this->logindManager->Suspend(true); } +void Systemd::hibernate() { this->logindManager->Hibernate(true); } + +ObjectModel* Systemd::userUnits() { return &this->mUserUnits; } + +std::string SystemdInhibitorParams::toString(SystemdInhibitorParams::WhatItem what) { + if (what == SystemdInhibitorParams::Shutdown) + return "shutdown"; + else if (what == SystemdInhibitorParams::Sleep) + return "sleep"; + else if (what == SystemdInhibitorParams::Idle) + return "idle"; + else if (what == SystemdInhibitorParams::HandlePowerKey) + return "handle-power-key"; + else if (what == SystemdInhibitorParams::HandleSuspendKey) + return "handle-suspend-key"; + else if (what == SystemdInhibitorParams::HandleHibernateKey) + return "handle-hibernate-key"; + else if (what == SystemdInhibitorParams::HandleLidSwitch) + return "handle-lid-switch"; + return ""; +} + +std::string SystemdInhibitorParams::toString(SystemdInhibitorParams::What what) { + std::ostringstream res; + bool first = true; + for (const WhatItem& item: SystemdInhibitorParams::allWhatItems) { + if (!(what & item)) + continue; + + if (!first) + res << ":"; + else + first = false; + res << SystemdInhibitorParams::toString(item); + } + return res.str(); +} + +std::string SystemdInhibitorParams::toString(SystemdInhibitorParams::Mode mode) { + if (mode == SystemdInhibitorParams::Block) + return "block"; + else if (mode == SystemdInhibitorParams::BlockWeak) + return "block-weak"; + else if (mode == SystemdInhibitorParams::Delay) + return "delay"; + return ""; +} + +bool SystemdInhibitor::enabled() const { return static_cast(this->activeInhibitor); } +void SystemdInhibitor::setEnabled(bool enabled) { + this->mEnabled = enabled; + + if (enabled) + this->update(); + else + this->release(); +} + +SystemdInhibitorParams::What SystemdInhibitor::what() const { return this->mWhat; } +void SystemdInhibitor::setWhat(SystemdInhibitorParams::What what) { + this->mWhat = what; + this->update(); +} + +QString SystemdInhibitor::who() const { return this->mWho; } +void SystemdInhibitor::setWho(QString who) { + this->mWho = who; + this->update(); +} + +QString SystemdInhibitor::why() const { return this->mWhy; } +void SystemdInhibitor::setWhy(QString why) { + this->mWhy = why; + this->update(); +} + +SystemdInhibitorParams::Mode SystemdInhibitor::mode() const { return this->mMode; } +void SystemdInhibitor::setMode(SystemdInhibitorParams::Mode mode) { + this->mMode = mode; + this->update(); +} + +SystemdInhibitor::ActiveSystemdInhibitor::ActiveSystemdInhibitor(SystemdInhibitorParams::What what_, QString who_, QString why_, SystemdInhibitorParams::Mode mode_): what(what_), who(who_), why(why_), mode(mode_) { + DBusLogindManager logindManager( + "org.freedesktop.login1", + "/org/freedesktop/login1", + QDBusConnection::systemBus() + ); + QDBusReply fd_ = logindManager.Inhibit(QString::fromStdString(SystemdInhibitorParams::toString(what)), who, why, QString::fromStdString(SystemdInhibitorParams::toString(mode))); + if (fd_.error().isValid()) + throw fd_.error(); + this->fd = ::dup(fd_.value().fileDescriptor()); +} +SystemdInhibitor::ActiveSystemdInhibitor::~ActiveSystemdInhibitor() { + if (this->fd != -1) + ::close(this->fd); +} + +void SystemdInhibitor::release() { + if (!this->activeInhibitor) + return; + + this->activeInhibitor.reset(); + emit this->enabledChanged(); +} + +void SystemdInhibitor::update() { + if (!this->mWhat || this->mWho.isEmpty() || this->mWhy.isEmpty() || !this->mMode || !this->mEnabled) + if (this->activeInhibitor) + this->release(); + else + return; + + if (this->activeInhibitor && this->mWhat == this->activeInhibitor->what && this->mWho == this->activeInhibitor->who && this->mWhy == this->activeInhibitor->why && this->mMode == this->activeInhibitor->mode) + return; + + std::unique_ptr otherInhibitor; + try { + otherInhibitor.reset(new SystemdInhibitor::ActiveSystemdInhibitor(this->mWhat, this->mWho, this->mWhy, this->mMode)); + } catch (const QDBusError& err) { + qCritical().noquote() + << err.name().toStdString() << " " << err.message().toStdString(); + return; + } + this->activeInhibitor.swap(otherInhibitor); + + if (!otherInhibitor && this->activeInhibitor) + emit this->enabledChanged(); + if (otherInhibitor && otherInhibitor->what != this->activeInhibitor->what) + emit this->whatChanged(); + if (otherInhibitor && otherInhibitor->who != this->activeInhibitor->who) + emit this->whoChanged(); + if (otherInhibitor && otherInhibitor->why != this->activeInhibitor->why) + emit this->whyChanged(); + if (otherInhibitor && otherInhibitor->mode != this->activeInhibitor->mode) + emit this->modeChanged(); +} -- cgit v1.2.3