1 | /* |
2 | SPDX-FileCopyrightText: 2015 Martin Gräßlin <mgraesslin@kde.org> |
3 | |
4 | SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL |
5 | */ |
6 | #include "dpms.h" |
7 | #include "event_queue.h" |
8 | #include "output.h" |
9 | #include "wayland_pointer_p.h" |
10 | |
11 | #include <wayland-client-protocol.h> |
12 | #include <wayland-dpms-client-protocol.h> |
13 | |
14 | namespace KWayland |
15 | { |
16 | namespace Client |
17 | { |
18 | class Q_DECL_HIDDEN DpmsManager::Private |
19 | { |
20 | public: |
21 | WaylandPointer<org_kde_kwin_dpms_manager, org_kde_kwin_dpms_manager_destroy> manager; |
22 | EventQueue *queue = nullptr; |
23 | }; |
24 | |
25 | DpmsManager::DpmsManager(QObject *parent) |
26 | : QObject(parent) |
27 | , d(new Private) |
28 | { |
29 | } |
30 | |
31 | DpmsManager::~DpmsManager() |
32 | { |
33 | release(); |
34 | } |
35 | |
36 | void DpmsManager::release() |
37 | { |
38 | d->manager.release(); |
39 | } |
40 | |
41 | void DpmsManager::destroy() |
42 | { |
43 | d->manager.destroy(); |
44 | } |
45 | |
46 | bool DpmsManager::isValid() const |
47 | { |
48 | return d->manager.isValid(); |
49 | } |
50 | |
51 | void DpmsManager::setup(org_kde_kwin_dpms_manager *manager) |
52 | { |
53 | Q_ASSERT(manager); |
54 | Q_ASSERT(!d->manager.isValid()); |
55 | d->manager.setup(pointer: manager); |
56 | } |
57 | |
58 | EventQueue *DpmsManager::eventQueue() |
59 | { |
60 | return d->queue; |
61 | } |
62 | |
63 | void DpmsManager::setEventQueue(EventQueue *queue) |
64 | { |
65 | d->queue = queue; |
66 | } |
67 | |
68 | Dpms *DpmsManager::getDpms(Output *output, QObject *parent) |
69 | { |
70 | Q_ASSERT(isValid()); |
71 | Q_ASSERT(output); |
72 | Dpms *dpms = new Dpms(output, parent); |
73 | auto w = org_kde_kwin_dpms_manager_get(org_kde_kwin_dpms_manager: d->manager, output: *output); |
74 | if (d->queue) { |
75 | d->queue->addProxy(proxy: w); |
76 | } |
77 | dpms->setup(w); |
78 | return dpms; |
79 | } |
80 | |
81 | DpmsManager::operator org_kde_kwin_dpms_manager *() const |
82 | { |
83 | return d->manager; |
84 | } |
85 | |
86 | DpmsManager::operator org_kde_kwin_dpms_manager *() |
87 | { |
88 | return d->manager; |
89 | } |
90 | |
91 | class Q_DECL_HIDDEN Dpms::Private |
92 | { |
93 | public: |
94 | explicit Private(const QPointer<Output> &output, Dpms *q); |
95 | void setup(org_kde_kwin_dpms *d); |
96 | |
97 | WaylandPointer<org_kde_kwin_dpms, org_kde_kwin_dpms_release> dpms; |
98 | struct Data { |
99 | bool supported = false; |
100 | Mode mode = Mode::On; |
101 | bool supportedChanged = false; |
102 | bool modeChanged = false; |
103 | }; |
104 | Data current; |
105 | Data pending; |
106 | QPointer<Output> output; |
107 | |
108 | private: |
109 | static void supportedCallback(void *data, org_kde_kwin_dpms *org_kde_kwin_dpms, uint32_t supported); |
110 | static void modeCallback(void *data, org_kde_kwin_dpms *org_kde_kwin_dpms, uint32_t mode); |
111 | static void doneCallback(void *data, org_kde_kwin_dpms *org_kde_kwin_dpms); |
112 | static const struct org_kde_kwin_dpms_listener s_listener; |
113 | |
114 | Dpms *q; |
115 | }; |
116 | |
117 | #ifndef K_DOXYGEN |
118 | const org_kde_kwin_dpms_listener Dpms::Private::s_listener = {.supported: supportedCallback, .mode: modeCallback, .done: doneCallback}; |
119 | #endif |
120 | |
121 | void Dpms::Private::supportedCallback(void *data, org_kde_kwin_dpms *org_kde_kwin_dpms, uint32_t supported) |
122 | { |
123 | Q_UNUSED(org_kde_kwin_dpms) |
124 | Private *p = reinterpret_cast<Private *>(data); |
125 | p->pending.supported = supported == 0 ? false : true; |
126 | p->pending.supportedChanged = true; |
127 | } |
128 | |
129 | void Dpms::Private::modeCallback(void *data, org_kde_kwin_dpms *org_kde_kwin_dpms, uint32_t mode) |
130 | { |
131 | Q_UNUSED(org_kde_kwin_dpms) |
132 | Mode m; |
133 | switch (mode) { |
134 | case ORG_KDE_KWIN_DPMS_MODE_ON: |
135 | m = Mode::On; |
136 | break; |
137 | case ORG_KDE_KWIN_DPMS_MODE_STANDBY: |
138 | m = Mode::Standby; |
139 | break; |
140 | case ORG_KDE_KWIN_DPMS_MODE_SUSPEND: |
141 | m = Mode::Suspend; |
142 | break; |
143 | case ORG_KDE_KWIN_DPMS_MODE_OFF: |
144 | m = Mode::Off; |
145 | break; |
146 | default: |
147 | return; |
148 | } |
149 | Private *p = reinterpret_cast<Private *>(data); |
150 | p->pending.mode = m; |
151 | p->pending.modeChanged = true; |
152 | } |
153 | |
154 | void Dpms::Private::doneCallback(void *data, org_kde_kwin_dpms *org_kde_kwin_dpms) |
155 | { |
156 | Q_UNUSED(org_kde_kwin_dpms) |
157 | Private *p = reinterpret_cast<Private *>(data); |
158 | const bool supportedChanged = p->pending.supportedChanged && p->pending.supported != p->current.supported; |
159 | const bool modeChanged = p->pending.modeChanged && p->pending.mode != p->current.mode; |
160 | if (supportedChanged) { |
161 | p->current.supported = p->pending.supported; |
162 | Q_EMIT p->q->supportedChanged(); |
163 | } |
164 | if (modeChanged) { |
165 | p->current.mode = p->pending.mode; |
166 | Q_EMIT p->q->modeChanged(); |
167 | } |
168 | p->pending = Data(); |
169 | } |
170 | |
171 | Dpms::Private::Private(const QPointer<Output> &output, Dpms *q) |
172 | : output(output) |
173 | , q(q) |
174 | { |
175 | } |
176 | |
177 | void Dpms::Private::setup(org_kde_kwin_dpms *d) |
178 | { |
179 | Q_ASSERT(d); |
180 | Q_ASSERT(!dpms.isValid()); |
181 | dpms.setup(pointer: d); |
182 | org_kde_kwin_dpms_add_listener(org_kde_kwin_dpms: dpms, listener: &s_listener, data: this); |
183 | } |
184 | |
185 | Dpms::Dpms(const QPointer<Output> &o, QObject *parent) |
186 | : QObject(parent) |
187 | , d(new Private(o, this)) |
188 | { |
189 | } |
190 | |
191 | Dpms::~Dpms() |
192 | { |
193 | release(); |
194 | } |
195 | |
196 | void Dpms::destroy() |
197 | { |
198 | d->dpms.destroy(); |
199 | } |
200 | |
201 | void Dpms::release() |
202 | { |
203 | d->dpms.release(); |
204 | } |
205 | |
206 | bool Dpms::isValid() const |
207 | { |
208 | return d->dpms.isValid(); |
209 | } |
210 | |
211 | void Dpms::setup(org_kde_kwin_dpms *dpms) |
212 | { |
213 | d->setup(dpms); |
214 | } |
215 | |
216 | bool Dpms::isSupported() const |
217 | { |
218 | return d->current.supported; |
219 | } |
220 | |
221 | Dpms::Mode Dpms::mode() const |
222 | { |
223 | return d->current.mode; |
224 | } |
225 | |
226 | void Dpms::requestMode(Dpms::Mode mode) |
227 | { |
228 | uint32_t wlMode; |
229 | switch (mode) { |
230 | case Mode::On: |
231 | wlMode = ORG_KDE_KWIN_DPMS_MODE_ON; |
232 | break; |
233 | case Mode::Standby: |
234 | wlMode = ORG_KDE_KWIN_DPMS_MODE_STANDBY; |
235 | break; |
236 | case Mode::Suspend: |
237 | wlMode = ORG_KDE_KWIN_DPMS_MODE_SUSPEND; |
238 | break; |
239 | case Mode::Off: |
240 | wlMode = ORG_KDE_KWIN_DPMS_MODE_OFF; |
241 | break; |
242 | default: |
243 | Q_UNREACHABLE(); |
244 | } |
245 | org_kde_kwin_dpms_set(org_kde_kwin_dpms: d->dpms, mode: wlMode); |
246 | } |
247 | |
248 | QPointer<Output> Dpms::output() const |
249 | { |
250 | return d->output; |
251 | } |
252 | |
253 | Dpms::operator org_kde_kwin_dpms *() |
254 | { |
255 | return d->dpms; |
256 | } |
257 | |
258 | Dpms::operator org_kde_kwin_dpms *() const |
259 | { |
260 | return d->dpms; |
261 | } |
262 | |
263 | } |
264 | } |
265 | |
266 | #include "moc_dpms.cpp" |
267 | |