summaryrefslogtreecommitdiff
path: root/accounts/gkleen@skadhi/shell/quickshell-plugins/Systemd.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'accounts/gkleen@skadhi/shell/quickshell-plugins/Systemd.cpp')
-rw-r--r--accounts/gkleen@skadhi/shell/quickshell-plugins/Systemd.cpp289
1 files changed, 289 insertions, 0 deletions
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..1fa236f6
--- /dev/null
+++ b/accounts/gkleen@skadhi/shell/quickshell-plugins/Systemd.cpp
@@ -0,0 +1,289 @@
1#include "Systemd.hpp"
2
3#include <sstream>
4
5#include <QDBusConnection>
6#include <QDBusReply>
7#include <QDebug>
8#include <QDBusUnixFileDescriptor>
9#include <QDBusObjectPath>
10
11#include <set>
12
13Systemd::Systemd(QObject* parent) : QObject(parent) {
14 ListUnitsEntry::registerMetaType();
15 qDBusRegisterMetaType<ListUnitsResult>();
16
17 this->systemdManager = new DBusSystemdManager(
18 "org.freedesktop.systemd1",
19 "/org/freedesktop/systemd1",
20 QDBusConnection::sessionBus(),
21 this
22 );
23 this->logindManager = new DBusLogindManager(
24 "org.freedesktop.login1",
25 "/org/freedesktop/login1",
26 QDBusConnection::systemBus(),
27 this
28 );
29
30
31 QDBusReply<QDBusObjectPath> sessionPath = this->logindManager->GetSession("auto");
32 // qDebug() << sessionPath;
33 this->logindSession = new DBusLogindSession(
34 "org.freedesktop.login1",
35 sessionPath.value().path(),
36 QDBusConnection::systemBus(),
37 this
38 );
39 this->logindSessionProperties = new DBusProperties(
40 "org.freedesktop.login1",
41 sessionPath.value().path(),
42 QDBusConnection::systemBus(),
43 this
44 );
45
46 QObject::connect(this->logindManager, &DBusLogindManager::PrepareForShutdown, this, &Systemd::prepareForShutdown);
47 QObject::connect(this->logindManager, &DBusLogindManager::PrepareForSleep, this, &Systemd::prepareForSleep);
48 QObject::connect(this->logindSession, &DBusLogindSession::Lock, this, &Systemd::lock);
49 QObject::connect(this->logindSession, &DBusLogindSession::Unlock, this, &Systemd::unlock);
50 QObject::connect(this->logindSessionProperties, &DBusProperties::PropertiesChanged, this, &Systemd::onLogindSessionPropertiesChanged);
51 this->systemdManager->Subscribe();
52 QObject::connect(this->systemdManager, &DBusSystemdManager::UnitNew, this, &Systemd::onUserUnitNew);
53 QObject::connect(this->systemdManager, &DBusSystemdManager::UnitRemoved, this, &Systemd::onUserUnitRemoved);
54
55 for (const auto& unit: this->systemdManager->ListUnits().value())
56 this->onUserUnitNew(unit.primaryName, unit.unitPath);
57}
58
59void Systemd::onLogindSessionPropertiesChanged(const QString& interface_name, const QVariantMap& changed_properties, const QStringList& invalidated_properties) {
60 if (changed_properties.contains("IdleHint") || invalidated_properties.contains("IdleHint"))
61 emit this->idleHintChanged();
62 if (changed_properties.contains("LockedHint") || invalidated_properties.contains("LockedHint"))
63 emit this->lockedHintChanged();
64}
65void Systemd::onUserUnitNew(const QString& id, const QDBusObjectPath& object_path) {
66 for (auto unit: this->mUserUnits.valueList())
67 if (unit->path() == object_path)
68 return;
69
70 for (const auto& unit: this->systemdManager->ListUnits().value())
71 if (unit.unitPath == object_path) {
72 this->mUserUnits.insertObject(new SystemdUnit(this, object_path, id));
73 return;
74 }
75}
76void Systemd::onUserUnitRemoved(const QString& id, const QDBusObjectPath& object_path) {
77 std::set<SystemdUnit*> toRemove;
78 for (auto unit: this->mUserUnits.valueList())
79 if (unit->path() == object_path)
80 toRemove.insert(unit);
81
82 for (auto unit: toRemove) {
83 this->mUserUnits.removeObject(unit);
84 delete unit;
85 }
86}
87
88SystemdUnit::SystemdUnit(QObject* parent, const QDBusObjectPath& path, const QString& id): QObject(parent), mPath(path), mId(id) {
89 this->mUnitProperties = new DBusProperties(
90 "org.freedesktop.systemd1",
91 this->path().path(),
92 QDBusConnection::sessionBus(),
93 this
94 );
95}
96std::unique_ptr<DBusSystemdUnit> SystemdUnit::systemdUnit() {
97 return std::make_unique<DBusSystemdUnit>(
98 "org.freedesktop.systemd1",
99 this->path().path(),
100 QDBusConnection::sessionBus(),
101 nullptr
102 );
103}
104std::unique_ptr<DBusSystemdService> SystemdUnit::systemdService() {
105 if (!this->id().endsWith(".service"))
106 return std::unique_ptr<DBusSystemdService>();
107
108 return std::make_unique<DBusSystemdService>(
109 "org.freedesktop.systemd1",
110 this->path().path(),
111 QDBusConnection::sessionBus(),
112 nullptr
113 );
114}
115QList<QString> SystemdUnit::runtimeDirectory() {
116 if (std::unique_ptr<DBusSystemdService> systemdService = this->systemdService()) {
117 if (!this->mRuntimeDirectory)
118 this->mRuntimeDirectory = systemdService->runtimeDirectory();
119 return *this->mRuntimeDirectory;
120 }
121
122 return QList<QString>{};
123}
124QString SystemdUnit::activeState() {
125 if (!this->mActiveState) {
126 QObject::connect(this->mUnitProperties, &DBusProperties::PropertiesChanged, this, &SystemdUnit::onUnitPropertiesChanged);
127 this->mActiveState = this->systemdUnit()->activeState();
128 }
129
130 return *this->mActiveState;
131}
132
133const QDBusObjectPath& SystemdUnit::path() const { return this->mPath; }
134const QString& SystemdUnit::id() const { return this->mId; }
135void SystemdUnit::onUnitPropertiesChanged(const QString& interface_name, const QVariantMap& changed_properties, const QStringList& invalidated_properties) {
136 if (changed_properties.contains("ActiveState") || invalidated_properties.contains("ActiveState")) {
137 this->mActiveState = this->systemdUnit()->activeState();
138 emit this->activeStateChanged();
139 }
140}
141
142void Systemd::stopUserUnit(const QString& unit, const QString& mode) { this->systemdManager->StopUnit(unit, mode); }
143
144void Systemd::setBrightness(const QString& subsystem, const QString& name, quint32 brightness) { this->logindSession->SetBrightness(subsystem, name, brightness); }
145
146bool Systemd::idleHint() { return this->logindSession->idleHint(); }
147void Systemd::setIdleHint(bool idle) { this->logindSession->SetIdleHint(idle); }
148bool Systemd::lockedHint() { return this->logindSession->lockedHint(); }
149void Systemd::setLockedHint(bool locked) { this->logindSession->SetLockedHint(locked); }
150void Systemd::lockSession() { this->logindSession->call("Lock"); }
151void Systemd::sleep() { this->logindManager->Sleep(true); }
152void Systemd::suspend() { this->logindManager->Suspend(true); }
153void Systemd::hibernate() { this->logindManager->Hibernate(true); }
154
155ObjectModel<SystemdUnit>* Systemd::userUnits() { return &this->mUserUnits; }
156
157std::string SystemdInhibitorParams::toString(SystemdInhibitorParams::WhatItem what) {
158 if (what == SystemdInhibitorParams::Shutdown)
159 return "shutdown";
160 else if (what == SystemdInhibitorParams::Sleep)
161 return "sleep";
162 else if (what == SystemdInhibitorParams::Idle)
163 return "idle";
164 else if (what == SystemdInhibitorParams::HandlePowerKey)
165 return "handle-power-key";
166 else if (what == SystemdInhibitorParams::HandleSuspendKey)
167 return "handle-suspend-key";
168 else if (what == SystemdInhibitorParams::HandleHibernateKey)
169 return "handle-hibernate-key";
170 else if (what == SystemdInhibitorParams::HandleLidSwitch)
171 return "handle-lid-switch";
172 return "";
173}
174
175std::string SystemdInhibitorParams::toString(SystemdInhibitorParams::What what) {
176 std::ostringstream res;
177 bool first = true;
178 for (const WhatItem& item: SystemdInhibitorParams::allWhatItems) {
179 if (!(what & item))
180 continue;
181
182 if (!first)
183 res << ":";
184 else
185 first = false;
186 res << SystemdInhibitorParams::toString(item);
187 }
188 return res.str();
189}
190
191std::string SystemdInhibitorParams::toString(SystemdInhibitorParams::Mode mode) {
192 if (mode == SystemdInhibitorParams::Block)
193 return "block";
194 else if (mode == SystemdInhibitorParams::BlockWeak)
195 return "block-weak";
196 else if (mode == SystemdInhibitorParams::Delay)
197 return "delay";
198 return "";
199}
200
201bool SystemdInhibitor::enabled() const { return static_cast<bool>(this->activeInhibitor); }
202void SystemdInhibitor::setEnabled(bool enabled) {
203 this->mEnabled = enabled;
204
205 if (enabled)
206 this->update();
207 else
208 this->release();
209}
210
211SystemdInhibitorParams::What SystemdInhibitor::what() const { return this->mWhat; }
212void SystemdInhibitor::setWhat(SystemdInhibitorParams::What what) {
213 this->mWhat = what;
214 this->update();
215}
216
217QString SystemdInhibitor::who() const { return this->mWho; }
218void SystemdInhibitor::setWho(QString who) {
219 this->mWho = who;
220 this->update();
221}
222
223QString SystemdInhibitor::why() const { return this->mWhy; }
224void SystemdInhibitor::setWhy(QString why) {
225 this->mWhy = why;
226 this->update();
227}
228
229SystemdInhibitorParams::Mode SystemdInhibitor::mode() const { return this->mMode; }
230void SystemdInhibitor::setMode(SystemdInhibitorParams::Mode mode) {
231 this->mMode = mode;
232 this->update();
233}
234
235SystemdInhibitor::ActiveSystemdInhibitor::ActiveSystemdInhibitor(SystemdInhibitorParams::What what_, QString who_, QString why_, SystemdInhibitorParams::Mode mode_): what(what_), who(who_), why(why_), mode(mode_) {
236 DBusLogindManager logindManager(
237 "org.freedesktop.login1",
238 "/org/freedesktop/login1",
239 QDBusConnection::systemBus()
240 );
241 QDBusReply<QDBusUnixFileDescriptor> fd_ = logindManager.Inhibit(QString::fromStdString(SystemdInhibitorParams::toString(what)), who, why, QString::fromStdString(SystemdInhibitorParams::toString(mode)));
242 if (fd_.error().isValid())
243 throw fd_.error();
244 this->fd = ::dup(fd_.value().fileDescriptor());
245}
246SystemdInhibitor::ActiveSystemdInhibitor::~ActiveSystemdInhibitor() {
247 if (this->fd != -1)
248 ::close(this->fd);
249}
250
251void SystemdInhibitor::release() {
252 if (!this->activeInhibitor)
253 return;
254
255 this->activeInhibitor.reset();
256 emit this->enabledChanged();
257}
258
259void SystemdInhibitor::update() {
260 if (!this->mWhat || this->mWho.isEmpty() || this->mWhy.isEmpty() || !this->mMode || !this->mEnabled)
261 if (this->activeInhibitor)
262 this->release();
263 else
264 return;
265
266 if (this->activeInhibitor && this->mWhat == this->activeInhibitor->what && this->mWho == this->activeInhibitor->who && this->mWhy == this->activeInhibitor->why && this->mMode == this->activeInhibitor->mode)
267 return;
268
269 std::unique_ptr<ActiveSystemdInhibitor> otherInhibitor;
270 try {
271 otherInhibitor.reset(new SystemdInhibitor::ActiveSystemdInhibitor(this->mWhat, this->mWho, this->mWhy, this->mMode));
272 } catch (const QDBusError& err) {
273 qCritical().noquote()
274 << err.name().toStdString() << " " << err.message().toStdString();
275 return;
276 }
277 this->activeInhibitor.swap(otherInhibitor);
278
279 if (!otherInhibitor && this->activeInhibitor)
280 emit this->enabledChanged();
281 if (otherInhibitor && otherInhibitor->what != this->activeInhibitor->what)
282 emit this->whatChanged();
283 if (otherInhibitor && otherInhibitor->who != this->activeInhibitor->who)
284 emit this->whoChanged();
285 if (otherInhibitor && otherInhibitor->why != this->activeInhibitor->why)
286 emit this->whyChanged();
287 if (otherInhibitor && otherInhibitor->mode != this->activeInhibitor->mode)
288 emit this->modeChanged();
289}