KWin
Loading...
Searching...
No Matches
pointerconstraints_v1.cpp
Go to the documentation of this file.
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
9#include "display.h"
10#include "pointer.h"
12#include "region_p.h"
13#include "surface_p.h"
14
15namespace KWin
16{
17static const int s_version = 1;
18
19static QRegion mapScaleOverride(const QRegion &region, qreal scaleOverride)
20{
21 QRegion out;
22 for (const QRect &rect : region) {
23 out += QRect(rect.topLeft() / scaleOverride, rect.size() / scaleOverride);
24 }
25 return out;
26}
27
29 : QtWaylandServer::zwp_pointer_constraints_v1(*display, s_version)
30{
31}
32
33static QRegion regionFromResource(::wl_resource *resource)
34{
35 const RegionInterface *region = RegionInterface::get(resource);
36 return region ? region->region() : QRegion();
37}
38
40 uint32_t id,
41 ::wl_resource *surface_resource,
42 ::wl_resource *pointer_resource,
43 ::wl_resource *region_resource,
44 uint32_t lifetime)
45{
46 PointerInterface *pointer = PointerInterface::get(pointer_resource);
47 if (!pointer) {
48 wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT, "invalid pointer");
49 return;
50 }
51
52 SurfaceInterface *surface = SurfaceInterface::get(surface_resource);
53 if (!surface) {
54 wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT, "invalid surface");
55 return;
56 }
57
58 if (surface->lockedPointer() || surface->confinedPointer()) {
59 wl_resource_post_error(resource->handle, error_already_constrained, "the surface is already constrained");
60 return;
61 }
62
63 if (lifetime != lifetime_oneshot && lifetime != lifetime_persistent) {
64 wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT, "unknown lifetime %d", lifetime);
65 return;
66 }
67
68 wl_resource *lockedPointerResource = wl_resource_create(resource->client(), &zwp_locked_pointer_v1_interface, resource->version(), id);
69 if (!lockedPointerResource) {
70 wl_resource_post_no_memory(resource->handle);
71 return;
72 }
73
74 new LockedPointerV1Interface(surface, LockedPointerV1Interface::LifeTime(lifetime), regionFromResource(region_resource), lockedPointerResource);
75}
76
78 uint32_t id,
79 ::wl_resource *surface_resource,
80 ::wl_resource *pointer_resource,
81 ::wl_resource *region_resource,
82 uint32_t lifetime)
83{
84 PointerInterface *pointer = PointerInterface::get(pointer_resource);
85 if (!pointer) {
86 wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT, "invalid pointer");
87 return;
88 }
89
90 SurfaceInterface *surface = SurfaceInterface::get(surface_resource);
91 if (!surface) {
92 wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT, "invalid surface");
93 return;
94 }
95
96 if (lifetime != lifetime_oneshot && lifetime != lifetime_persistent) {
97 wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT, "unknown lifetime %d", lifetime);
98 return;
99 }
100
101 if (surface->lockedPointer() || surface->confinedPointer()) {
102 wl_resource_post_error(resource->handle, error_already_constrained, "the surface is already constrained");
103 return;
104 }
105
106 wl_resource *confinedPointerResource = wl_resource_create(resource->client(), &zwp_confined_pointer_v1_interface, resource->version(), id);
107 if (!confinedPointerResource) {
108 wl_resource_post_no_memory(resource->handle);
109 return;
110 }
111
112 new ConfinedPointerV1Interface(surface, ConfinedPointerV1Interface::LifeTime(lifetime), regionFromResource(region_resource), confinedPointerResource);
113}
114
116{
117 wl_resource_destroy(resource->handle);
118}
119
121 : QObject(parent)
123{
124}
125
129
134
136 SurfaceInterface *surface,
138 const QRegion &region,
139 ::wl_resource *resource)
140 : QtWaylandServer::zwp_locked_pointer_v1(resource)
141 , SurfaceExtension(surface)
142 , q(q)
143 , surface(surface)
144 , lifeTime(lifeTime)
145{
147
148 apply(&pending);
149
151}
152
154{
155 const QRegion oldRegion = effectiveRegion;
156 const QPointF oldHint = hint;
157
158 if (commit->region.has_value()) {
159 region = mapScaleOverride(commit->region.value(), surface->scaleOverride());
160 }
161 if (commit->hint.has_value()) {
162 hint = commit->hint.value() / surface->scaleOverride();
163 }
164
165 effectiveRegion = surface->input();
166 if (!region.isEmpty()) {
168 }
169
170 if (oldRegion != effectiveRegion) {
171 Q_EMIT q->regionChanged();
172 }
173 if (oldHint != hint) {
175 }
176}
177
179{
180 Q_EMIT q->aboutToBeDestroyed();
181 delete q;
182}
183
185{
186 wl_resource_destroy(resource->handle);
187}
188
189void LockedPointerV1InterfacePrivate::zwp_locked_pointer_v1_set_cursor_position_hint(Resource *resource, wl_fixed_t surface_x, wl_fixed_t surface_y)
190{
191 pending.hint = QPointF(wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y));
192}
193
194void LockedPointerV1InterfacePrivate::zwp_locked_pointer_v1_set_region(Resource *resource, ::wl_resource *region_resource)
195{
196 pending.region = regionFromResource(region_resource);
197}
198
199LockedPointerV1Interface::LockedPointerV1Interface(SurfaceInterface *surface,
200 LifeTime lifeTime,
201 const QRegion &region,
202 ::wl_resource *resource)
203 : d(new LockedPointerV1InterfacePrivate(this, surface, lifeTime, region, resource))
204{
206}
207
211
216
218{
219 return d->effectiveRegion;
220}
221
223{
224 return d->hint;
225}
226
228{
229 return d->isLocked;
230}
231
233{
234 if (d->isLocked == locked) {
235 return;
236 }
237 if (!locked) {
238 d->hint = QPointF(-1, -1);
239 }
240 d->isLocked = locked;
241 if (d->isLocked) {
242 d->send_locked();
243 } else {
244 d->send_unlocked();
245 }
246 Q_EMIT lockedChanged();
247}
248
253
255 SurfaceInterface *surface,
257 const QRegion &region,
258 ::wl_resource *resource)
259 : QtWaylandServer::zwp_confined_pointer_v1(resource)
260 , SurfaceExtension(surface)
261 , q(q)
262 , surface(surface)
263 , lifeTime(lifeTime)
264{
266
267 apply(&pending);
268
270}
271
273{
274 const QRegion oldRegion = effectiveRegion;
275
276 if (commit->region.has_value()) {
277 region = mapScaleOverride(commit->region.value(), surface->scaleOverride());
278 }
279
280 effectiveRegion = surface->input();
281 if (!region.isEmpty()) {
283 }
284
285 if (oldRegion != effectiveRegion) {
286 Q_EMIT q->regionChanged();
287 }
288}
289
294
296{
297 wl_resource_destroy(resource->handle);
298}
299
300void ConfinedPointerV1InterfacePrivate::zwp_confined_pointer_v1_set_region(Resource *resource, ::wl_resource *region_resource)
301{
302 pending.region = regionFromResource(region_resource);
303}
304
305ConfinedPointerV1Interface::ConfinedPointerV1Interface(SurfaceInterface *surface,
306 LifeTime lifeTime,
307 const QRegion &region,
308 ::wl_resource *resource)
309 : d(new ConfinedPointerV1InterfacePrivate(this, surface, lifeTime, region, resource))
310{
312}
313
317
322
324{
325 return d->effectiveRegion;
326}
327
329{
330 return d->isConfined;
331}
332
334{
335 if (d->isConfined == confined) {
336 return;
337 }
338 d->isConfined = confined;
339 if (d->isConfined) {
340 d->send_confined();
341 } else {
342 d->send_unconfined();
343 }
344 Q_EMIT confinedChanged();
345}
346
347} // namespace KWin
348
349#include "moc_pointerconstraints_v1.cpp"
static ConfinedPointerV1InterfacePrivate * get(ConfinedPointerV1Interface *pointer)
void zwp_confined_pointer_v1_set_region(Resource *resource, struct ::wl_resource *region_resource) override
void zwp_confined_pointer_v1_destroy(Resource *resource) override
void apply(ConfinedPointerV1Commit *commit) override
ConfinedPointerV1InterfacePrivate(ConfinedPointerV1Interface *q, SurfaceInterface *surface, ConfinedPointerV1Interface::LifeTime lifeTime, const QRegion &region, ::wl_resource *resource)
void zwp_confined_pointer_v1_destroy_resource(Resource *resource) override
Class holding the Wayland server display loop.
Definition display.h:34
void zwp_locked_pointer_v1_destroy(Resource *resource) override
void zwp_locked_pointer_v1_set_region(Resource *resource, struct ::wl_resource *region_resource) override
void zwp_locked_pointer_v1_destroy_resource(Resource *resource) override
LockedPointerV1InterfacePrivate(LockedPointerV1Interface *q, SurfaceInterface *surface, LockedPointerV1Interface::LifeTime lifeTime, const QRegion &region, ::wl_resource *resource)
void apply(LockedPointerV1Commit *commit) override
void zwp_locked_pointer_v1_set_cursor_position_hint(Resource *resource, wl_fixed_t surface_x, wl_fixed_t surface_y) override
static LockedPointerV1InterfacePrivate * get(LockedPointerV1Interface *pointer)
PointerConstraintsV1Interface(Display *display, QObject *parent=nullptr)
void zwp_pointer_constraints_v1_lock_pointer(Resource *resource, uint32_t id, struct ::wl_resource *surface_resource, struct ::wl_resource *pointer_resource, struct ::wl_resource *region_resource, uint32_t lifetime) override
void zwp_pointer_constraints_v1_destroy(Resource *resource) override
void zwp_pointer_constraints_v1_confine_pointer(Resource *resource, uint32_t id, struct ::wl_resource *surface_resource, struct ::wl_resource *pointer_resource, struct ::wl_resource *region_resource, uint32_t lifetime) override
static PointerInterface * get(wl_resource *native)
Definition pointer.cpp:370
static RegionInterface * get(wl_resource *native)
Definition region.cpp:42
QRegion region() const
Definition region.cpp:37
Resource representing a wl_surface.
Definition surface.h:80
static SurfaceInterface * get(wl_resource *native)
Definition surface.cpp:819
ConfinedPointerV1Interface * confinedPointer() const
Definition surface.cpp:1019
LockedPointerV1Interface * lockedPointer() const
Definition surface.cpp:1014
static SurfaceInterfacePrivate * get(SurfaceInterface *surface)
Definition surface_p.h:99
void installPointerConstraint(LockedPointerV1Interface *lock)
Definition surface.cpp:201
std::optional< QRegion > region