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 #include "pointerconstraints_v1_interface.h"
9 #include "display.h"
10 #include "pointer_interface.h"
11 #include "pointerconstraints_v1_interface_p.h"
12 #include "region_interface_p.h"
13 #include "surface_interface_p.h"
14
15 namespace KWaylandServer
16 {
17 static const int s_version = 1;
18
PointerConstraintsV1InterfacePrivate(Display * display)19 PointerConstraintsV1InterfacePrivate::PointerConstraintsV1InterfacePrivate(Display *display)
20 : QtWaylandServer::zwp_pointer_constraints_v1(*display, s_version)
21 {
22 }
23
regionFromResource(::wl_resource * resource)24 static QRegion regionFromResource(::wl_resource *resource)
25 {
26 const RegionInterface *region = RegionInterface::get(resource);
27 return region ? region->region() : QRegion();
28 }
29
zwp_pointer_constraints_v1_lock_pointer(Resource * resource,uint32_t id,::wl_resource * surface_resource,::wl_resource * pointer_resource,::wl_resource * region_resource,uint32_t lifetime)30 void PointerConstraintsV1InterfacePrivate::zwp_pointer_constraints_v1_lock_pointer(Resource *resource,
31 uint32_t id,
32 ::wl_resource *surface_resource,
33 ::wl_resource *pointer_resource,
34 ::wl_resource *region_resource,
35 uint32_t lifetime)
36 {
37 PointerInterface *pointer = PointerInterface::get(pointer_resource);
38 if (!pointer) {
39 wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT, "invalid pointer");
40 return;
41 }
42
43 SurfaceInterface *surface = SurfaceInterface::get(surface_resource);
44 if (!surface) {
45 wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT, "invalid surface");
46 return;
47 }
48
49 if (surface->lockedPointer() || surface->confinedPointer()) {
50 wl_resource_post_error(resource->handle, error_already_constrained, "the surface is already constrained");
51 return;
52 }
53
54 if (lifetime != lifetime_oneshot && lifetime != lifetime_persistent) {
55 wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT, "unknown lifetime %d", lifetime);
56 return;
57 }
58
59 wl_resource *lockedPointerResource = wl_resource_create(resource->client(), &zwp_locked_pointer_v1_interface, resource->version(), id);
60 if (!lockedPointerResource) {
61 wl_resource_post_no_memory(resource->handle);
62 return;
63 }
64
65 auto lockedPointer = new LockedPointerV1Interface(LockedPointerV1Interface::LifeTime(lifetime), regionFromResource(region_resource), lockedPointerResource);
66
67 SurfaceInterfacePrivate::get(surface)->installPointerConstraint(lockedPointer);
68 }
69
zwp_pointer_constraints_v1_confine_pointer(Resource * resource,uint32_t id,::wl_resource * surface_resource,::wl_resource * pointer_resource,::wl_resource * region_resource,uint32_t lifetime)70 void PointerConstraintsV1InterfacePrivate::zwp_pointer_constraints_v1_confine_pointer(Resource *resource,
71 uint32_t id,
72 ::wl_resource *surface_resource,
73 ::wl_resource *pointer_resource,
74 ::wl_resource *region_resource,
75 uint32_t lifetime)
76 {
77 PointerInterface *pointer = PointerInterface::get(pointer_resource);
78 if (!pointer) {
79 wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT, "invalid pointer");
80 return;
81 }
82
83 SurfaceInterface *surface = SurfaceInterface::get(surface_resource);
84 if (!surface) {
85 wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT, "invalid surface");
86 return;
87 }
88
89 if (lifetime != lifetime_oneshot && lifetime != lifetime_persistent) {
90 wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT, "unknown lifetime %d", lifetime);
91 return;
92 }
93
94 if (surface->lockedPointer() || surface->confinedPointer()) {
95 wl_resource_post_error(resource->handle, error_already_constrained, "the surface is already constrained");
96 return;
97 }
98
99 wl_resource *confinedPointerResource = wl_resource_create(resource->client(), &zwp_confined_pointer_v1_interface, resource->version(), id);
100 if (!confinedPointerResource) {
101 wl_resource_post_no_memory(resource->handle);
102 return;
103 }
104
105 auto confinedPointer =
106 new ConfinedPointerV1Interface(ConfinedPointerV1Interface::LifeTime(lifetime), regionFromResource(region_resource), confinedPointerResource);
107
108 SurfaceInterfacePrivate::get(surface)->installPointerConstraint(confinedPointer);
109 }
110
zwp_pointer_constraints_v1_destroy(Resource * resource)111 void PointerConstraintsV1InterfacePrivate::zwp_pointer_constraints_v1_destroy(Resource *resource)
112 {
113 wl_resource_destroy(resource->handle);
114 }
115
PointerConstraintsV1Interface(Display * display,QObject * parent)116 PointerConstraintsV1Interface::PointerConstraintsV1Interface(Display *display, QObject *parent)
117 : QObject(parent)
118 , d(new PointerConstraintsV1InterfacePrivate(display))
119 {
120 }
121
~PointerConstraintsV1Interface()122 PointerConstraintsV1Interface::~PointerConstraintsV1Interface()
123 {
124 }
125
get(LockedPointerV1Interface * q)126 LockedPointerV1InterfacePrivate *LockedPointerV1InterfacePrivate::get(LockedPointerV1Interface *q)
127 {
128 return q->d.data();
129 }
130
LockedPointerV1InterfacePrivate(LockedPointerV1Interface * q,LockedPointerV1Interface::LifeTime lifeTime,const QRegion & region,::wl_resource * resource)131 LockedPointerV1InterfacePrivate::LockedPointerV1InterfacePrivate(LockedPointerV1Interface *q,
132 LockedPointerV1Interface::LifeTime lifeTime,
133 const QRegion ®ion,
134 ::wl_resource *resource)
135 : QtWaylandServer::zwp_locked_pointer_v1(resource)
136 , q(q)
137 , lifeTime(lifeTime)
138 , region(region)
139 {
140 }
141
commit()142 void LockedPointerV1InterfacePrivate::commit()
143 {
144 if (hasPendingRegion) {
145 region = pendingRegion;
146 hasPendingRegion = false;
147 Q_EMIT q->regionChanged();
148 }
149 if (hasPendingHint) {
150 hint = pendingHint;
151 hasPendingHint = false;
152 Q_EMIT q->cursorPositionHintChanged();
153 }
154 }
155
zwp_locked_pointer_v1_destroy_resource(Resource * resource)156 void LockedPointerV1InterfacePrivate::zwp_locked_pointer_v1_destroy_resource(Resource *resource)
157 {
158 Q_UNUSED(resource)
159 Q_EMIT q->aboutToBeDestroyed();
160 delete q;
161 }
162
zwp_locked_pointer_v1_destroy(Resource * resource)163 void LockedPointerV1InterfacePrivate::zwp_locked_pointer_v1_destroy(Resource *resource)
164 {
165 wl_resource_destroy(resource->handle);
166 }
167
zwp_locked_pointer_v1_set_cursor_position_hint(Resource * resource,wl_fixed_t surface_x,wl_fixed_t surface_y)168 void LockedPointerV1InterfacePrivate::zwp_locked_pointer_v1_set_cursor_position_hint(Resource *resource, wl_fixed_t surface_x, wl_fixed_t surface_y)
169 {
170 Q_UNUSED(resource)
171 pendingHint = QPointF(wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y));
172 hasPendingHint = true;
173 }
174
zwp_locked_pointer_v1_set_region(Resource * resource,::wl_resource * region_resource)175 void LockedPointerV1InterfacePrivate::zwp_locked_pointer_v1_set_region(Resource *resource, ::wl_resource *region_resource)
176 {
177 Q_UNUSED(resource)
178 pendingRegion = regionFromResource(region_resource);
179 hasPendingRegion = true;
180 }
181
LockedPointerV1Interface(LifeTime lifeTime,const QRegion & region,::wl_resource * resource)182 LockedPointerV1Interface::LockedPointerV1Interface(LifeTime lifeTime, const QRegion ®ion, ::wl_resource *resource)
183 : d(new LockedPointerV1InterfacePrivate(this, lifeTime, region, resource))
184 {
185 }
186
~LockedPointerV1Interface()187 LockedPointerV1Interface::~LockedPointerV1Interface()
188 {
189 }
190
lifeTime() const191 LockedPointerV1Interface::LifeTime LockedPointerV1Interface::lifeTime() const
192 {
193 return d->lifeTime;
194 }
195
region() const196 QRegion LockedPointerV1Interface::region() const
197 {
198 return d->region;
199 }
200
cursorPositionHint() const201 QPointF LockedPointerV1Interface::cursorPositionHint() const
202 {
203 return d->hint;
204 }
205
isLocked() const206 bool LockedPointerV1Interface::isLocked() const
207 {
208 return d->isLocked;
209 }
210
setLocked(bool locked)211 void LockedPointerV1Interface::setLocked(bool locked)
212 {
213 if (d->isLocked == locked) {
214 return;
215 }
216 if (!locked) {
217 d->hint = QPointF(-1, -1);
218 }
219 d->isLocked = locked;
220 if (d->isLocked) {
221 d->send_locked();
222 } else {
223 d->send_unlocked();
224 }
225 Q_EMIT lockedChanged();
226 }
227
get(ConfinedPointerV1Interface * q)228 ConfinedPointerV1InterfacePrivate *ConfinedPointerV1InterfacePrivate::get(ConfinedPointerV1Interface *q)
229 {
230 return q->d.data();
231 }
232
ConfinedPointerV1InterfacePrivate(ConfinedPointerV1Interface * q,ConfinedPointerV1Interface::LifeTime lifeTime,const QRegion & region,::wl_resource * resource)233 ConfinedPointerV1InterfacePrivate::ConfinedPointerV1InterfacePrivate(ConfinedPointerV1Interface *q,
234 ConfinedPointerV1Interface::LifeTime lifeTime,
235 const QRegion ®ion,
236 ::wl_resource *resource)
237 : QtWaylandServer::zwp_confined_pointer_v1(resource)
238 , q(q)
239 , lifeTime(lifeTime)
240 , region(region)
241 {
242 }
243
commit()244 void ConfinedPointerV1InterfacePrivate::commit()
245 {
246 if (hasPendingRegion) {
247 region = pendingRegion;
248 hasPendingRegion = false;
249 Q_EMIT q->regionChanged();
250 }
251 }
252
zwp_confined_pointer_v1_destroy_resource(Resource * resource)253 void ConfinedPointerV1InterfacePrivate::zwp_confined_pointer_v1_destroy_resource(Resource *resource)
254 {
255 Q_UNUSED(resource)
256 delete q;
257 }
258
zwp_confined_pointer_v1_destroy(Resource * resource)259 void ConfinedPointerV1InterfacePrivate::zwp_confined_pointer_v1_destroy(Resource *resource)
260 {
261 wl_resource_destroy(resource->handle);
262 }
263
zwp_confined_pointer_v1_set_region(Resource * resource,::wl_resource * region_resource)264 void ConfinedPointerV1InterfacePrivate::zwp_confined_pointer_v1_set_region(Resource *resource, ::wl_resource *region_resource)
265 {
266 Q_UNUSED(resource)
267 pendingRegion = regionFromResource(region_resource);
268 hasPendingRegion = true;
269 }
270
ConfinedPointerV1Interface(LifeTime lifeTime,const QRegion & region,::wl_resource * resource)271 ConfinedPointerV1Interface::ConfinedPointerV1Interface(LifeTime lifeTime, const QRegion ®ion, ::wl_resource *resource)
272 : d(new ConfinedPointerV1InterfacePrivate(this, lifeTime, region, resource))
273 {
274 }
275
~ConfinedPointerV1Interface()276 ConfinedPointerV1Interface::~ConfinedPointerV1Interface()
277 {
278 }
279
lifeTime() const280 ConfinedPointerV1Interface::LifeTime ConfinedPointerV1Interface::lifeTime() const
281 {
282 return d->lifeTime;
283 }
284
region() const285 QRegion ConfinedPointerV1Interface::region() const
286 {
287 return d->region;
288 }
289
isConfined() const290 bool ConfinedPointerV1Interface::isConfined() const
291 {
292 return d->isConfined;
293 }
294
setConfined(bool confined)295 void ConfinedPointerV1Interface::setConfined(bool confined)
296 {
297 if (d->isConfined == confined) {
298 return;
299 }
300 d->isConfined = confined;
301 if (d->isConfined) {
302 d->send_confined();
303 } else {
304 d->send_unconfined();
305 }
306 Q_EMIT confinedChanged();
307 }
308
309 } // namespace KWaylandServer
310