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#ifndef KWAYLAND_CLIENT_POINTERCONSTRAINTS_H
7#define KWAYLAND_CLIENT_POINTERCONSTRAINTS_H
8
9#include <QObject>
10
11#include "KWayland/Client/kwaylandclient_export.h"
12
13struct zwp_pointer_constraints_v1;
14struct zwp_locked_pointer_v1;
15struct zwp_confined_pointer_v1;
16
17class QPointF;
18
19namespace KWayland
20{
21namespace Client
22{
23class EventQueue;
24class LockedPointer;
25class Surface;
26class Region;
27class ConfinedPointer;
28class Pointer;
29
30/**
31 * @short Wrapper for the zwp_pointer_constraints_v1 interface.
32 *
33 * This class provides a convenient wrapper for the zwp_pointer_constraints_v1 interface.
34 *
35 * To use this class one needs to interact with the Registry. There are two
36 * possible ways to create the PointerConstraints interface:
37 * @code
38 * PointerConstraints *c = registry->createPointerConstraints(name, version);
39 * @endcode
40 *
41 * This creates the PointerConstraints and sets it up directly. As an alternative this
42 * can also be done in a more low level way:
43 * @code
44 * PointerConstraints *c = new PointerConstraints;
45 * c->setup(registry->bindPointerConstraints(name, version));
46 * @endcode
47 *
48 * The PointerConstraints can be used as a drop-in replacement for any zwp_pointer_constraints_v1
49 * pointer as it provides matching cast operators.
50 *
51 * @see Registry
52 * @since 5.29
53 **/
54class KWAYLANDCLIENT_EXPORT PointerConstraints : public QObject
55{
56 Q_OBJECT
57public:
58 /**
59 * Creates a new PointerConstraints.
60 * Note: after constructing the PointerConstraints it is not yet valid and one needs
61 * to call setup. In order to get a ready to use PointerConstraints prefer using
62 * Registry::createPointerConstraints.
63 **/
64 explicit PointerConstraints(QObject *parent = nullptr);
65 ~PointerConstraints() override;
66
67 /**
68 * Setup this PointerConstraints to manage the @p pointerconstraints.
69 * When using Registry::createPointerConstraints there is no need to call this
70 * method.
71 **/
72 void setup(zwp_pointer_constraints_v1 *pointerconstraints);
73 /**
74 * @returns @c true if managing a zwp_pointer_constraints_v1.
75 **/
76 bool isValid() const;
77 /**
78 * Releases the zwp_pointer_constraints_v1 interface.
79 * After the interface has been released the PointerConstraints instance is no
80 * longer valid and can be setup with another zwp_pointer_constraints_v1 interface.
81 **/
82 void release();
83 /**
84 * Destroys the data held by this PointerConstraints.
85 * This method is supposed to be used when the connection to the Wayland
86 * server goes away. If the connection is not valid anymore, it's not
87 * possible to call release anymore as that calls into the Wayland
88 * connection and the call would fail. This method cleans up the data, so
89 * that the instance can be deleted or set up to a new zwp_pointer_constraints_v1 interface
90 * once there is a new connection available.
91 *
92 * It is suggested to connect this method to ConnectionThread::connectionDied:
93 * @code
94 * connect(connection, &ConnectionThread::connectionDied, pointerconstraints, &PointerConstraints::destroy);
95 * @endcode
96 *
97 * @see release
98 **/
99 void destroy();
100
101 /**
102 * Sets the @p queue to use for creating objects with this PointerConstraints.
103 **/
104 void setEventQueue(EventQueue *queue);
105 /**
106 * @returns The event queue to use for creating objects with this PointerConstraints.
107 **/
108 EventQueue *eventQueue();
109
110 /**
111 * These values represent different lifetime semantics. They are passed
112 * as arguments to the factory requests to specify how the constraint
113 * lifetimes should be managed.
114 * @see lockPointer
115 * @see confinePointer
116 **/
117 enum class LifeTime {
118 /**
119 * A OneShot pointer constraint will never reactivate once it has been
120 * deactivated.
121 **/
122 OneShot,
123 /**
124 * A persistent pointer constraint may again reactivate once it has
125 * been deactivated.
126 **/
127 Persistent,
128 };
129
130 /**
131 * This factory method creates a LockedPointer.
132 *
133 * A LockedPointer lets the client request to disable movements of
134 * the virtual pointer (i.e. the cursor), effectively locking the pointer
135 * to a position.
136 *
137 * Creating a LockedPointer does not lock the pointer immediately; in the
138 * future, when the compositor deems implementation-specific constraints
139 * are satisfied, the pointer lock will be activated and the compositor
140 * sends a locked event, reported by {@link LockedPointer::locked}.
141 *
142 * The protocol provides no guarantee that the constraints are ever
143 * satisfied, and does not require the compositor to send an error if the
144 * constraints cannot ever be satisfied. It is thus possible to request a
145 * lock that will never activate.
146 *
147 * There may not be another pointer constraint of any kind requested or
148 * active on the @p surface for any of the Pointer objects of the Seat of
149 * the passed @p pointer when requesting a lock. If there is, an error will be
150 * raised.
151 *
152 * The intersection of the @p region passed with this request and the input
153 * region of the @p surface is used to determine where the pointer must be
154 * in order for the lock to activate. It is up to the compositor whether to
155 * warp the pointer or require some kind of user interaction for the lock
156 * to activate. If the @p region is null the surface input region is used.
157 *
158 * A Surface may receive pointer focus without the lock being activated.
159 *
160 * Note that while a pointer is locked, the Pointer objects of the
161 * corresponding seat will not emit any {@link Pointer::motion} signals, but
162 * relative motion events will still be emitted via {@link RelativePointer::relativeMotion}.
163 * Pointer axis and button events are unaffected.
164 *
165 * @param surface The Surface which should be constrained in pointer motion
166 * @param pointer The Pointer object for which this LockedPointer should be created
167 * @param region Region where to lock the pointer, if @c null the input region of the Surface is used
168 * @param lifetime Whether the LockedPointer becomes invalid on unlocked
169 * @param parent The parent object for the LockedPointer
170 * @returns The factored LockedPointer
171 **/
172 LockedPointer *lockPointer(Surface *surface, Pointer *pointer, Region *region, LifeTime lifetime, QObject *parent = nullptr);
173
174 /**
175 * This factory method creates a ConfinedPointer.
176 *
177 * A ConfinedPointer lets the client request to confine the
178 * pointer cursor to a given @p region. Creating a ConfinedPointer
179 * does not take effect immediately; in the future, when the compositor
180 * deems implementation-specific constraints are satisfied, the pointer
181 * confinement will be activated and the compositor sends a confined event,
182 * which is reported through the {@link ConfinedPointer::confined} signal.
183 *
184 * The intersection of the @p region passed and the input region of the
185 * @p surface is used to determine where the pointer must be
186 * in order for the confinement to activate. It is up to the compositor
187 * whether to warp the pointer or require some kind of user interaction for
188 * the confinement to activate. If the @p region is @c null the @p surface input
189 * region is used.
190 *
191 * @param surface The Surface which should be constrained in pointer motion
192 * @param pointer The Pointer object for which this LockedPointer should be created
193 * @param region Region where to confine the pointer, if @c null the input region of the Surface is used
194 * @param lifetime Whether the ConfinedPointer becomes invalid on unconfined
195 * @param parent The parent object for the ConfinedPointer
196 * @returns The factored ConfinedPointer
197 **/
198 ConfinedPointer *confinePointer(Surface *surface, Pointer *pointer, Region *region, LifeTime lifetime, QObject *parent = nullptr);
199
200 operator zwp_pointer_constraints_v1 *();
201 operator zwp_pointer_constraints_v1 *() const;
202
203Q_SIGNALS:
204 /**
205 * The corresponding global for this interface on the Registry got removed.
206 *
207 * This signal gets only emitted if the PointerConstraints got created by
208 * Registry::createPointerConstraints
209 **/
210 void removed();
211
212private:
213 class Private;
214 QScopedPointer<Private> d;
215};
216
217/**
218 * @short Wrapper for the zwp_locked_pointer_v1 interface.
219 *
220 * The LockedPointer represents a locked pointer state.
221 *
222 * While the lock of this object is active, the Pointer objects of the
223 * associated seat will not emit any {@link Pointer::motion} events.
224 *
225 * This object will send the signal locked when the lock is activated.
226 * Whenever the lock is activated, it is guaranteed that the locked surface
227 * will already have received pointer focus and that the pointer will be
228 * within the region passed to the request creating this object.
229 *
230 * To unlock the pointer, delete the object.
231 *
232 * If the compositor decides to unlock the pointer the unlocked signal is
233 * emitted.
234 *
235 * When unlocking, the compositor may warp the cursor position to the set
236 * cursor position hint. If it does, it will not result in any relative
237 * motion events emitted via {@link RelativePointer::relativeMotion}.
238 *
239 * If the Surface the lock was requested on is destroyed and the lock is not
240 * yet activated, the LockedPointer object is now defunct and must be
241 * deleted.
242 *
243 * @see PointerConstraints::lockedPointer
244 * @since 5.29
245 **/
246class KWAYLANDCLIENT_EXPORT LockedPointer : public QObject
247{
248 Q_OBJECT
249public:
250 ~LockedPointer() override;
251
252 /**
253 * Setup this LockedPointer to manage the @p lockedpointer.
254 * When using PointerConstraints::createLockedPointer there is no need to call this
255 * method.
256 **/
257 void setup(zwp_locked_pointer_v1 *lockedpointer);
258 /**
259 * @returns @c true if managing a zwp_locked_pointer_v1.
260 **/
261 bool isValid() const;
262 /**
263 * Releases the zwp_locked_pointer_v1 interface.
264 * After the interface has been released the LockedPointer instance is no
265 * longer valid and can be setup with another zwp_locked_pointer_v1 interface.
266 **/
267 void release();
268 /**
269 * Destroys the data held by this LockedPointer.
270 * This method is supposed to be used when the connection to the Wayland
271 * server goes away. If the connection is not valid anymore, it's not
272 * possible to call release anymore as that calls into the Wayland
273 * connection and the call would fail. This method cleans up the data, so
274 * that the instance can be deleted or set up to a new zwp_locked_pointer_v1 interface
275 * once there is a new connection available.
276 *
277 * It is suggested to connect this method to ConnectionThread::connectionDied:
278 * @code
279 * connect(connection, &ConnectionThread::connectionDied, lockedpointer, &LockedPointer::destroy);
280 * @endcode
281 *
282 * @see release
283 **/
284 void destroy();
285
286 /**
287 * Set the cursor position hint relative to the top left corner of the Surface.
288 *
289 * If the client is drawing its own cursor, it should update the position
290 * hint to the position of its own cursor. A compositor may use this
291 * information to warp the pointer upon unlock in order to avoid pointer
292 * jumps.
293 *
294 * The cursor position hint is double buffered. The new hint will only take
295 * effect when the associated surface gets it pending state applied.
296 * See {@link Surface::commit} for details.
297 *
298 * @param surfaceLocal The new position hint in surface local coordinates
299 * @see Surface::commit
300 **/
301 void setCursorPositionHint(const QPointF &surfaceLocal);
302
303 /**
304 * Set a new region used to lock the pointer.
305 *
306 * The new lock region is double-buffered. The new lock region will
307 * only take effect when the associated Surface gets its pending state
308 * applied. See {@link Surface::commit} for details.
309 *
310 * @param region The new lock region.
311 * @see Surface::commit
312 * @see PointerConstraints::lockPointer
313 **/
314 void setRegion(Region *region);
315
316 operator zwp_locked_pointer_v1 *();
317 operator zwp_locked_pointer_v1 *() const;
318
319Q_SIGNALS:
320 /**
321 * Notification that the pointer lock of the seat's pointer is activated.
322 * @see unlocked
323 **/
324 void locked();
325
326 /**
327 * Notification that the pointer lock of the seat's pointer is no longer
328 * active. If this is a oneshot pointer lock (see
329 * wp_pointer_constraints.lifetime) this object is now defunct and should
330 * be destroyed. If this is a persistent pointer lock (see
331 * wp_pointer_constraints.lifetime) this pointer lock may again
332 * reactivate in the future.
333 * @see locked
334 **/
335 void unlocked();
336
337private:
338 friend class PointerConstraints;
339 explicit LockedPointer(QObject *parent = nullptr);
340 class Private;
341 QScopedPointer<Private> d;
342};
343
344/**
345 * @short Wrapper for zwp_confined_pointer_v1 protocol
346 * The confine pointer interface represents a confined pointer state.
347 *
348 * This object will send the signal 'confined' when the confinement is
349 * activated. Whenever the confinement is activated, it is guaranteed that
350 * the surface the pointer is confined to will already have received pointer
351 * focus and that the pointer will be within the region passed to the request
352 * creating this object. It is up to the compositor to decide whether this
353 * requires some user interaction and if the pointer will warp to within the
354 * passed region if outside.
355 *
356 * To unconfine the pointer, delete the object.
357 *
358 * If the compositor decides to unconfine the pointer the unconfined signal is
359 * emitted. The ConfinedPointer object is at this point defunct and should
360 * be deleted.
361 * @see PointerConstraints::confinePointer
362 * @since 5.29
363 **/
364class KWAYLANDCLIENT_EXPORT ConfinedPointer : public QObject
365{
366 Q_OBJECT
367public:
368 ~ConfinedPointer() override;
369
370 /**
371 * Setup this ConfinedPointer to manage the @p confinedpointer.
372 * When using PointerConstraints::createConfinedPointer there is no need to call this
373 * method.
374 **/
375 void setup(zwp_confined_pointer_v1 *confinedpointer);
376 /**
377 * @returns @c true if managing a zwp_confined_pointer_v1.
378 **/
379 bool isValid() const;
380 /**
381 * Releases the zwp_confined_pointer_v1 interface.
382 * After the interface has been released the ConfinedPointer instance is no
383 * longer valid and can be setup with another zwp_confined_pointer_v1 interface.
384 **/
385 void release();
386 /**
387 * Destroys the data held by this ConfinedPointer.
388 * This method is supposed to be used when the connection to the Wayland
389 * server goes away. If the connection is not valid anymore, it's not
390 * possible to call release anymore as that calls into the Wayland
391 * connection and the call would fail. This method cleans up the data, so
392 * that the instance can be deleted or set up to a new zwp_confined_pointer_v1 interface
393 * once there is a new connection available.
394 *
395 * This method is automatically invoked when the Registry which created this
396 * PointerConstraints gets destroyed.
397 *
398 * @see release
399 **/
400 void destroy();
401
402 /**
403 * Set a new region used to confine the pointer.
404 *
405 * The new confine region is double-buffered. The new confine region will
406 * only take effect when the associated Surface gets its pending state
407 * applied. See {@link Surface::commit} for details.
408 *
409 * If the confinement is active when the new confinement region is applied
410 * and the pointer ends up outside of newly applied region, the pointer may
411 * warped to a position within the new confinement region. If warped, a
412 * {@link Pointer::motion} signal will be emitted, but no
413 * {@link RelativePointer::relativeMotion} signal.
414 *
415 * The compositor may also, instead of using the new region, unconfine the
416 * pointer.
417 *
418 * @param region The new confine region.
419 * @see Surface::commit
420 * @see PointerConstraints::confinePointer
421 **/
422 void setRegion(Region *region);
423
424 operator zwp_confined_pointer_v1 *();
425 operator zwp_confined_pointer_v1 *() const;
426
427Q_SIGNALS:
428 /**
429 * Notification that the pointer confinement of the seat's pointer is activated.
430 * @see unconfined
431 **/
432 void confined();
433
434 /**
435 * Notification that the pointer confinement of the seat's pointer is no
436 * longer active. If this is a oneshot pointer confinement (see
437 * wp_pointer_constraints.lifetime) this object is now defunct and should
438 * be destroyed. If this is a persistent pointer confinement (see
439 * wp_pointer_constraints.lifetime) this pointer confinement may again
440 * reactivate in the future.
441 * @see confined
442 **/
443 void unconfined();
444
445private:
446 friend class PointerConstraints;
447 explicit ConfinedPointer(QObject *parent = nullptr);
448 class Private;
449 QScopedPointer<Private> d;
450};
451
452}
453}
454
455#endif
456

source code of kwayland/src/client/pointerconstraints.h