Changeset View
Changeset View
Standalone View
Standalone View
daemon/powerdevilpowermanagement.cpp
- This file was added.
1 | /******************************************************************** | ||||
---|---|---|---|---|---|
2 | Copyright 2016 Martin Gräßlin <mgraesslin@kde.org> | ||||
3 | | ||||
4 | This library is free software; you can redistribute it and/or | ||||
5 | modify it under the terms of the GNU Lesser General Public | ||||
6 | License as published by the Free Software Foundation; either | ||||
7 | version 2.1 of the License, or (at your option) version 3, or any | ||||
8 | later version accepted by the membership of KDE e.V. (or its | ||||
9 | successor approved by the membership of KDE e.V.), which shall | ||||
10 | act as a proxy defined in Section 6 of version 3 of the license. | ||||
11 | | ||||
12 | This library is distributed in the hope that it will be useful, | ||||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||||
15 | Lesser General Public License for more details. | ||||
16 | | ||||
17 | You should have received a copy of the GNU Lesser General Public | ||||
18 | License along with this library. If not, see <http://www.gnu.org/licenses/>. | ||||
19 | *********************************************************************/ | ||||
20 | | ||||
21 | #include "powerdevilpowermanagement.h" | ||||
22 | | ||||
23 | #include <QDBusConnection> | ||||
24 | #include <QDBusConnectionInterface> | ||||
25 | #include <QDBusServiceWatcher> | ||||
26 | | ||||
27 | namespace PowerDevil { | ||||
28 | | ||||
29 | static const QString s_fdoPowerService = QStringLiteral("org.freedesktop.PowerManagement"); | ||||
30 | static const QString s_fdoPowerPath = QStringLiteral("/org/freedesktop/PowerManagement"); | ||||
31 | | ||||
32 | class PowerManagementInstance : public PowerManagement | ||||
33 | { | ||||
34 | Q_OBJECT | ||||
35 | public: | ||||
36 | explicit PowerManagementInstance() : PowerManagement() {} | ||||
37 | }; | ||||
38 | Q_GLOBAL_STATIC(PowerManagementInstance, s_instance) | ||||
39 | | ||||
40 | class PowerManagement::Private | ||||
41 | { | ||||
42 | public: | ||||
43 | Private(PowerManagement *q); | ||||
44 | void update(); | ||||
45 | void setCanSuspend(bool set); | ||||
46 | void setCanHibernate(bool set); | ||||
47 | void setCanHybridSuspend(bool set); | ||||
48 | | ||||
49 | bool serviceRegistered; | ||||
50 | bool canSuspend; | ||||
51 | bool canHibernate; | ||||
52 | bool canHybridSuspend; | ||||
53 | QScopedPointer<QDBusServiceWatcher> fdoPowerServiceWatcher; | ||||
54 | | ||||
55 | private: | ||||
56 | void updateProperty(const QString &dbusName, void (Private::*setter)(bool)); | ||||
57 | PowerManagement *q; | ||||
58 | }; | ||||
59 | | ||||
60 | PowerManagement::Private::Private(PowerManagement *q) | ||||
61 | : serviceRegistered(false) | ||||
62 | , canSuspend(false) | ||||
63 | , canHibernate(false) | ||||
64 | , canHybridSuspend(false) | ||||
65 | , fdoPowerServiceWatcher(new QDBusServiceWatcher(s_fdoPowerService, QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForUnregistration | QDBusServiceWatcher::WatchForRegistration)) | ||||
66 | , q(q) | ||||
67 | { | ||||
68 | } | ||||
69 | | ||||
70 | void PowerManagement::Private::update() | ||||
71 | { | ||||
72 | serviceRegistered = true; | ||||
73 | updateProperty(QStringLiteral("CanSuspend"), &Private::setCanSuspend); | ||||
74 | updateProperty(QStringLiteral("CanHibernate"), &Private::setCanHibernate); | ||||
75 | updateProperty(QStringLiteral("CanHybridSuspend"), &Private::setCanHybridSuspend); | ||||
76 | } | ||||
77 | | ||||
78 | void PowerManagement::Private::updateProperty(const QString &dbusName, void (Private::*setter)(bool)) | ||||
79 | { | ||||
80 | QDBusMessage message = QDBusMessage::createMethodCall(s_fdoPowerService, | ||||
81 | s_fdoPowerPath, | ||||
82 | s_fdoPowerService, | ||||
83 | dbusName); | ||||
84 | QDBusPendingReply<bool> reply = QDBusConnection::sessionBus().asyncCall(message); | ||||
85 | QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(reply, q); | ||||
86 | QObject::connect(callWatcher, &QDBusPendingCallWatcher::finished, q, | ||||
87 | [this, setter](QDBusPendingCallWatcher *self) { | ||||
88 | QDBusPendingReply<bool> reply = *self; | ||||
89 | self->deleteLater(); | ||||
90 | if (!reply.isValid()) { | ||||
91 | return; | ||||
92 | } | ||||
93 | ((this)->*setter)(reply.value()); | ||||
94 | } | ||||
95 | ); | ||||
96 | | ||||
97 | } | ||||
98 | | ||||
99 | void PowerManagement::Private::setCanHibernate(bool set) | ||||
100 | { | ||||
101 | if (canHibernate == set) { | ||||
102 | return; | ||||
103 | } | ||||
104 | canHibernate = set; | ||||
105 | q->canHibernateChanged(); | ||||
106 | } | ||||
107 | | ||||
108 | void PowerManagement::Private::setCanSuspend(bool set) | ||||
109 | { | ||||
110 | if (canSuspend == set) { | ||||
111 | return; | ||||
112 | } | ||||
113 | canSuspend = set; | ||||
114 | q->canSuspendChanged(); | ||||
115 | } | ||||
116 | | ||||
117 | void PowerManagement::Private::setCanHybridSuspend(bool set) | ||||
118 | { | ||||
119 | if (canHybridSuspend == set) { | ||||
120 | return; | ||||
121 | } | ||||
122 | canHybridSuspend = set; | ||||
123 | q->canHybridSuspendChanged(); | ||||
124 | } | ||||
125 | | ||||
126 | PowerManagement *PowerManagement::instance() | ||||
127 | { | ||||
128 | return s_instance; | ||||
129 | } | ||||
130 | | ||||
131 | PowerManagement::PowerManagement() | ||||
132 | : QObject() | ||||
133 | , d(new Private(this)) | ||||
134 | { | ||||
135 | connect(d->fdoPowerServiceWatcher.data(), &QDBusServiceWatcher::serviceRegistered, this, [this] { d->update(); }); | ||||
136 | connect(d->fdoPowerServiceWatcher.data(), &QDBusServiceWatcher::serviceUnregistered, this, | ||||
137 | [this] { | ||||
138 | d->serviceRegistered = false; | ||||
139 | d->setCanSuspend(false); | ||||
140 | d->setCanHibernate(false); | ||||
141 | d->setCanHybridSuspend(false); | ||||
142 | } | ||||
143 | ); | ||||
144 | | ||||
145 | // check whether the service is registered | ||||
146 | QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.DBus"), | ||||
147 | QStringLiteral("/"), | ||||
148 | QStringLiteral("org.freedesktop.DBus"), | ||||
149 | QStringLiteral("ListNames")); | ||||
150 | QDBusPendingReply<QStringList> async = QDBusConnection::sessionBus().asyncCall(message); | ||||
151 | QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(async, this); | ||||
152 | connect(callWatcher, &QDBusPendingCallWatcher::finished, this, | ||||
153 | [this](QDBusPendingCallWatcher *self) { | ||||
154 | QDBusPendingReply<QStringList> reply = *self; | ||||
155 | self->deleteLater(); | ||||
156 | if (!reply.isValid()) { | ||||
157 | return; | ||||
158 | } | ||||
159 | if (reply.value().contains(s_fdoPowerService)) { | ||||
160 | d->update(); | ||||
161 | } | ||||
162 | } | ||||
163 | ); | ||||
164 | } | ||||
165 | | ||||
166 | PowerManagement::~PowerManagement() | ||||
167 | { | ||||
168 | } | ||||
169 | | ||||
170 | void PowerManagement::suspend() | ||||
171 | { | ||||
172 | if (!d->serviceRegistered) { | ||||
173 | return; | ||||
174 | } | ||||
175 | if (!d->canSuspend) { | ||||
176 | return; | ||||
177 | } | ||||
178 | QDBusMessage message = QDBusMessage::createMethodCall(s_fdoPowerService, | ||||
179 | s_fdoPowerPath, | ||||
180 | s_fdoPowerService, | ||||
181 | QStringLiteral("Suspend")); | ||||
182 | QDBusConnection::sessionBus().asyncCall(message); | ||||
183 | } | ||||
184 | | ||||
185 | void PowerManagement::hibernate() | ||||
186 | { | ||||
187 | if (!d->serviceRegistered) { | ||||
188 | return; | ||||
189 | } | ||||
190 | if (!d->canHibernate) { | ||||
191 | return; | ||||
192 | } | ||||
193 | QDBusMessage message = QDBusMessage::createMethodCall(s_fdoPowerService, | ||||
194 | s_fdoPowerPath, | ||||
195 | s_fdoPowerService, | ||||
196 | QStringLiteral("Hibernate")); | ||||
197 | QDBusConnection::sessionBus().asyncCall(message); | ||||
198 | } | ||||
199 | | ||||
200 | void PowerManagement::hybridSuspend() | ||||
201 | { | ||||
202 | // FIXME: Whether there is a support of this mode? | ||||
203 | } | ||||
204 | | ||||
205 | bool PowerManagement::canSuspend() const | ||||
206 | { | ||||
207 | return d->canSuspend; | ||||
208 | } | ||||
209 | | ||||
210 | bool PowerManagement::canHibernate() const | ||||
211 | { | ||||
212 | return d->canHibernate; | ||||
213 | } | ||||
214 | | ||||
215 | bool PowerManagement::canHybridSuspend() const | ||||
216 | { | ||||
217 | return d->canHybridSuspend; | ||||
218 | } | ||||
219 | | ||||
220 | } // namespace PowerDevil | ||||
221 | | ||||
222 | #include "powerdevilpowermanagement.moc" |