1 | /* |
2 | SPDX-FileCopyrightText: 2016 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 "pointerconstraints.h" |
7 | #include "event_queue.h" |
8 | #include "pointer.h" |
9 | #include "region.h" |
10 | #include "surface.h" |
11 | #include "wayland_pointer_p.h" |
12 | |
13 | #include <wayland-pointer-constraints-unstable-v1-client-protocol.h> |
14 | |
15 | namespace KWayland |
16 | { |
17 | namespace Client |
18 | { |
19 | class Q_DECL_HIDDEN PointerConstraints::Private |
20 | { |
21 | public: |
22 | Private() = default; |
23 | |
24 | void setup(zwp_pointer_constraints_v1 *arg); |
25 | |
26 | WaylandPointer<zwp_pointer_constraints_v1, zwp_pointer_constraints_v1_destroy> pointerconstraints; |
27 | EventQueue *queue = nullptr; |
28 | }; |
29 | |
30 | PointerConstraints::PointerConstraints(QObject *parent) |
31 | : QObject(parent) |
32 | , d(new Private) |
33 | { |
34 | } |
35 | |
36 | void PointerConstraints::Private::setup(zwp_pointer_constraints_v1 *arg) |
37 | { |
38 | Q_ASSERT(arg); |
39 | Q_ASSERT(!pointerconstraints); |
40 | pointerconstraints.setup(pointer: arg); |
41 | } |
42 | |
43 | PointerConstraints::~PointerConstraints() |
44 | { |
45 | release(); |
46 | } |
47 | |
48 | void PointerConstraints::setup(zwp_pointer_constraints_v1 *pointerconstraints) |
49 | { |
50 | d->setup(pointerconstraints); |
51 | } |
52 | |
53 | void PointerConstraints::release() |
54 | { |
55 | d->pointerconstraints.release(); |
56 | } |
57 | |
58 | void PointerConstraints::destroy() |
59 | { |
60 | d->pointerconstraints.destroy(); |
61 | } |
62 | |
63 | PointerConstraints::operator zwp_pointer_constraints_v1 *() |
64 | { |
65 | return d->pointerconstraints; |
66 | } |
67 | |
68 | PointerConstraints::operator zwp_pointer_constraints_v1 *() const |
69 | { |
70 | return d->pointerconstraints; |
71 | } |
72 | |
73 | bool PointerConstraints::isValid() const |
74 | { |
75 | return d->pointerconstraints.isValid(); |
76 | } |
77 | |
78 | void PointerConstraints::setEventQueue(EventQueue *queue) |
79 | { |
80 | d->queue = queue; |
81 | } |
82 | |
83 | EventQueue *PointerConstraints::eventQueue() |
84 | { |
85 | return d->queue; |
86 | } |
87 | |
88 | LockedPointer *PointerConstraints::lockPointer(Surface *surface, Pointer *pointer, Region *region, LifeTime lifetime, QObject *parent) |
89 | { |
90 | Q_ASSERT(isValid()); |
91 | auto p = new LockedPointer(parent); |
92 | zwp_pointer_constraints_v1_lifetime lf; |
93 | switch (lifetime) { |
94 | case LifeTime::OneShot: |
95 | lf = ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT; |
96 | break; |
97 | case LifeTime::Persistent: |
98 | lf = ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT; |
99 | break; |
100 | default: |
101 | Q_UNREACHABLE(); |
102 | break; |
103 | } |
104 | wl_region *wr = nullptr; |
105 | if (region) { |
106 | wr = *region; |
107 | } |
108 | auto w = zwp_pointer_constraints_v1_lock_pointer(zwp_pointer_constraints_v1: d->pointerconstraints, surface: *surface, pointer: *pointer, region: wr, lifetime: lf); |
109 | if (d->queue) { |
110 | d->queue->addProxy(proxy: w); |
111 | } |
112 | p->setup(w); |
113 | return p; |
114 | } |
115 | |
116 | ConfinedPointer *PointerConstraints::confinePointer(Surface *surface, Pointer *pointer, Region *region, LifeTime lifetime, QObject *parent) |
117 | { |
118 | Q_ASSERT(isValid()); |
119 | auto p = new ConfinedPointer(parent); |
120 | zwp_pointer_constraints_v1_lifetime lf; |
121 | switch (lifetime) { |
122 | case LifeTime::OneShot: |
123 | lf = ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT; |
124 | break; |
125 | case LifeTime::Persistent: |
126 | lf = ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT; |
127 | break; |
128 | default: |
129 | Q_UNREACHABLE(); |
130 | break; |
131 | } |
132 | wl_region *wr = nullptr; |
133 | if (region) { |
134 | wr = *region; |
135 | } |
136 | auto w = zwp_pointer_constraints_v1_confine_pointer(zwp_pointer_constraints_v1: d->pointerconstraints, surface: *surface, pointer: *pointer, region: wr, lifetime: lf); |
137 | if (d->queue) { |
138 | d->queue->addProxy(proxy: w); |
139 | } |
140 | p->setup(w); |
141 | return p; |
142 | } |
143 | |
144 | class Q_DECL_HIDDEN LockedPointer::Private |
145 | { |
146 | public: |
147 | Private(LockedPointer *q); |
148 | |
149 | void setup(zwp_locked_pointer_v1 *arg); |
150 | |
151 | WaylandPointer<zwp_locked_pointer_v1, zwp_locked_pointer_v1_destroy> lockedpointer; |
152 | |
153 | private: |
154 | LockedPointer *q; |
155 | |
156 | private: |
157 | static void lockedCallback(void *data, zwp_locked_pointer_v1 *zwp_locked_pointer_v1); |
158 | static void unlockedCallback(void *data, zwp_locked_pointer_v1 *zwp_locked_pointer_v1); |
159 | |
160 | static const zwp_locked_pointer_v1_listener s_listener; |
161 | }; |
162 | |
163 | const zwp_locked_pointer_v1_listener LockedPointer::Private::s_listener = {.locked: lockedCallback, .unlocked: unlockedCallback}; |
164 | |
165 | void LockedPointer::Private::lockedCallback(void *data, zwp_locked_pointer_v1 *zwp_locked_pointer_v1) |
166 | { |
167 | auto p = reinterpret_cast<LockedPointer::Private *>(data); |
168 | Q_ASSERT(p->lockedpointer == zwp_locked_pointer_v1); |
169 | Q_EMIT p->q->locked(); |
170 | } |
171 | |
172 | void LockedPointer::Private::unlockedCallback(void *data, zwp_locked_pointer_v1 *zwp_locked_pointer_v1) |
173 | { |
174 | auto p = reinterpret_cast<LockedPointer::Private *>(data); |
175 | Q_ASSERT(p->lockedpointer == zwp_locked_pointer_v1); |
176 | Q_EMIT p->q->unlocked(); |
177 | } |
178 | |
179 | LockedPointer::Private::Private(LockedPointer *q) |
180 | : q(q) |
181 | { |
182 | } |
183 | |
184 | LockedPointer::LockedPointer(QObject *parent) |
185 | : QObject(parent) |
186 | , d(new Private(this)) |
187 | { |
188 | } |
189 | |
190 | void LockedPointer::Private::setup(zwp_locked_pointer_v1 *arg) |
191 | { |
192 | Q_ASSERT(arg); |
193 | Q_ASSERT(!lockedpointer); |
194 | lockedpointer.setup(pointer: arg); |
195 | zwp_locked_pointer_v1_add_listener(zwp_locked_pointer_v1: lockedpointer, listener: &s_listener, data: this); |
196 | } |
197 | |
198 | LockedPointer::~LockedPointer() |
199 | { |
200 | release(); |
201 | } |
202 | |
203 | void LockedPointer::setup(zwp_locked_pointer_v1 *lockedpointer) |
204 | { |
205 | d->setup(lockedpointer); |
206 | } |
207 | |
208 | void LockedPointer::release() |
209 | { |
210 | d->lockedpointer.release(); |
211 | } |
212 | |
213 | void LockedPointer::destroy() |
214 | { |
215 | d->lockedpointer.destroy(); |
216 | } |
217 | |
218 | LockedPointer::operator zwp_locked_pointer_v1 *() |
219 | { |
220 | return d->lockedpointer; |
221 | } |
222 | |
223 | LockedPointer::operator zwp_locked_pointer_v1 *() const |
224 | { |
225 | return d->lockedpointer; |
226 | } |
227 | |
228 | bool LockedPointer::isValid() const |
229 | { |
230 | return d->lockedpointer.isValid(); |
231 | } |
232 | |
233 | void LockedPointer::setCursorPositionHint(const QPointF &surfaceLocal) |
234 | { |
235 | Q_ASSERT(isValid()); |
236 | zwp_locked_pointer_v1_set_cursor_position_hint(zwp_locked_pointer_v1: d->lockedpointer, surface_x: wl_fixed_from_double(d: surfaceLocal.x()), surface_y: wl_fixed_from_double(d: surfaceLocal.y())); |
237 | } |
238 | |
239 | void LockedPointer::setRegion(Region *region) |
240 | { |
241 | Q_ASSERT(isValid()); |
242 | wl_region *wr = nullptr; |
243 | if (region) { |
244 | wr = *region; |
245 | } |
246 | zwp_locked_pointer_v1_set_region(zwp_locked_pointer_v1: d->lockedpointer, region: wr); |
247 | } |
248 | |
249 | class Q_DECL_HIDDEN ConfinedPointer::Private |
250 | { |
251 | public: |
252 | Private(ConfinedPointer *q); |
253 | |
254 | void setup(zwp_confined_pointer_v1 *arg); |
255 | |
256 | WaylandPointer<zwp_confined_pointer_v1, zwp_confined_pointer_v1_destroy> confinedpointer; |
257 | |
258 | private: |
259 | ConfinedPointer *q; |
260 | |
261 | private: |
262 | static void confinedCallback(void *data, zwp_confined_pointer_v1 *zwp_confined_pointer_v1); |
263 | static void unconfinedCallback(void *data, zwp_confined_pointer_v1 *zwp_confined_pointer_v1); |
264 | |
265 | static const zwp_confined_pointer_v1_listener s_listener; |
266 | }; |
267 | |
268 | const zwp_confined_pointer_v1_listener ConfinedPointer::Private::s_listener = {.confined: confinedCallback, .unconfined: unconfinedCallback}; |
269 | |
270 | void ConfinedPointer::Private::confinedCallback(void *data, zwp_confined_pointer_v1 *zwp_confined_pointer_v1) |
271 | { |
272 | auto p = reinterpret_cast<ConfinedPointer::Private *>(data); |
273 | Q_ASSERT(p->confinedpointer == zwp_confined_pointer_v1); |
274 | Q_EMIT p->q->confined(); |
275 | } |
276 | |
277 | void ConfinedPointer::Private::unconfinedCallback(void *data, zwp_confined_pointer_v1 *zwp_confined_pointer_v1) |
278 | { |
279 | auto p = reinterpret_cast<ConfinedPointer::Private *>(data); |
280 | Q_ASSERT(p->confinedpointer == zwp_confined_pointer_v1); |
281 | Q_EMIT p->q->unconfined(); |
282 | } |
283 | |
284 | ConfinedPointer::Private::Private(ConfinedPointer *q) |
285 | : q(q) |
286 | { |
287 | } |
288 | |
289 | ConfinedPointer::ConfinedPointer(QObject *parent) |
290 | : QObject(parent) |
291 | , d(new Private(this)) |
292 | { |
293 | } |
294 | |
295 | void ConfinedPointer::Private::setup(zwp_confined_pointer_v1 *arg) |
296 | { |
297 | Q_ASSERT(arg); |
298 | Q_ASSERT(!confinedpointer); |
299 | confinedpointer.setup(pointer: arg); |
300 | zwp_confined_pointer_v1_add_listener(zwp_confined_pointer_v1: confinedpointer, listener: &s_listener, data: this); |
301 | } |
302 | |
303 | ConfinedPointer::~ConfinedPointer() |
304 | { |
305 | release(); |
306 | } |
307 | |
308 | void ConfinedPointer::setup(zwp_confined_pointer_v1 *confinedpointer) |
309 | { |
310 | d->setup(confinedpointer); |
311 | } |
312 | |
313 | void ConfinedPointer::release() |
314 | { |
315 | d->confinedpointer.release(); |
316 | } |
317 | |
318 | void ConfinedPointer::destroy() |
319 | { |
320 | d->confinedpointer.destroy(); |
321 | } |
322 | |
323 | ConfinedPointer::operator zwp_confined_pointer_v1 *() |
324 | { |
325 | return d->confinedpointer; |
326 | } |
327 | |
328 | ConfinedPointer::operator zwp_confined_pointer_v1 *() const |
329 | { |
330 | return d->confinedpointer; |
331 | } |
332 | |
333 | bool ConfinedPointer::isValid() const |
334 | { |
335 | return d->confinedpointer.isValid(); |
336 | } |
337 | |
338 | void ConfinedPointer::setRegion(Region *region) |
339 | { |
340 | Q_ASSERT(isValid()); |
341 | wl_region *wr = nullptr; |
342 | if (region) { |
343 | wr = *region; |
344 | } |
345 | zwp_confined_pointer_v1_set_region(zwp_confined_pointer_v1: d->confinedpointer, region: wr); |
346 | } |
347 | |
348 | } |
349 | } |
350 | |
351 | #include "moc_pointerconstraints.cpp" |
352 | |