1 /*
2     SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
3     SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
4 
5     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6 */
7 
8 #pragma once
9 
10 #include <KWaylandServer/kwaylandserver_export.h>
11 
12 #include <QObject>
13 #include <QRegion>
14 
15 struct wl_resource;
16 
17 namespace KWaylandServer
18 {
19 class ConfinedPointerV1InterfacePrivate;
20 class Display;
21 class LockedPointerV1InterfacePrivate;
22 class PointerConstraintsV1InterfacePrivate;
23 class SurfaceInterface;
24 
25 /**
26  * Manager object to create pointer constraints.
27  *
28  * To create this manager use {@link Display::createPointerConstraintsV1}
29  *
30  * @see ConfinedPointerV1Interface
31  * @see LockedPointerV1Interface
32  */
33 class KWAYLANDSERVER_EXPORT PointerConstraintsV1Interface : public QObject
34 {
35     Q_OBJECT
36 
37 public:
38     explicit PointerConstraintsV1Interface(Display *display, QObject *parent = nullptr);
39     ~PointerConstraintsV1Interface() override;
40 
41 private:
42     QScopedPointer<PointerConstraintsV1InterfacePrivate> d;
43 };
44 
45 /**
46  * The LockedPointerV1Interface lets the client request to disable movements of
47  * the virtual pointer (i.e. the cursor), effectively locking the pointer
48  * to a position.
49  *
50  * It is up to the compositor whether the lock gets activated.
51  * To activate it needs to use {@link LockedPointerV1Interface::setLocked}.
52  * The compositor needs to ensure that the SurfaceInterface has pointer focus
53  * and that the pointer is inside the {@link LockedPointerV1Interface::region} when
54  * it activates the lock.
55  *
56  * While the lock is active the PointerInterface does no longer Q_EMIT pointer motion
57  * events, but still emits relative pointer motion events.
58  */
59 class KWAYLANDSERVER_EXPORT LockedPointerV1Interface : public QObject
60 {
61     Q_OBJECT
62 
63 public:
64     ~LockedPointerV1Interface() override;
65 
66     enum class LifeTime : uint {
67         OneShot = 1,
68         Persistent = 2,
69     };
70 
71     LifeTime lifeTime() const;
72 
73     /**
74      * The intersection of this region and the input region of the SurfaceInterface is used
75      * to determine where the pointer must be in order for the lock to activate.
76      * It is up to the compositor whether to warp the pointer or require some kind of
77      * user interaction for the lock to activate.
78      *
79      * If the region is empty the SurfaceInterface input region is used.
80      *
81      * @see regionChanged
82      * @see SurfaceInterface::input
83      */
84     QRegion region() const;
85 
86     /**
87      * Indicates where the mouse cursor should be positioned after it has been unlocked again.
88      * The compositor can warp the cursor at this moment to the position. For that it
89      * will not Q_EMIT any relative motion events. The hint is relative to the top-left
90      * corner of the surface the lock was applied to. Only non-negative x and y values
91      * are allowed. Otherwise the hint is invalid and should be ignored by the compositor.
92      *
93      * In case the client never set the hint, an invalid one will be returned.
94      *
95      * This function should be called when the compositor decides to break the lock or the
96      * client unbinds the resource. To set the position in this case the compositor should
97      * call this function when the aboutToBeUnbound signal has been emitted.
98      *
99      * @see cursorPositionHintChanged
100      */
101     QPointF cursorPositionHint() const;
102 
103     /**
104      * Whether the Compositor set this pointer lock to be active.
105      * @see setLocked
106      * @see lockedChanged
107      */
108     bool isLocked() const;
109 
110     /**
111      * Activates or deactivates the lock.
112      *
113      * A pointer lock can only be activated if the SurfaceInterface
114      * this LockedPointerV1Interface was created for has pointer focus
115      * and the pointer is inside the {@link region}.
116      *
117      * Unlocking resets the cursor position hint.
118      *
119      * @param locked Whether the lock should be active
120      * @see isLocked
121      * @see lockedChanged
122      */
123     void setLocked(bool locked);
124 
125 Q_SIGNALS:
126     /**
127      * This is signal is emitted when the locked pointer is about to be destroyed.
128      */
129     void aboutToBeDestroyed();
130 
131     /**
132      * Emitted whenever the region changes.
133      * This happens when the parent SurfaceInterface gets committed
134      * @see region
135      */
136     void regionChanged();
137 
138     /**
139      * Emitted whenever the cursor position hint changes.
140      * This happens when the parent SurfaceInterface gets committed
141      * @see cursorPositionHint
142      */
143     void cursorPositionHintChanged();
144 
145     /**
146      * Emitted whenever the {@link isLocked} state changes.
147      * @see isLocked
148      * @see setLocked
149      */
150     void lockedChanged();
151 
152 private:
153     LockedPointerV1Interface(LifeTime lifeTime, const QRegion &region, ::wl_resource *resource);
154     QScopedPointer<LockedPointerV1InterfacePrivate> d;
155     friend class LockedPointerV1InterfacePrivate;
156     friend class PointerConstraintsV1InterfacePrivate;
157 };
158 
159 /**
160  *
161  * The ConfinedPointerV1Interface gets installed on a SurfaceInterface.
162  * The confinement indicates that the SurfaceInterface wants to confine the
163  * pointer to a region of the SurfaceInterface.
164  *
165  * It is up to the compositor whether the confinement gets activated.
166  * To activate it needs to use {@link ConfinedPointerV1Interface::setConfined}.
167  * The compositor needs to ensure that the SurfaceInterface has pointer focus
168  * and that the pointer is inside the {@link ConfinedPointerV1Interface::region} when
169  * it activates the confinement.
170  *
171  * From client side the confinement gets deactivated by destroying the ConfinedPointerV1Interface.
172  * From compositor side the confinement can be deactivated by setting
173  * {@link ConfinedPointerV1Interface::setConfined} to @c false.
174  */
175 class KWAYLANDSERVER_EXPORT ConfinedPointerV1Interface : public QObject
176 {
177     Q_OBJECT
178 
179 public:
180     ~ConfinedPointerV1Interface() override;
181 
182     enum class LifeTime : uint {
183         OneShot = 1,
184         Persistent = 2,
185     };
186 
187     LifeTime lifeTime() const;
188 
189     /**
190      * The intersection of this region and the input region of the SurfaceInterface is used
191      * to determine where the pointer must be in order for the confinement to activate.
192      * It is up to the compositor whether to warp the pointer or require some kind of
193      * user interaction for the confinement to activate.
194      *
195      * If the region is empty the SurfaceInterface input region is used.
196      *
197      * @see regionChanged
198      * @see SurfaceInterface::input
199      */
200     QRegion region() const;
201 
202     /**
203      * Whether the Compositor set this pointer confinement to be active.
204      * @see setConfined
205      * @see confinedChanged
206      */
207     bool isConfined() const;
208 
209     /**
210      * Activates or deactivates the confinement.
211      *
212      * A pointer confinement can only be activated if the SurfaceInterface
213      * this ConfinedPointerV1Interface was created for has pointer focus
214      * and the pointer is inside the {@link region}.
215      *
216      * @param confined Whether the confinement should be active
217      * @see isConfined
218      * @see confinedChanged
219      */
220     void setConfined(bool confined);
221 
222 Q_SIGNALS:
223     /**
224      * Emitted whenever the region changes.
225      * This happens when the parent SurfaceInterface gets committed
226      * @see region
227      */
228     void regionChanged();
229 
230     /**
231      * Emitted whenever the {@link isConfined} state changes.
232      * @see isConfined
233      * @see setConfined
234      */
235     void confinedChanged();
236 
237 private:
238     ConfinedPointerV1Interface(LifeTime lifeTime, const QRegion &region, ::wl_resource *resource);
239     QScopedPointer<ConfinedPointerV1InterfacePrivate> d;
240     friend class ConfinedPointerV1InterfacePrivate;
241     friend class PointerConstraintsV1InterfacePrivate;
242 };
243 
244 } // namespace KWaylandServer
245