1 /*
2 * SPDX-FileCopyrightText: 2019 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 #include "monitor.h"
8 #include "monitor_p.h"
9
10 #include <QDBusConnection>
11 #include <QDBusMessage>
12 #include <QDBusPendingCallWatcher>
13 #include <QDBusPendingReply>
14 #include <QDBusServiceWatcher>
15
16 static const QString s_serviceName = QStringLiteral("org.kde.KWin");
17 static const QString s_nightColorPath = QStringLiteral("/ColorCorrect");
18 static const QString s_nightColorInterface = QStringLiteral("org.kde.kwin.ColorCorrect");
19 static const QString s_propertiesInterface = QStringLiteral("org.freedesktop.DBus.Properties");
20
MonitorPrivate(QObject * parent)21 MonitorPrivate::MonitorPrivate(QObject *parent)
22 : QObject(parent)
23 {
24 QDBusServiceWatcher *watcher = new QDBusServiceWatcher(s_serviceName, QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForOwnerChange, this);
25 connect(watcher, &QDBusServiceWatcher::serviceRegistered, this, &MonitorPrivate::handleServiceRegistered);
26 connect(watcher, &QDBusServiceWatcher::serviceUnregistered, this, &MonitorPrivate::handleServiceUnregistered);
27
28 handleServiceRegistered();
29 }
30
~MonitorPrivate()31 MonitorPrivate::~MonitorPrivate()
32 {
33 }
34
handleServiceRegistered()35 void MonitorPrivate::handleServiceRegistered()
36 {
37 QDBusConnection bus = QDBusConnection::sessionBus();
38
39 // clang-format off
40 const bool connected = bus.connect(s_serviceName,
41 s_nightColorPath,
42 s_propertiesInterface,
43 QStringLiteral("PropertiesChanged"),
44 this,
45 SLOT(handlePropertiesChanged(QString,QVariantMap,QStringList)));
46 // clang-format on
47 if (!connected) {
48 return;
49 }
50
51 QDBusMessage message = QDBusMessage::createMethodCall(s_serviceName, s_nightColorPath, s_propertiesInterface, QStringLiteral("GetAll"));
52 message.setArguments({s_nightColorInterface});
53
54 QDBusPendingReply<QVariantMap> properties = bus.asyncCall(message);
55 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(properties, this);
56
57 connect(watcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *self) {
58 self->deleteLater();
59
60 const QDBusPendingReply<QVariantMap> properties = *self;
61 if (properties.isError()) {
62 return;
63 }
64
65 updateProperties(properties.value());
66 });
67 }
68
handleServiceUnregistered()69 void MonitorPrivate::handleServiceUnregistered()
70 {
71 QDBusConnection bus = QDBusConnection::sessionBus();
72
73 // clang-format off
74 bus.disconnect(s_serviceName,
75 s_nightColorPath,
76 s_propertiesInterface,
77 QStringLiteral("PropertiesChanged"),
78 this,
79 SLOT(handlePropertiesChanged(QString,QVariantMap,QStringList)));
80 // clang-format on
81
82 setAvailable(false);
83 }
84
handlePropertiesChanged(const QString & interfaceName,const QVariantMap & changedProperties,const QStringList & invalidatedProperties)85 void MonitorPrivate::handlePropertiesChanged(const QString &interfaceName, const QVariantMap &changedProperties, const QStringList &invalidatedProperties)
86 {
87 Q_UNUSED(interfaceName)
88 Q_UNUSED(invalidatedProperties)
89
90 updateProperties(changedProperties);
91 }
92
currentTemperature() const93 int MonitorPrivate::currentTemperature() const
94 {
95 return m_currentTemperature;
96 }
97
targetTemperature() const98 int MonitorPrivate::targetTemperature() const
99 {
100 return m_targetTemperature;
101 }
102
updateProperties(const QVariantMap & properties)103 void MonitorPrivate::updateProperties(const QVariantMap &properties)
104 {
105 const QVariant available = properties.value(QStringLiteral("available"));
106 if (available.isValid()) {
107 setAvailable(available.toBool());
108 }
109
110 const QVariant enabled = properties.value(QStringLiteral("enabled"));
111 if (enabled.isValid()) {
112 setEnabled(enabled.toBool());
113 }
114
115 const QVariant running = properties.value(QStringLiteral("running"));
116 if (running.isValid()) {
117 setRunning(running.toBool());
118 }
119
120 const QVariant currentTemperature = properties.value(QStringLiteral("currentTemperature"));
121 if (currentTemperature.isValid()) {
122 setCurrentTemperature(currentTemperature.toInt());
123 }
124
125 const QVariant targetTemperature = properties.value(QStringLiteral("targetTemperature"));
126 if (targetTemperature.isValid()) {
127 setTargetTemperature(targetTemperature.toInt());
128 }
129 }
130
setCurrentTemperature(int temperature)131 void MonitorPrivate::setCurrentTemperature(int temperature)
132 {
133 if (m_currentTemperature == temperature) {
134 return;
135 }
136 m_currentTemperature = temperature;
137 Q_EMIT currentTemperatureChanged();
138 }
139
setTargetTemperature(int temperature)140 void MonitorPrivate::setTargetTemperature(int temperature)
141 {
142 if (m_targetTemperature == temperature) {
143 return;
144 }
145 m_targetTemperature = temperature;
146 Q_EMIT targetTemperatureChanged();
147 }
148
isAvailable() const149 bool MonitorPrivate::isAvailable() const
150 {
151 return m_isAvailable;
152 }
153
setAvailable(bool available)154 void MonitorPrivate::setAvailable(bool available)
155 {
156 if (m_isAvailable == available) {
157 return;
158 }
159 m_isAvailable = available;
160 Q_EMIT availableChanged();
161 }
162
isEnabled() const163 bool MonitorPrivate::isEnabled() const
164 {
165 return m_isEnabled;
166 }
167
setEnabled(bool enabled)168 void MonitorPrivate::setEnabled(bool enabled)
169 {
170 if (m_isEnabled == enabled) {
171 return;
172 }
173 m_isEnabled = enabled;
174 Q_EMIT enabledChanged();
175 }
176
isRunning() const177 bool MonitorPrivate::isRunning() const
178 {
179 return m_isRunning;
180 }
181
setRunning(bool running)182 void MonitorPrivate::setRunning(bool running)
183 {
184 if (m_isRunning == running) {
185 return;
186 }
187 m_isRunning = running;
188 Q_EMIT runningChanged();
189 }
190
Monitor(QObject * parent)191 Monitor::Monitor(QObject *parent)
192 : QObject(parent)
193 , d(new MonitorPrivate(this))
194 {
195 connect(d, &MonitorPrivate::availableChanged, this, &Monitor::availableChanged);
196 connect(d, &MonitorPrivate::enabledChanged, this, &Monitor::enabledChanged);
197 connect(d, &MonitorPrivate::runningChanged, this, &Monitor::runningChanged);
198 connect(d, &MonitorPrivate::currentTemperatureChanged, this, &Monitor::currentTemperatureChanged);
199 connect(d, &MonitorPrivate::targetTemperatureChanged, this, &Monitor::targetTemperatureChanged);
200 }
201
~Monitor()202 Monitor::~Monitor()
203 {
204 }
205
isAvailable() const206 bool Monitor::isAvailable() const
207 {
208 return d->isAvailable();
209 }
210
isEnabled() const211 bool Monitor::isEnabled() const
212 {
213 return d->isEnabled();
214 }
215
isRunning() const216 bool Monitor::isRunning() const
217 {
218 return d->isRunning();
219 }
220
currentTemperature() const221 int Monitor::currentTemperature() const
222 {
223 return d->currentTemperature();
224 }
225
targetTemperature() const226 int Monitor::targetTemperature() const
227 {
228 return d->targetTemperature();
229 }
230