blob: 2ec5aca302812de51c0605df91a718be8a1446b4 [file] [log] [blame]
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001/*
2 * Copyright © 2013 Intel Corporation
Louis-Francis Ratté-Boulianne6ef59c92017-11-28 20:42:47 -05003 * Copyright 2017-2018 Collabora, Ltd.
4 * Copyright 2017-2018 General Electric Company
Kristian Høgsberg2158a882013-04-18 15:07:39 -04005 *
Bryce Harringtona0bbfea2015-06-11 15:35:43 -07006 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
Kristian Høgsberg2158a882013-04-18 15:07:39 -040013 *
Bryce Harringtona0bbfea2015-06-11 15:35:43 -070014 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
22 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
Kristian Høgsberg2158a882013-04-18 15:07:39 -040026 */
27
Daniel Stone8e7a8bd2013-08-15 01:10:24 +010028#include "config.h"
29
Jonas Ådahld3414f22016-07-22 17:56:31 +080030#include <stdbool.h>
Kristian Høgsberg2158a882013-04-18 15:07:39 -040031#include <stdlib.h>
32#include <stdint.h>
33#include <string.h>
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040034#include <sys/mman.h>
35#include <assert.h>
36#include <unistd.h>
Jonas Ådahld0be2bb2015-04-30 17:56:37 +080037#include <values.h>
Matt Roper01a92732013-06-24 16:52:44 +010038#include <fcntl.h>
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +020039#include <limits.h>
Antonio Borneo39578632019-04-26 23:57:31 +020040#include <errno.h>
Kristian Høgsberg2158a882013-04-18 15:07:39 -040041
Jon Cruz35b2eaa2015-06-15 15:37:08 -070042#include "shared/helpers.h"
Jon Cruz4678bab2015-06-15 15:37:07 -070043#include "shared/os-compatibility.h"
Alexandros Frantzis84b31f82017-11-24 18:01:46 +020044#include "shared/timespec-util.h"
Pekka Paalanen3d5d9472019-03-28 16:28:47 +020045#include <libweston/libweston.h>
Marius Vlad5d649b62019-07-16 23:44:21 +030046#include "backend.h"
Marius Vlad56f3a682019-07-10 14:48:39 +030047#include "libweston-internal.h"
Daniel Stone7dbb0e12016-11-24 15:30:41 +000048#include "relative-pointer-unstable-v1-server-protocol.h"
49#include "pointer-constraints-unstable-v1-server-protocol.h"
Alexandros Frantzis538749d2018-02-16 18:44:16 +020050#include "input-timestamps-unstable-v1-server-protocol.h"
Jonas Ådahld3414f22016-07-22 17:56:31 +080051
52enum pointer_constraint_type {
53 POINTER_CONSTRAINT_TYPE_LOCK,
54 POINTER_CONSTRAINT_TYPE_CONFINE,
55};
56
Jonas Ådahld0be2bb2015-04-30 17:56:37 +080057enum motion_direction {
58 MOTION_DIRECTION_POSITIVE_X = 1 << 0,
59 MOTION_DIRECTION_NEGATIVE_X = 1 << 1,
60 MOTION_DIRECTION_POSITIVE_Y = 1 << 2,
61 MOTION_DIRECTION_NEGATIVE_Y = 1 << 3,
62};
63
64struct vec2d {
65 double x, y;
66};
67
68struct line {
69 struct vec2d a;
70 struct vec2d b;
71};
72
73struct border {
74 struct line line;
75 enum motion_direction blocking_dir;
76};
77
Jonas Ådahld3414f22016-07-22 17:56:31 +080078static void
79maybe_warp_confined_pointer(struct weston_pointer_constraint *constraint);
Kristian Høgsberg2158a882013-04-18 15:07:39 -040080
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040081static void
82empty_region(pixman_region32_t *region)
83{
84 pixman_region32_fini(region);
85 pixman_region32_init(region);
86}
87
Jonas Ådahld3414f22016-07-22 17:56:31 +080088static void
89region_init_infinite(pixman_region32_t *region)
90{
91 pixman_region32_init_rect(region, INT32_MIN, INT32_MIN,
92 UINT32_MAX, UINT32_MAX);
93}
94
Alexandros Frantzis2b442482018-02-20 14:05:50 +020095static void
96send_timestamp(struct wl_resource *resource,
97 const struct timespec *time)
98{
99 uint32_t tv_sec_hi, tv_sec_lo, tv_nsec;
100
101 timespec_to_proto(time, &tv_sec_hi, &tv_sec_lo, &tv_nsec);
102 zwp_input_timestamps_v1_send_timestamp(resource, tv_sec_hi, tv_sec_lo,
103 tv_nsec);
104}
105
106static void
107send_timestamps_for_input_resource(struct wl_resource *input_resource,
108 struct wl_list *list,
109 const struct timespec *time)
110{
111 struct wl_resource *resource;
112
113 wl_resource_for_each(resource, list) {
114 if (wl_resource_get_user_data(resource) == input_resource)
115 send_timestamp(resource, time);
116 }
117}
118
119static void
120remove_input_resource_from_timestamps(struct wl_resource *input_resource,
121 struct wl_list *list)
122{
123 struct wl_resource *resource;
124
125 wl_resource_for_each(resource, list) {
126 if (wl_resource_get_user_data(resource) == input_resource)
127 wl_resource_set_user_data(resource, NULL);
128 }
129}
130
Louis-Francis Ratté-Boulianne6ef59c92017-11-28 20:42:47 -0500131/** Register a touchscreen input device
132 *
133 * \param touch The parent weston_touch that identifies the seat.
134 * \param syspath Unique device name.
135 * \param backend_data Backend private data if necessary.
136 * \param ops Calibration operations, or NULL for not able to run calibration.
137 * \return New touch device, or NULL on failure.
138 */
139WL_EXPORT struct weston_touch_device *
140weston_touch_create_touch_device(struct weston_touch *touch,
141 const char *syspath,
142 void *backend_data,
143 const struct weston_touch_device_ops *ops)
144{
145 struct weston_touch_device *device;
146
147 assert(syspath);
148 if (ops) {
149 assert(ops->get_output);
150 assert(ops->get_calibration_head_name);
151 assert(ops->get_calibration);
152 assert(ops->set_calibration);
153 }
154
155 device = zalloc(sizeof *device);
156 if (!device)
157 return NULL;
158
159 wl_signal_init(&device->destroy_signal);
160
161 device->syspath = strdup(syspath);
162 if (!device->syspath) {
163 free(device);
164 return NULL;
165 }
166
167 device->backend_data = backend_data;
168 device->ops = ops;
169
170 device->aggregate = touch;
171 wl_list_insert(touch->device_list.prev, &device->link);
172
173 return device;
174}
175
176/** Destroy the touch device. */
177WL_EXPORT void
178weston_touch_device_destroy(struct weston_touch_device *device)
179{
180 wl_list_remove(&device->link);
181 wl_signal_emit(&device->destroy_signal, device);
182 free(device->syspath);
183 free(device);
184}
185
186/** Is it possible to run calibration on this touch device? */
187WL_EXPORT bool
188weston_touch_device_can_calibrate(struct weston_touch_device *device)
189{
190 return !!device->ops;
191}
192
Louis-Francis Ratté-Bouliannec4689ff2017-11-28 20:42:47 -0500193static enum weston_touch_mode
194weston_touch_device_get_mode(struct weston_touch_device *device)
195{
196 return device->aggregate->seat->compositor->touch_mode;
197}
198
Jonas Ådahl2cbf2932015-07-22 12:05:38 +0800199static struct weston_pointer_client *
200weston_pointer_client_create(struct wl_client *client)
201{
202 struct weston_pointer_client *pointer_client;
203
204 pointer_client = zalloc(sizeof *pointer_client);
205 if (!pointer_client)
206 return NULL;
207
208 pointer_client->client = client;
209 wl_list_init(&pointer_client->pointer_resources);
Jonas Ådahl30d61d82014-10-22 21:21:17 +0200210 wl_list_init(&pointer_client->relative_pointer_resources);
Jonas Ådahl2cbf2932015-07-22 12:05:38 +0800211
212 return pointer_client;
213}
214
215static void
216weston_pointer_client_destroy(struct weston_pointer_client *pointer_client)
217{
Alexandros Frantzis1c3a40e2018-02-08 15:37:53 +0200218 struct wl_resource *resource;
219
220 wl_resource_for_each(resource, &pointer_client->pointer_resources) {
221 wl_resource_set_user_data(resource, NULL);
222 }
223
224 wl_resource_for_each(resource,
225 &pointer_client->relative_pointer_resources) {
226 wl_resource_set_user_data(resource, NULL);
227 }
228
229 wl_list_remove(&pointer_client->pointer_resources);
230 wl_list_remove(&pointer_client->relative_pointer_resources);
Jonas Ådahl2cbf2932015-07-22 12:05:38 +0800231 free(pointer_client);
232}
233
234static bool
235weston_pointer_client_is_empty(struct weston_pointer_client *pointer_client)
236{
Jonas Ådahl30d61d82014-10-22 21:21:17 +0200237 return (wl_list_empty(&pointer_client->pointer_resources) &&
238 wl_list_empty(&pointer_client->relative_pointer_resources));
Jonas Ådahl2cbf2932015-07-22 12:05:38 +0800239}
240
241static struct weston_pointer_client *
242weston_pointer_get_pointer_client(struct weston_pointer *pointer,
243 struct wl_client *client)
244{
245 struct weston_pointer_client *pointer_client;
246
247 wl_list_for_each(pointer_client, &pointer->pointer_clients, link) {
248 if (pointer_client->client == client)
249 return pointer_client;
250 }
251
252 return NULL;
253}
254
255static struct weston_pointer_client *
256weston_pointer_ensure_pointer_client(struct weston_pointer *pointer,
257 struct wl_client *client)
258{
259 struct weston_pointer_client *pointer_client;
260
261 pointer_client = weston_pointer_get_pointer_client(pointer, client);
262 if (pointer_client)
263 return pointer_client;
264
265 pointer_client = weston_pointer_client_create(client);
266 wl_list_insert(&pointer->pointer_clients, &pointer_client->link);
267
268 if (pointer->focus &&
269 pointer->focus->surface->resource &&
270 wl_resource_get_client(pointer->focus->surface->resource) == client) {
271 pointer->focus_client = pointer_client;
272 }
273
274 return pointer_client;
275}
276
277static void
278weston_pointer_cleanup_pointer_client(struct weston_pointer *pointer,
279 struct weston_pointer_client *pointer_client)
280{
281 if (weston_pointer_client_is_empty(pointer_client)) {
282 if (pointer->focus_client == pointer_client)
283 pointer->focus_client = NULL;
284 wl_list_remove(&pointer_client->link);
285 weston_pointer_client_destroy(pointer_client);
286 }
287}
288
289static void
290unbind_pointer_client_resource(struct wl_resource *resource)
291{
292 struct weston_pointer *pointer = wl_resource_get_user_data(resource);
293 struct wl_client *client = wl_resource_get_client(resource);
294 struct weston_pointer_client *pointer_client;
295
Jonas Ådahl2cbf2932015-07-22 12:05:38 +0800296 wl_list_remove(wl_resource_get_link(resource));
Alexandros Frantzis1c3a40e2018-02-08 15:37:53 +0200297
298 if (pointer) {
299 pointer_client = weston_pointer_get_pointer_client(pointer,
300 client);
301 assert(pointer_client);
Alexandros Frantzisdb907b72018-02-20 14:06:26 +0200302 remove_input_resource_from_timestamps(resource,
303 &pointer->timestamps_list);
Alexandros Frantzis1c3a40e2018-02-08 15:37:53 +0200304 weston_pointer_cleanup_pointer_client(pointer, pointer_client);
305 }
Jonas Ådahl2cbf2932015-07-22 12:05:38 +0800306}
307
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400308static void unbind_resource(struct wl_resource *resource)
309{
Jason Ekstrand44a38632013-06-14 10:08:00 -0500310 wl_list_remove(wl_resource_get_link(resource));
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400311}
312
Jonas Ådahl3042ffe2013-10-17 23:04:08 +0200313WL_EXPORT void
Jonas Ådahl30d61d82014-10-22 21:21:17 +0200314weston_pointer_motion_to_abs(struct weston_pointer *pointer,
315 struct weston_pointer_motion_event *event,
316 wl_fixed_t *x, wl_fixed_t *y)
317{
318 if (event->mask & WESTON_POINTER_MOTION_ABS) {
319 *x = wl_fixed_from_double(event->x);
320 *y = wl_fixed_from_double(event->y);
321 } else if (event->mask & WESTON_POINTER_MOTION_REL) {
322 *x = pointer->x + wl_fixed_from_double(event->dx);
323 *y = pointer->y + wl_fixed_from_double(event->dy);
324 } else {
325 assert(!"invalid motion event");
326 *x = *y = 0;
327 }
328}
329
330static bool
331weston_pointer_motion_to_rel(struct weston_pointer *pointer,
332 struct weston_pointer_motion_event *event,
333 double *dx, double *dy,
334 double *dx_unaccel, double *dy_unaccel)
335{
336 if (event->mask & WESTON_POINTER_MOTION_REL &&
337 event->mask & WESTON_POINTER_MOTION_REL_UNACCEL) {
338 *dx = event->dx;
339 *dy = event->dy;
340 *dx_unaccel = event->dx_unaccel;
341 *dy_unaccel = event->dy_unaccel;
342 return true;
343 } else if (event->mask & WESTON_POINTER_MOTION_REL) {
344 *dx_unaccel = *dx = event->dx;
345 *dy_unaccel = *dy = event->dy;
346 return true;
347 } else if (event->mask & WESTON_POINTER_MOTION_REL_UNACCEL) {
348 *dx_unaccel = *dx = event->dx_unaccel;
349 *dy_unaccel = *dy = event->dy_unaccel;
350 return true;
351 } else {
352 return false;
353 }
354}
355
356WL_EXPORT void
Kristian Høgsberga71e8b22013-05-06 21:51:21 -0400357weston_seat_repick(struct weston_seat *seat)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400358{
Derek Foreman1281a362015-07-31 16:55:32 -0500359 const struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400360
Derek Foreman1b786ee2015-06-03 15:53:23 -0500361 if (!pointer)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400362 return;
363
Derek Foreman1b786ee2015-06-03 15:53:23 -0500364 pointer->grab->interface->focus(pointer->grab);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400365}
366
367static void
368weston_compositor_idle_inhibit(struct weston_compositor *compositor)
369{
370 weston_compositor_wake(compositor);
371 compositor->idle_inhibit++;
372}
373
374static void
375weston_compositor_idle_release(struct weston_compositor *compositor)
376{
377 compositor->idle_inhibit--;
378 weston_compositor_wake(compositor);
379}
380
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400381static void
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100382pointer_focus_view_destroyed(struct wl_listener *listener, void *data)
383{
384 struct weston_pointer *pointer =
385 container_of(listener, struct weston_pointer,
386 focus_view_listener);
387
Derek Foremanf9318d12015-05-11 15:40:11 -0500388 weston_pointer_clear_focus(pointer);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100389}
390
391static void
392pointer_focus_resource_destroyed(struct wl_listener *listener, void *data)
393{
394 struct weston_pointer *pointer =
395 container_of(listener, struct weston_pointer,
396 focus_resource_listener);
397
Derek Foremanf9318d12015-05-11 15:40:11 -0500398 weston_pointer_clear_focus(pointer);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100399}
400
401static void
402keyboard_focus_resource_destroyed(struct wl_listener *listener, void *data)
403{
404 struct weston_keyboard *keyboard =
405 container_of(listener, struct weston_keyboard,
406 focus_resource_listener);
407
408 weston_keyboard_set_focus(keyboard, NULL);
409}
410
411static void
412touch_focus_view_destroyed(struct wl_listener *listener, void *data)
413{
414 struct weston_touch *touch =
415 container_of(listener, struct weston_touch,
416 focus_view_listener);
417
Derek Foreman4c93c082015-04-30 16:45:41 -0500418 weston_touch_set_focus(touch, NULL);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100419}
420
421static void
422touch_focus_resource_destroyed(struct wl_listener *listener, void *data)
423{
424 struct weston_touch *touch =
425 container_of(listener, struct weston_touch,
426 focus_resource_listener);
427
Derek Foreman4c93c082015-04-30 16:45:41 -0500428 weston_touch_set_focus(touch, NULL);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100429}
430
431static void
Neil Roberts96d790e2013-09-19 17:32:00 +0100432move_resources(struct wl_list *destination, struct wl_list *source)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400433{
Neil Roberts96d790e2013-09-19 17:32:00 +0100434 wl_list_insert_list(destination, source);
435 wl_list_init(source);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400436}
437
438static void
Neil Roberts96d790e2013-09-19 17:32:00 +0100439move_resources_for_client(struct wl_list *destination,
440 struct wl_list *source,
441 struct wl_client *client)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400442{
Neil Roberts96d790e2013-09-19 17:32:00 +0100443 struct wl_resource *resource, *tmp;
444 wl_resource_for_each_safe(resource, tmp, source) {
445 if (wl_resource_get_client(resource) == client) {
446 wl_list_remove(wl_resource_get_link(resource));
447 wl_list_insert(destination,
448 wl_resource_get_link(resource));
449 }
450 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400451}
452
453static void
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700454default_grab_pointer_focus(struct weston_pointer_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400455{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400456 struct weston_pointer *pointer = grab->pointer;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500457 struct weston_view *view;
Kristian Høgsberg6848c252013-05-08 22:02:59 -0400458 wl_fixed_t sx, sy;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400459
460 if (pointer->button_count > 0)
461 return;
462
Jason Ekstranda7af7042013-10-12 22:38:11 -0500463 view = weston_compositor_pick_view(pointer->seat->compositor,
464 pointer->x, pointer->y,
465 &sx, &sy);
Kristian Høgsberg6848c252013-05-08 22:02:59 -0400466
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -0800467 if (pointer->focus != view || pointer->sx != sx || pointer->sy != sy)
Jason Ekstranda7af7042013-10-12 22:38:11 -0500468 weston_pointer_set_focus(pointer, view, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400469}
470
471static void
Quentin Glidiccde13452016-08-12 10:41:32 +0200472pointer_send_relative_motion(struct weston_pointer *pointer,
Alexandros Frantzis84b31f82017-11-24 18:01:46 +0200473 const struct timespec *time,
Quentin Glidiccde13452016-08-12 10:41:32 +0200474 struct weston_pointer_motion_event *event)
Jonas Ådahl30d61d82014-10-22 21:21:17 +0200475{
476 uint64_t time_usec;
477 double dx, dy, dx_unaccel, dy_unaccel;
478 wl_fixed_t dxf, dyf, dxf_unaccel, dyf_unaccel;
479 struct wl_list *resource_list;
480 struct wl_resource *resource;
481
482 if (!pointer->focus_client)
483 return;
484
485 if (!weston_pointer_motion_to_rel(pointer, event,
486 &dx, &dy,
487 &dx_unaccel, &dy_unaccel))
488 return;
489
490 resource_list = &pointer->focus_client->relative_pointer_resources;
Alexandros Frantzis84b31f82017-11-24 18:01:46 +0200491 time_usec = timespec_to_usec(&event->time);
Jonas Ådahl30d61d82014-10-22 21:21:17 +0200492 if (time_usec == 0)
Alexandros Frantzis84b31f82017-11-24 18:01:46 +0200493 time_usec = timespec_to_usec(time);
Jonas Ådahl30d61d82014-10-22 21:21:17 +0200494
495 dxf = wl_fixed_from_double(dx);
496 dyf = wl_fixed_from_double(dy);
497 dxf_unaccel = wl_fixed_from_double(dx_unaccel);
498 dyf_unaccel = wl_fixed_from_double(dy_unaccel);
499
500 wl_resource_for_each(resource, resource_list) {
501 zwp_relative_pointer_v1_send_relative_motion(
502 resource,
503 (uint32_t) (time_usec >> 32),
504 (uint32_t) time_usec,
505 dxf, dyf,
506 dxf_unaccel, dyf_unaccel);
507 }
508}
509
510static void
Alexandros Frantzis84b31f82017-11-24 18:01:46 +0200511pointer_send_motion(struct weston_pointer *pointer,
512 const struct timespec *time,
Quentin Glidiccde13452016-08-12 10:41:32 +0200513 wl_fixed_t sx, wl_fixed_t sy)
Jonas Ådahlf44942e2016-07-22 17:54:55 +0800514{
515 struct wl_list *resource_list;
516 struct wl_resource *resource;
Alexandros Frantzis84b31f82017-11-24 18:01:46 +0200517 uint32_t msecs;
Jonas Ådahlf44942e2016-07-22 17:54:55 +0800518
519 if (!pointer->focus_client)
520 return;
521
522 resource_list = &pointer->focus_client->pointer_resources;
Alexandros Frantzis84b31f82017-11-24 18:01:46 +0200523 msecs = timespec_to_msec(time);
Alexandros Frantzisdb907b72018-02-20 14:06:26 +0200524 wl_resource_for_each(resource, resource_list) {
525 send_timestamps_for_input_resource(resource,
Emmanuel Gil Peyroteff793a2021-07-31 17:25:41 +0200526 &pointer->timestamps_list,
527 time);
Alexandros Frantzis84b31f82017-11-24 18:01:46 +0200528 wl_pointer_send_motion(resource, msecs, sx, sy);
Alexandros Frantzisdb907b72018-02-20 14:06:26 +0200529 }
Jonas Ådahlf44942e2016-07-22 17:54:55 +0800530}
531
Quentin Glidiccde13452016-08-12 10:41:32 +0200532WL_EXPORT void
Alexandros Frantzis84b31f82017-11-24 18:01:46 +0200533weston_pointer_send_motion(struct weston_pointer *pointer,
534 const struct timespec *time,
Quentin Glidiccde13452016-08-12 10:41:32 +0200535 struct weston_pointer_motion_event *event)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400536{
Jonas Ådahld2510102014-10-05 21:39:14 +0200537 wl_fixed_t x, y;
Jonas Ådahl8283c342015-04-24 15:26:17 +0800538 wl_fixed_t old_sx = pointer->sx;
539 wl_fixed_t old_sy = pointer->sy;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400540
Jonas Ådahld2510102014-10-05 21:39:14 +0200541 if (pointer->focus) {
542 weston_pointer_motion_to_abs(pointer, event, &x, &y);
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -0800543 weston_view_from_global_fixed(pointer->focus, x, y,
544 &pointer->sx, &pointer->sy);
Jonas Ådahld2510102014-10-05 21:39:14 +0200545 }
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -0800546
Jonas Ådahld2510102014-10-05 21:39:14 +0200547 weston_pointer_move(pointer, event);
Giulio Camuffo1959ab82013-11-14 23:42:52 +0100548
Jonas Ådahlf44942e2016-07-22 17:54:55 +0800549 if (old_sx != pointer->sx || old_sy != pointer->sy) {
Quentin Glidiccde13452016-08-12 10:41:32 +0200550 pointer_send_motion(pointer, time,
551 pointer->sx, pointer->sy);
Kristian Høgsbergbe6403e2013-05-08 21:03:21 -0400552 }
Jonas Ådahl30d61d82014-10-22 21:21:17 +0200553
Quentin Glidiccde13452016-08-12 10:41:32 +0200554 pointer_send_relative_motion(pointer, time, event);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400555}
556
557static void
Alexandros Frantzis84b31f82017-11-24 18:01:46 +0200558default_grab_pointer_motion(struct weston_pointer_grab *grab,
559 const struct timespec *time,
Quentin Glidiccde13452016-08-12 10:41:32 +0200560 struct weston_pointer_motion_event *event)
561{
562 weston_pointer_send_motion(grab->pointer, time, event);
563}
564
565/** Check if the pointer has focused resources.
566 *
567 * \param pointer The pointer to check for focused resources.
568 * \return Whether or not this pointer has focused resources
569 */
570WL_EXPORT bool
571weston_pointer_has_focus_resource(struct weston_pointer *pointer)
572{
573 if (!pointer->focus_client)
574 return false;
575
576 if (wl_list_empty(&pointer->focus_client->pointer_resources))
577 return false;
578
579 return true;
580}
581
582/** Send wl_pointer.button events to focused resources.
583 *
584 * \param pointer The pointer where the button events originates from.
585 * \param time The timestamp of the event
586 * \param button The button value of the event
Marius Vlada2dace22019-06-12 16:05:44 +0300587 * \param state The state enum value of the event
Quentin Glidiccde13452016-08-12 10:41:32 +0200588 *
589 * For every resource that is currently in focus, send a wl_pointer.button event
590 * with the passed parameters. The focused resources are the wl_pointer
591 * resources of the client which currently has the surface with pointer focus.
592 */
593WL_EXPORT void
Jonas Ådahlc02ac112016-07-22 17:55:43 +0800594weston_pointer_send_button(struct weston_pointer *pointer,
Alexandros Frantzis215bedc2017-11-16 18:20:55 +0200595 const struct timespec *time, uint32_t button,
Quentin Glidiccde13452016-08-12 10:41:32 +0200596 enum wl_pointer_button_state state)
Jonas Ådahlc02ac112016-07-22 17:55:43 +0800597{
598 struct wl_display *display = pointer->seat->compositor->wl_display;
599 struct wl_list *resource_list;
600 struct wl_resource *resource;
601 uint32_t serial;
Alexandros Frantzis215bedc2017-11-16 18:20:55 +0200602 uint32_t msecs;
Jonas Ådahlc02ac112016-07-22 17:55:43 +0800603
Quentin Glidiccde13452016-08-12 10:41:32 +0200604 if (!weston_pointer_has_focus_resource(pointer))
Jonas Ådahlc02ac112016-07-22 17:55:43 +0800605 return;
606
607 resource_list = &pointer->focus_client->pointer_resources;
Quentin Glidiccde13452016-08-12 10:41:32 +0200608 serial = wl_display_next_serial(display);
Alexandros Frantzis215bedc2017-11-16 18:20:55 +0200609 msecs = timespec_to_msec(time);
Alexandros Frantzisdb907b72018-02-20 14:06:26 +0200610 wl_resource_for_each(resource, resource_list) {
611 send_timestamps_for_input_resource(resource,
Emmanuel Gil Peyroteff793a2021-07-31 17:25:41 +0200612 &pointer->timestamps_list,
613 time);
Alexandros Frantzis215bedc2017-11-16 18:20:55 +0200614 wl_pointer_send_button(resource, serial, msecs, button, state);
Alexandros Frantzisdb907b72018-02-20 14:06:26 +0200615 }
Jonas Ådahlc02ac112016-07-22 17:55:43 +0800616}
617
618static void
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700619default_grab_pointer_button(struct weston_pointer_grab *grab,
Alexandros Frantzis215bedc2017-11-16 18:20:55 +0200620 const struct timespec *time, uint32_t button,
Quentin Glidiccde13452016-08-12 10:41:32 +0200621 enum wl_pointer_button_state state)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400622{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400623 struct weston_pointer *pointer = grab->pointer;
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400624 struct weston_compositor *compositor = pointer->seat->compositor;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500625 struct weston_view *view;
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400626 wl_fixed_t sx, sy;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400627
Quentin Glidiccde13452016-08-12 10:41:32 +0200628 weston_pointer_send_button(pointer, time, button, state);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400629
630 if (pointer->button_count == 0 &&
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400631 state == WL_POINTER_BUTTON_STATE_RELEASED) {
Jason Ekstranda7af7042013-10-12 22:38:11 -0500632 view = weston_compositor_pick_view(compositor,
633 pointer->x, pointer->y,
634 &sx, &sy);
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400635
Jason Ekstranda7af7042013-10-12 22:38:11 -0500636 weston_pointer_set_focus(pointer, view, sx, sy);
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400637 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400638}
639
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200640/** Send wl_pointer.axis events to focused resources.
641 *
642 * \param pointer The pointer where the axis events originates from.
643 * \param time The timestamp of the event
Marius Vlada2dace22019-06-12 16:05:44 +0300644 * \param event The axis value of the event
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200645 *
646 * For every resource that is currently in focus, send a wl_pointer.axis event
647 * with the passed parameters. The focused resources are the wl_pointer
648 * resources of the client which currently has the surface with pointer focus.
649 */
650WL_EXPORT void
651weston_pointer_send_axis(struct weston_pointer *pointer,
Alexandros Frantzis80321942017-11-16 18:20:56 +0200652 const struct timespec *time,
Peter Hutterer89b6a492016-01-18 15:58:17 +1000653 struct weston_pointer_axis_event *event)
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200654{
655 struct wl_resource *resource;
656 struct wl_list *resource_list;
Alexandros Frantzis80321942017-11-16 18:20:56 +0200657 uint32_t msecs;
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200658
Quentin Glidiccde13452016-08-12 10:41:32 +0200659 if (!weston_pointer_has_focus_resource(pointer))
Jonas Ådahl2cbf2932015-07-22 12:05:38 +0800660 return;
661
662 resource_list = &pointer->focus_client->pointer_resources;
Alexandros Frantzis80321942017-11-16 18:20:56 +0200663 msecs = timespec_to_msec(time);
Peter Hutterer87743e92016-01-18 16:38:22 +1000664 wl_resource_for_each(resource, resource_list) {
665 if (event->has_discrete &&
666 wl_resource_get_version(resource) >=
667 WL_POINTER_AXIS_DISCRETE_SINCE_VERSION)
668 wl_pointer_send_axis_discrete(resource, event->axis,
669 event->discrete);
670
Alexandros Frantzisdb907b72018-02-20 14:06:26 +0200671 if (event->value) {
672 send_timestamps_for_input_resource(resource,
673 &pointer->timestamps_list,
674 time);
Alexandros Frantzis80321942017-11-16 18:20:56 +0200675 wl_pointer_send_axis(resource, msecs,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +0200676 event->axis,
677 wl_fixed_from_double(event->value));
Alexandros Frantzisdb907b72018-02-20 14:06:26 +0200678 } else if (wl_resource_get_version(resource) >=
679 WL_POINTER_AXIS_STOP_SINCE_VERSION) {
680 send_timestamps_for_input_resource(resource,
681 &pointer->timestamps_list,
682 time);
Alexandros Frantzis80321942017-11-16 18:20:56 +0200683 wl_pointer_send_axis_stop(resource, msecs,
Peter Hutterer87743e92016-01-18 16:38:22 +1000684 event->axis);
Alexandros Frantzisdb907b72018-02-20 14:06:26 +0200685 }
Peter Hutterer87743e92016-01-18 16:38:22 +1000686 }
687}
688
Quentin Glidiccde13452016-08-12 10:41:32 +0200689/** Send wl_pointer.axis_source events to focused resources.
690 *
691 * \param pointer The pointer where the axis_source events originates from.
692 * \param source The axis_source enum value of the event
693 *
694 * For every resource that is currently in focus, send a wl_pointer.axis_source
695 * event with the passed parameter. The focused resources are the wl_pointer
696 * resources of the client which currently has the surface with pointer focus.
697 */
Peter Hutterer87743e92016-01-18 16:38:22 +1000698WL_EXPORT void
Quentin Glidiccde13452016-08-12 10:41:32 +0200699weston_pointer_send_axis_source(struct weston_pointer *pointer,
700 enum wl_pointer_axis_source source)
Peter Hutterer87743e92016-01-18 16:38:22 +1000701{
702 struct wl_resource *resource;
703 struct wl_list *resource_list;
704
Quentin Glidiccde13452016-08-12 10:41:32 +0200705 if (!weston_pointer_has_focus_resource(pointer))
Jonas Ådahled6014a2016-04-21 10:21:48 +0800706 return;
707
Peter Hutterer87743e92016-01-18 16:38:22 +1000708 resource_list = &pointer->focus_client->pointer_resources;
709 wl_resource_for_each(resource, resource_list) {
710 if (wl_resource_get_version(resource) >=
711 WL_POINTER_AXIS_SOURCE_SINCE_VERSION) {
712 wl_pointer_send_axis_source(resource, source);
713 }
714 }
715}
716
717static void
718pointer_send_frame(struct wl_resource *resource)
719{
720 if (wl_resource_get_version(resource) >=
721 WL_POINTER_FRAME_SINCE_VERSION) {
722 wl_pointer_send_frame(resource);
723 }
724}
725
Quentin Glidiccde13452016-08-12 10:41:32 +0200726/** Send wl_pointer.frame events to focused resources.
727 *
728 * \param pointer The pointer where the frame events originates from.
729 *
730 * For every resource that is currently in focus, send a wl_pointer.frame event.
731 * The focused resources are the wl_pointer resources of the client which
732 * currently has the surface with pointer focus.
733 */
Peter Hutterer87743e92016-01-18 16:38:22 +1000734WL_EXPORT void
735weston_pointer_send_frame(struct weston_pointer *pointer)
736{
737 struct wl_resource *resource;
738 struct wl_list *resource_list;
739
Quentin Glidiccde13452016-08-12 10:41:32 +0200740 if (!weston_pointer_has_focus_resource(pointer))
Derek Foreman8efa31b2016-01-29 10:29:46 -0600741 return;
742
Peter Hutterer87743e92016-01-18 16:38:22 +1000743 resource_list = &pointer->focus_client->pointer_resources;
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200744 wl_resource_for_each(resource, resource_list)
Peter Hutterer87743e92016-01-18 16:38:22 +1000745 pointer_send_frame(resource);
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200746}
747
748static void
749default_grab_pointer_axis(struct weston_pointer_grab *grab,
Alexandros Frantzis80321942017-11-16 18:20:56 +0200750 const struct timespec *time,
Peter Hutterer89b6a492016-01-18 15:58:17 +1000751 struct weston_pointer_axis_event *event)
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200752{
Peter Hutterer89b6a492016-01-18 15:58:17 +1000753 weston_pointer_send_axis(grab->pointer, time, event);
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200754}
755
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200756static void
Peter Hutterer87743e92016-01-18 16:38:22 +1000757default_grab_pointer_axis_source(struct weston_pointer_grab *grab,
Quentin Glidiccde13452016-08-12 10:41:32 +0200758 enum wl_pointer_axis_source source)
Peter Hutterer87743e92016-01-18 16:38:22 +1000759{
760 weston_pointer_send_axis_source(grab->pointer, source);
761}
762
763static void
764default_grab_pointer_frame(struct weston_pointer_grab *grab)
765{
766 weston_pointer_send_frame(grab->pointer);
767}
768
769static void
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200770default_grab_pointer_cancel(struct weston_pointer_grab *grab)
771{
772}
773
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400774static const struct weston_pointer_grab_interface
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400775 default_pointer_grab_interface = {
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700776 default_grab_pointer_focus,
777 default_grab_pointer_motion,
778 default_grab_pointer_button,
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200779 default_grab_pointer_axis,
Peter Hutterer87743e92016-01-18 16:38:22 +1000780 default_grab_pointer_axis_source,
781 default_grab_pointer_frame,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200782 default_grab_pointer_cancel,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400783};
784
Quentin Glidiccde13452016-08-12 10:41:32 +0200785/** Check if the touch has focused resources.
786 *
787 * \param touch The touch to check for focused resources.
788 * \return Whether or not this touch has focused resources
789 */
790WL_EXPORT bool
791weston_touch_has_focus_resource(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400792{
Quentin Glidiccde13452016-08-12 10:41:32 +0200793 if (!touch->focus)
794 return false;
795
796 if (wl_list_empty(&touch->focus_resource_list))
797 return false;
798
799 return true;
800}
801
802/** Send wl_touch.down events to focused resources.
803 *
804 * \param touch The touch where the down events originates from.
805 * \param time The timestamp of the event
806 * \param touch_id The touch_id value of the event
807 * \param x The x value of the event
808 * \param y The y value of the event
809 *
810 * For every resource that is currently in focus, send a wl_touch.down event
811 * with the passed parameters. The focused resources are the wl_touch
812 * resources of the client which currently has the surface with touch focus.
813 */
814WL_EXPORT void
Alexandros Frantzis9448deb2017-11-16 18:20:58 +0200815weston_touch_send_down(struct weston_touch *touch, const struct timespec *time,
Quentin Glidiccde13452016-08-12 10:41:32 +0200816 int touch_id, wl_fixed_t x, wl_fixed_t y)
817{
Rob Bradford880ebc72013-07-22 17:31:38 +0100818 struct wl_display *display = touch->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400819 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +0100820 struct wl_resource *resource;
821 struct wl_list *resource_list;
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300822 wl_fixed_t sx, sy;
Alexandros Frantzis9448deb2017-11-16 18:20:58 +0200823 uint32_t msecs;
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300824
Quentin Glidiccde13452016-08-12 10:41:32 +0200825 if (!weston_touch_has_focus_resource(touch))
Bryce Harrington2c40d1d2016-02-02 10:18:48 -0800826 return;
827
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300828 weston_view_from_global_fixed(touch->focus, x, y, &sx, &sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400829
Neil Roberts96d790e2013-09-19 17:32:00 +0100830 resource_list = &touch->focus_resource_list;
Quentin Glidiccde13452016-08-12 10:41:32 +0200831 serial = wl_display_next_serial(display);
Alexandros Frantzis9448deb2017-11-16 18:20:58 +0200832 msecs = timespec_to_msec(time);
Alexandros Frantzisd7157842018-02-20 14:07:03 +0200833 wl_resource_for_each(resource, resource_list) {
834 send_timestamps_for_input_resource(resource,
835 &touch->timestamps_list,
836 time);
837 wl_touch_send_down(resource, serial, msecs,
838 touch->focus->surface->resource,
839 touch_id, sx, sy);
840 }
Quentin Glidiccde13452016-08-12 10:41:32 +0200841}
Neil Roberts96d790e2013-09-19 17:32:00 +0100842
Quentin Glidiccde13452016-08-12 10:41:32 +0200843static void
Alexandros Frantzis9448deb2017-11-16 18:20:58 +0200844default_grab_touch_down(struct weston_touch_grab *grab,
845 const struct timespec *time, int touch_id,
846 wl_fixed_t x, wl_fixed_t y)
Quentin Glidiccde13452016-08-12 10:41:32 +0200847{
848 weston_touch_send_down(grab->touch, time, touch_id, x, y);
849}
850
851/** Send wl_touch.up events to focused resources.
852 *
853 * \param touch The touch where the up events originates from.
854 * \param time The timestamp of the event
855 * \param touch_id The touch_id value of the event
856 *
857 * For every resource that is currently in focus, send a wl_touch.up event
858 * with the passed parameters. The focused resources are the wl_touch
859 * resources of the client which currently has the surface with touch focus.
860 */
861WL_EXPORT void
Alexandros Frantzis27a51b82017-11-16 18:20:59 +0200862weston_touch_send_up(struct weston_touch *touch, const struct timespec *time,
863 int touch_id)
Quentin Glidiccde13452016-08-12 10:41:32 +0200864{
865 struct wl_display *display = touch->seat->compositor->wl_display;
866 uint32_t serial;
867 struct wl_resource *resource;
868 struct wl_list *resource_list;
Alexandros Frantzis27a51b82017-11-16 18:20:59 +0200869 uint32_t msecs;
Quentin Glidiccde13452016-08-12 10:41:32 +0200870
871 if (!weston_touch_has_focus_resource(touch))
872 return;
873
874 resource_list = &touch->focus_resource_list;
875 serial = wl_display_next_serial(display);
Alexandros Frantzis27a51b82017-11-16 18:20:59 +0200876 msecs = timespec_to_msec(time);
Alexandros Frantzisd7157842018-02-20 14:07:03 +0200877 wl_resource_for_each(resource, resource_list) {
878 send_timestamps_for_input_resource(resource,
879 &touch->timestamps_list,
880 time);
Alexandros Frantzis27a51b82017-11-16 18:20:59 +0200881 wl_touch_send_up(resource, serial, msecs, touch_id);
Alexandros Frantzisd7157842018-02-20 14:07:03 +0200882 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400883}
884
Kristian Høgsberge329f362013-05-06 22:19:57 -0400885static void
886default_grab_touch_up(struct weston_touch_grab *grab,
Alexandros Frantzis27a51b82017-11-16 18:20:59 +0200887 const struct timespec *time, int touch_id)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400888{
Quentin Glidiccde13452016-08-12 10:41:32 +0200889 weston_touch_send_up(grab->touch, time, touch_id);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400890}
891
Quentin Glidiccde13452016-08-12 10:41:32 +0200892/** Send wl_touch.motion events to focused resources.
893 *
894 * \param touch The touch where the motion events originates from.
895 * \param time The timestamp of the event
896 * \param touch_id The touch_id value of the event
897 * \param x The x value of the event
898 * \param y The y value of the event
899 *
900 * For every resource that is currently in focus, send a wl_touch.motion event
901 * with the passed parameters. The focused resources are the wl_touch
902 * resources of the client which currently has the surface with touch focus.
903 */
904WL_EXPORT void
Alexandros Frantzis7d2abcf2017-11-16 18:21:00 +0200905weston_touch_send_motion(struct weston_touch *touch,
906 const struct timespec *time, int touch_id,
907 wl_fixed_t x, wl_fixed_t y)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400908{
Neil Roberts96d790e2013-09-19 17:32:00 +0100909 struct wl_resource *resource;
910 struct wl_list *resource_list;
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300911 wl_fixed_t sx, sy;
Alexandros Frantzis7d2abcf2017-11-16 18:21:00 +0200912 uint32_t msecs;
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300913
Quentin Glidiccde13452016-08-12 10:41:32 +0200914 if (!weston_touch_has_focus_resource(touch))
915 return;
916
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300917 weston_view_from_global_fixed(touch->focus, x, y, &sx, &sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400918
Neil Roberts96d790e2013-09-19 17:32:00 +0100919 resource_list = &touch->focus_resource_list;
Alexandros Frantzis7d2abcf2017-11-16 18:21:00 +0200920 msecs = timespec_to_msec(time);
Neil Roberts96d790e2013-09-19 17:32:00 +0100921 wl_resource_for_each(resource, resource_list) {
Alexandros Frantzisd7157842018-02-20 14:07:03 +0200922 send_timestamps_for_input_resource(resource,
923 &touch->timestamps_list,
924 time);
Alexandros Frantzis7d2abcf2017-11-16 18:21:00 +0200925 wl_touch_send_motion(resource, msecs,
Kristian Høgsberge329f362013-05-06 22:19:57 -0400926 touch_id, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400927 }
928}
929
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200930static void
Alexandros Frantzis7d2abcf2017-11-16 18:21:00 +0200931default_grab_touch_motion(struct weston_touch_grab *grab,
932 const struct timespec *time, int touch_id,
933 wl_fixed_t x, wl_fixed_t y)
Quentin Glidiccde13452016-08-12 10:41:32 +0200934{
935 weston_touch_send_motion(grab->touch, time, touch_id, x, y);
936}
937
938
939/** Send wl_touch.frame events to focused resources.
940 *
941 * \param touch The touch where the frame events originates from.
942 *
943 * For every resource that is currently in focus, send a wl_touch.frame event.
944 * The focused resources are the wl_touch resources of the client which
945 * currently has the surface with touch focus.
946 */
947WL_EXPORT void
948weston_touch_send_frame(struct weston_touch *touch)
Jonas Ådahl1679f232014-04-12 09:39:51 +0200949{
950 struct wl_resource *resource;
951
Quentin Glidiccde13452016-08-12 10:41:32 +0200952 if (!weston_touch_has_focus_resource(touch))
953 return;
954
955 wl_resource_for_each(resource, &touch->focus_resource_list)
Jonas Ådahl1679f232014-04-12 09:39:51 +0200956 wl_touch_send_frame(resource);
957}
958
959static void
Quentin Glidiccde13452016-08-12 10:41:32 +0200960default_grab_touch_frame(struct weston_touch_grab *grab)
961{
962 weston_touch_send_frame(grab->touch);
963}
964
965static void
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200966default_grab_touch_cancel(struct weston_touch_grab *grab)
967{
968}
969
Kristian Høgsberge329f362013-05-06 22:19:57 -0400970static const struct weston_touch_grab_interface default_touch_grab_interface = {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400971 default_grab_touch_down,
972 default_grab_touch_up,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200973 default_grab_touch_motion,
Jonas Ådahl1679f232014-04-12 09:39:51 +0200974 default_grab_touch_frame,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200975 default_grab_touch_cancel,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400976};
977
Quentin Glidiccde13452016-08-12 10:41:32 +0200978/** Check if the keyboard has focused resources.
979 *
980 * \param keyboard The keyboard to check for focused resources.
981 * \return Whether or not this keyboard has focused resources
982 */
983WL_EXPORT bool
984weston_keyboard_has_focus_resource(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400985{
Quentin Glidiccde13452016-08-12 10:41:32 +0200986 if (!keyboard->focus)
987 return false;
988
989 if (wl_list_empty(&keyboard->focus_resource_list))
990 return false;
991
992 return true;
993}
994
995/** Send wl_keyboard.key events to focused resources.
996 *
997 * \param keyboard The keyboard where the key events originates from.
998 * \param time The timestamp of the event
999 * \param key The key value of the event
1000 * \param state The state enum value of the event
1001 *
1002 * For every resource that is currently in focus, send a wl_keyboard.key event
1003 * with the passed parameters. The focused resources are the wl_keyboard
1004 * resources of the client which currently has the surface with keyboard focus.
1005 */
1006WL_EXPORT void
1007weston_keyboard_send_key(struct weston_keyboard *keyboard,
Alexandros Frantzis47e79c82017-11-16 18:20:57 +02001008 const struct timespec *time, uint32_t key,
Quentin Glidiccde13452016-08-12 10:41:32 +02001009 enum wl_keyboard_key_state state)
1010{
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001011 struct wl_resource *resource;
Rob Bradford880ebc72013-07-22 17:31:38 +01001012 struct wl_display *display = keyboard->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001013 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +01001014 struct wl_list *resource_list;
Alexandros Frantzis47e79c82017-11-16 18:20:57 +02001015 uint32_t msecs;
leng.fangdbaf6fa2024-06-20 19:31:04 +08001016 bool is_int_key = false;
1017 bool add_key_flg = false;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001018
leng.fange9d800e2024-07-12 13:31:59 +08001019 add_key_flg = (state == WL_KEYBOARD_KEY_STATE_PRESSED);
1020 if (!weston_keyboard_has_focus_resource(keyboard) && add_key_flg)
Quentin Glidiccde13452016-08-12 10:41:32 +02001021 return;
1022
Neil Roberts96d790e2013-09-19 17:32:00 +01001023 resource_list = &keyboard->focus_resource_list;
Quentin Glidiccde13452016-08-12 10:41:32 +02001024 serial = wl_display_next_serial(display);
Alexandros Frantzis47e79c82017-11-16 18:20:57 +02001025 msecs = timespec_to_msec(time);
leng.fangdbaf6fa2024-06-20 19:31:04 +08001026 is_int_key = weston_keyboard_is_intercepted_keycode(
1027 keyboard, key,
1028 0, 0, 0, 0,
1029 serial, state, msecs, false);
1030 if (is_int_key)
1031 return;
1032
Alexandros Frantzis2b442482018-02-20 14:05:50 +02001033 wl_resource_for_each(resource, resource_list) {
leng.fangdbaf6fa2024-06-20 19:31:04 +08001034 if (add_key_flg) {
1035 weston_keyboard_add_key_info(keyboard, resource, key);
1036 send_timestamps_for_input_resource(resource,
1037 &keyboard->timestamps_list,
1038 time);
1039 wl_keyboard_send_key(resource, serial, msecs, key, state);
1040 }
Alexandros Frantzis2b442482018-02-20 14:05:50 +02001041 }
leng.fangdbaf6fa2024-06-20 19:31:04 +08001042 if (!add_key_flg) {
1043 while (!wl_list_empty(&keyboard->key_info)) {
1044 weston_keyboard_get_resource_and_key(keyboard, &resource, &key);
1045 send_timestamps_for_input_resource(resource,
1046 &keyboard->timestamps_list,
1047 time);
1048 wl_keyboard_send_key(resource, serial, msecs, key, state);
1049 }
1050 }
1051}
Quentin Glidiccde13452016-08-12 10:41:32 +02001052
1053static void
1054default_grab_keyboard_key(struct weston_keyboard_grab *grab,
Alexandros Frantzis47e79c82017-11-16 18:20:57 +02001055 const struct timespec *time, uint32_t key,
1056 uint32_t state)
Quentin Glidiccde13452016-08-12 10:41:32 +02001057{
1058 weston_keyboard_send_key(grab->keyboard, time, key, state);
Neil Roberts96d790e2013-09-19 17:32:00 +01001059}
1060
1061static void
1062send_modifiers_to_resource(struct weston_keyboard *keyboard,
1063 struct wl_resource *resource,
1064 uint32_t serial)
1065{
1066 wl_keyboard_send_modifiers(resource,
1067 serial,
1068 keyboard->modifiers.mods_depressed,
1069 keyboard->modifiers.mods_latched,
1070 keyboard->modifiers.mods_locked,
1071 keyboard->modifiers.group);
1072}
1073
1074static void
1075send_modifiers_to_client_in_list(struct wl_client *client,
1076 struct wl_list *list,
1077 uint32_t serial,
1078 struct weston_keyboard *keyboard)
1079{
1080 struct wl_resource *resource;
1081
1082 wl_resource_for_each(resource, list) {
1083 if (wl_resource_get_client(resource) == client)
1084 send_modifiers_to_resource(keyboard,
1085 resource,
1086 serial);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001087 }
1088}
1089
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001090static struct weston_pointer_client *
1091find_pointer_client_for_surface(struct weston_pointer *pointer,
1092 struct weston_surface *surface)
1093{
1094 struct wl_client *client;
1095
1096 if (!surface)
1097 return NULL;
1098
1099 if (!surface->resource)
1100 return NULL;
1101
1102 client = wl_resource_get_client(surface->resource);
1103 return weston_pointer_get_pointer_client(pointer, client);
1104}
1105
1106static struct weston_pointer_client *
1107find_pointer_client_for_view(struct weston_pointer *pointer, struct weston_view *view)
1108{
1109 if (!view)
1110 return NULL;
1111
1112 return find_pointer_client_for_surface(pointer, view->surface);
1113}
1114
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001115static struct wl_resource *
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -04001116find_resource_for_surface(struct wl_list *list, struct weston_surface *surface)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001117{
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001118 if (!surface)
1119 return NULL;
1120
Jason Ekstrand44a38632013-06-14 10:08:00 -05001121 if (!surface->resource)
1122 return NULL;
Stefan Schmidtfda26522013-09-17 10:54:09 +01001123
Jason Ekstrand44a38632013-06-14 10:08:00 -05001124 return wl_resource_find_for_client(list, wl_resource_get_client(surface->resource));
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001125}
1126
Quentin Glidiccde13452016-08-12 10:41:32 +02001127/** Send wl_keyboard.modifiers events to focused resources and pointer
1128 * focused resources.
1129 *
1130 * \param keyboard The keyboard where the modifiers events originates from.
1131 * \param serial The serial of the event
1132 * \param mods_depressed The mods_depressed value of the event
1133 * \param mods_latched The mods_latched value of the event
1134 * \param mods_locked The mods_locked value of the event
1135 * \param group The group value of the event
1136 *
1137 * For every resource that is currently in focus, send a wl_keyboard.modifiers
1138 * event with the passed parameters. The focused resources are the wl_keyboard
1139 * resources of the client which currently has the surface with keyboard focus.
1140 * This also sends wl_keyboard.modifiers events to the wl_keyboard resources of
1141 * the client having pointer focus (if different from the keyboard focus client).
1142 */
1143WL_EXPORT void
1144weston_keyboard_send_modifiers(struct weston_keyboard *keyboard,
1145 uint32_t serial, uint32_t mods_depressed,
1146 uint32_t mods_latched,
1147 uint32_t mods_locked, uint32_t group)
1148{
1149 struct weston_pointer *pointer =
1150 weston_seat_get_pointer(keyboard->seat);
1151
1152 if (weston_keyboard_has_focus_resource(keyboard)) {
1153 struct wl_list *resource_list;
1154 struct wl_resource *resource;
1155
1156 resource_list = &keyboard->focus_resource_list;
1157 wl_resource_for_each(resource, resource_list) {
1158 wl_keyboard_send_modifiers(resource, serial,
1159 mods_depressed, mods_latched,
1160 mods_locked, group);
1161 }
1162 }
1163
1164 if (pointer && pointer->focus && pointer->focus->surface->resource &&
1165 pointer->focus->surface != keyboard->focus) {
1166 struct wl_client *pointer_client =
1167 wl_resource_get_client(pointer->focus->surface->resource);
1168
1169 send_modifiers_to_client_in_list(pointer_client,
1170 &keyboard->resource_list,
1171 serial,
1172 keyboard);
1173 }
1174}
1175
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001176static void
Kristian Høgsbergb27901c2013-10-28 15:32:02 -07001177default_grab_keyboard_modifiers(struct weston_keyboard_grab *grab,
1178 uint32_t serial, uint32_t mods_depressed,
1179 uint32_t mods_latched,
1180 uint32_t mods_locked, uint32_t group)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001181{
Quentin Glidiccde13452016-08-12 10:41:32 +02001182 weston_keyboard_send_modifiers(grab->keyboard, serial, mods_depressed,
1183 mods_latched, mods_locked, group);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001184}
1185
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02001186static void
1187default_grab_keyboard_cancel(struct weston_keyboard_grab *grab)
1188{
1189}
1190
Kristian Høgsberg29139d42013-04-18 15:25:39 -04001191static const struct weston_keyboard_grab_interface
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001192 default_keyboard_grab_interface = {
Kristian Høgsbergb27901c2013-10-28 15:32:02 -07001193 default_grab_keyboard_key,
1194 default_grab_keyboard_modifiers,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02001195 default_grab_keyboard_cancel,
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001196};
1197
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001198static void
1199pointer_unmap_sprite(struct weston_pointer *pointer)
1200{
Pekka Paalanenc557ff72014-11-12 16:42:52 +02001201 struct weston_surface *surface = pointer->sprite->surface;
1202
1203 if (weston_surface_is_mapped(surface))
1204 weston_surface_unmap(surface);
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001205
1206 wl_list_remove(&pointer->sprite_destroy_listener.link);
Quentin Glidic2edc3d52016-08-12 10:41:33 +02001207 surface->committed = NULL;
1208 surface->committed_private = NULL;
Pekka Paalanen8274d902014-08-06 19:36:51 +03001209 weston_surface_set_label_func(surface, NULL);
Jason Ekstranda7af7042013-10-12 22:38:11 -05001210 weston_view_destroy(pointer->sprite);
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001211 pointer->sprite = NULL;
1212}
1213
1214static void
1215pointer_handle_sprite_destroy(struct wl_listener *listener, void *data)
1216{
1217 struct weston_pointer *pointer =
1218 container_of(listener, struct weston_pointer,
1219 sprite_destroy_listener);
1220
1221 pointer->sprite = NULL;
1222}
1223
Jonas Ådahl3e12e632013-12-02 22:05:05 +01001224static void
1225weston_pointer_reset_state(struct weston_pointer *pointer)
1226{
1227 pointer->button_count = 0;
1228}
1229
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001230static void
1231weston_pointer_handle_output_destroy(struct wl_listener *listener, void *data);
1232
Pekka Paalanen1b043b12018-02-26 14:55:32 +02001233static struct weston_pointer *
Giulio Camuffocdb4d292013-11-14 23:42:53 +01001234weston_pointer_create(struct weston_seat *seat)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001235{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001236 struct weston_pointer *pointer;
1237
Peter Huttererf3d62272013-08-08 11:57:05 +10001238 pointer = zalloc(sizeof *pointer);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001239 if (pointer == NULL)
1240 return NULL;
1241
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001242 wl_list_init(&pointer->pointer_clients);
Giulio Camuffocdb4d292013-11-14 23:42:53 +01001243 weston_pointer_set_default_grab(pointer,
1244 seat->compositor->default_pointer_grab);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001245 wl_list_init(&pointer->focus_resource_listener.link);
1246 pointer->focus_resource_listener.notify = pointer_focus_resource_destroyed;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001247 pointer->default_grab.pointer = pointer;
1248 pointer->grab = &pointer->default_grab;
Giulio Camuffo6fcb3782013-11-14 23:42:50 +01001249 wl_signal_init(&pointer->motion_signal);
Emilio Pozuelo Monfortaa7a4762013-11-19 11:37:15 +01001250 wl_signal_init(&pointer->focus_signal);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001251 wl_list_init(&pointer->focus_view_listener.link);
Jonas Ådahl3eb4ddd2016-07-22 17:52:58 +08001252 wl_signal_init(&pointer->destroy_signal);
Alexandros Frantzisdb907b72018-02-20 14:06:26 +02001253 wl_list_init(&pointer->timestamps_list);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001254
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001255 pointer->sprite_destroy_listener.notify = pointer_handle_sprite_destroy;
1256
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001257 /* FIXME: Pick better co-ords. */
1258 pointer->x = wl_fixed_from_int(100);
1259 pointer->y = wl_fixed_from_int(100);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001260
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001261 pointer->output_destroy_listener.notify =
1262 weston_pointer_handle_output_destroy;
1263 wl_signal_add(&seat->compositor->output_destroyed_signal,
1264 &pointer->output_destroy_listener);
1265
Derek Foremanf9318d12015-05-11 15:40:11 -05001266 pointer->sx = wl_fixed_from_int(-1000000);
1267 pointer->sy = wl_fixed_from_int(-1000000);
1268
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001269 return pointer;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001270}
1271
Pekka Paalanen1b043b12018-02-26 14:55:32 +02001272static void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001273weston_pointer_destroy(struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001274{
Alexandros Frantzis1c3a40e2018-02-08 15:37:53 +02001275 struct weston_pointer_client *pointer_client, *tmp;
1276
Jonas Ådahl3eb4ddd2016-07-22 17:52:58 +08001277 wl_signal_emit(&pointer->destroy_signal, pointer);
1278
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001279 if (pointer->sprite)
1280 pointer_unmap_sprite(pointer);
1281
Alexandros Frantzis1c3a40e2018-02-08 15:37:53 +02001282 wl_list_for_each_safe(pointer_client, tmp, &pointer->pointer_clients,
1283 link) {
1284 wl_list_remove(&pointer_client->link);
1285 weston_pointer_client_destroy(pointer_client);
1286 }
Neil Roberts96d790e2013-09-19 17:32:00 +01001287
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001288 wl_list_remove(&pointer->focus_resource_listener.link);
1289 wl_list_remove(&pointer->focus_view_listener.link);
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001290 wl_list_remove(&pointer->output_destroy_listener.link);
Alexandros Frantzisdb907b72018-02-20 14:06:26 +02001291 wl_list_remove(&pointer->timestamps_list);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001292 free(pointer);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001293}
1294
Giulio Camuffocdb4d292013-11-14 23:42:53 +01001295void
1296weston_pointer_set_default_grab(struct weston_pointer *pointer,
1297 const struct weston_pointer_grab_interface *interface)
1298{
1299 if (interface)
1300 pointer->default_grab.interface = interface;
1301 else
1302 pointer->default_grab.interface =
1303 &default_pointer_grab_interface;
1304}
1305
Pekka Paalanen1b043b12018-02-26 14:55:32 +02001306static struct weston_keyboard *
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001307weston_keyboard_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001308{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001309 struct weston_keyboard *keyboard;
1310
Peter Huttererf3d62272013-08-08 11:57:05 +10001311 keyboard = zalloc(sizeof *keyboard);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001312 if (keyboard == NULL)
Neil Roberts96d790e2013-09-19 17:32:00 +01001313 return NULL;
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001314
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001315 wl_list_init(&keyboard->resource_list);
Neil Roberts96d790e2013-09-19 17:32:00 +01001316 wl_list_init(&keyboard->focus_resource_list);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001317 wl_list_init(&keyboard->focus_resource_listener.link);
1318 keyboard->focus_resource_listener.notify = keyboard_focus_resource_destroyed;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001319 wl_array_init(&keyboard->keys);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001320 keyboard->default_grab.interface = &default_keyboard_grab_interface;
1321 keyboard->default_grab.keyboard = keyboard;
1322 keyboard->grab = &keyboard->default_grab;
1323 wl_signal_init(&keyboard->focus_signal);
Alexandros Frantzis2b442482018-02-20 14:05:50 +02001324 wl_list_init(&keyboard->timestamps_list);
leng.fangdbaf6fa2024-06-20 19:31:04 +08001325 wl_list_init(&keyboard->intercept_resource);
1326 wl_list_init(&keyboard->key_info);
leng.fangbd0b8832024-08-09 18:36:50 +08001327 wl_list_init(&keyboard->virtual_key_info);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001328
1329 return keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001330}
1331
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001332static void
1333weston_xkb_info_destroy(struct weston_xkb_info *xkb_info);
1334
Pekka Paalanen1b043b12018-02-26 14:55:32 +02001335static void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001336weston_keyboard_destroy(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001337{
Alexandros Frantzis7a314d62018-01-26 18:47:56 +02001338 struct wl_resource *resource;
1339
1340 wl_resource_for_each(resource, &keyboard->resource_list) {
1341 wl_resource_set_user_data(resource, NULL);
1342 }
1343
1344 wl_resource_for_each(resource, &keyboard->focus_resource_list) {
1345 wl_resource_set_user_data(resource, NULL);
1346 }
1347
1348 wl_list_remove(&keyboard->resource_list);
1349 wl_list_remove(&keyboard->focus_resource_list);
Neil Roberts96d790e2013-09-19 17:32:00 +01001350
Derek Foreman185d1582017-06-28 11:17:23 -05001351 xkb_state_unref(keyboard->xkb_state.state);
1352 if (keyboard->xkb_info)
1353 weston_xkb_info_destroy(keyboard->xkb_info);
1354 xkb_keymap_unref(keyboard->pending_keymap);
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001355
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001356 wl_array_release(&keyboard->keys);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001357 wl_list_remove(&keyboard->focus_resource_listener.link);
Alexandros Frantzis2b442482018-02-20 14:05:50 +02001358 wl_list_remove(&keyboard->timestamps_list);
leng.fangdbaf6fa2024-06-20 19:31:04 +08001359 weston_keyboard_clear_key_intercept(keyboard);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001360 free(keyboard);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001361}
1362
Jonas Ådahlcbfa7f72013-12-02 22:05:04 +01001363static void
1364weston_touch_reset_state(struct weston_touch *touch)
1365{
1366 touch->num_tp = 0;
1367}
1368
Pekka Paalanen1b043b12018-02-26 14:55:32 +02001369static struct weston_touch *
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001370weston_touch_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001371{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001372 struct weston_touch *touch;
1373
Peter Huttererf3d62272013-08-08 11:57:05 +10001374 touch = zalloc(sizeof *touch);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001375 if (touch == NULL)
1376 return NULL;
1377
Louis-Francis Ratté-Boulianne6ef59c92017-11-28 20:42:47 -05001378 wl_list_init(&touch->device_list);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001379 wl_list_init(&touch->resource_list);
Neil Roberts96d790e2013-09-19 17:32:00 +01001380 wl_list_init(&touch->focus_resource_list);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001381 wl_list_init(&touch->focus_view_listener.link);
1382 touch->focus_view_listener.notify = touch_focus_view_destroyed;
1383 wl_list_init(&touch->focus_resource_listener.link);
1384 touch->focus_resource_listener.notify = touch_focus_resource_destroyed;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001385 touch->default_grab.interface = &default_touch_grab_interface;
1386 touch->default_grab.touch = touch;
1387 touch->grab = &touch->default_grab;
1388 wl_signal_init(&touch->focus_signal);
Alexandros Frantzisd7157842018-02-20 14:07:03 +02001389 wl_list_init(&touch->timestamps_list);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001390
1391 return touch;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001392}
1393
Pekka Paalanen1b043b12018-02-26 14:55:32 +02001394static void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001395weston_touch_destroy(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001396{
Alexandros Frantzisb0b598c2018-01-26 18:47:57 +02001397 struct wl_resource *resource;
Neil Roberts96d790e2013-09-19 17:32:00 +01001398
Louis-Francis Ratté-Boulianne6ef59c92017-11-28 20:42:47 -05001399 assert(wl_list_empty(&touch->device_list));
1400
Alexandros Frantzisb0b598c2018-01-26 18:47:57 +02001401 wl_resource_for_each(resource, &touch->resource_list) {
1402 wl_resource_set_user_data(resource, NULL);
1403 }
1404
1405 wl_resource_for_each(resource, &touch->focus_resource_list) {
1406 wl_resource_set_user_data(resource, NULL);
1407 }
1408
1409 wl_list_remove(&touch->resource_list);
1410 wl_list_remove(&touch->focus_resource_list);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001411 wl_list_remove(&touch->focus_view_listener.link);
1412 wl_list_remove(&touch->focus_resource_listener.link);
Alexandros Frantzisd7157842018-02-20 14:07:03 +02001413 wl_list_remove(&touch->timestamps_list);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001414 free(touch);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001415}
1416
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001417static void
Kristian Høgsberge3148752013-05-06 23:19:49 -04001418seat_send_updated_caps(struct weston_seat *seat)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001419{
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001420 enum wl_seat_capability caps = 0;
Rob Bradford6e737f52013-09-06 17:48:19 +01001421 struct wl_resource *resource;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001422
Jonas Ådahld6e1c342013-10-17 23:04:05 +02001423 if (seat->pointer_device_count > 0)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001424 caps |= WL_SEAT_CAPABILITY_POINTER;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02001425 if (seat->keyboard_device_count > 0)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001426 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02001427 if (seat->touch_device_count > 0)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001428 caps |= WL_SEAT_CAPABILITY_TOUCH;
1429
Rob Bradford6e737f52013-09-06 17:48:19 +01001430 wl_resource_for_each(resource, &seat->base_resource_list) {
1431 wl_seat_send_capabilities(resource, caps);
Jason Ekstrand44a38632013-06-14 10:08:00 -05001432 }
Jason Ekstranda4ab5422014-04-02 19:53:45 -05001433 wl_signal_emit(&seat->updated_caps_signal, seat);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001434}
1435
Derek Foremanf9318d12015-05-11 15:40:11 -05001436
1437/** Clear the pointer focus
1438 *
1439 * \param pointer the pointer to clear focus for.
1440 *
1441 * This can be used to unset pointer focus and set the co-ordinates to the
1442 * arbitrary values we use for the no focus case.
1443 *
1444 * There's no requirement to use this function. For example, passing the
1445 * results of a weston_compositor_pick_view() directly to
1446 * weston_pointer_set_focus() will do the right thing when no view is found.
1447 */
1448WL_EXPORT void
1449weston_pointer_clear_focus(struct weston_pointer *pointer)
1450{
1451 weston_pointer_set_focus(pointer, NULL,
1452 wl_fixed_from_int(-1000000),
1453 wl_fixed_from_int(-1000000));
1454}
1455
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001456WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001457weston_pointer_set_focus(struct weston_pointer *pointer,
Jason Ekstranda7af7042013-10-12 22:38:11 -05001458 struct weston_view *view,
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001459 wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001460{
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001461 struct weston_pointer_client *pointer_client;
Derek Foreman1281a362015-07-31 16:55:32 -05001462 struct weston_keyboard *kbd = weston_seat_get_keyboard(pointer->seat);
Neil Roberts96d790e2013-09-19 17:32:00 +01001463 struct wl_resource *resource;
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001464 struct wl_resource *surface_resource;
Rob Bradford880ebc72013-07-22 17:31:38 +01001465 struct wl_display *display = pointer->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001466 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +01001467 struct wl_list *focus_resource_list;
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -08001468 int refocus = 0;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001469
1470 if ((!pointer->focus && view) ||
1471 (pointer->focus && !view) ||
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -08001472 (pointer->focus && pointer->focus->surface != view->surface) ||
1473 pointer->sx != sx || pointer->sy != sy)
1474 refocus = 1;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001475
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001476 if (pointer->focus_client && refocus) {
1477 focus_resource_list = &pointer->focus_client->pointer_resources;
1478 if (!wl_list_empty(focus_resource_list)) {
1479 serial = wl_display_next_serial(display);
1480 surface_resource = pointer->focus->surface->resource;
1481 wl_resource_for_each(resource, focus_resource_list) {
1482 wl_pointer_send_leave(resource, serial,
1483 surface_resource);
Peter Hutterer87743e92016-01-18 16:38:22 +10001484 pointer_send_frame(resource);
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001485 }
Neil Roberts96d790e2013-09-19 17:32:00 +01001486 }
1487
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001488 pointer->focus_client = NULL;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001489 }
1490
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001491 pointer_client = find_pointer_client_for_view(pointer, view);
1492 if (pointer_client && refocus) {
1493 struct wl_client *surface_client = pointer_client->client;
Neil Roberts96d790e2013-09-19 17:32:00 +01001494
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001495 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +01001496
Jason Ekstranda7af7042013-10-12 22:38:11 -05001497 if (kbd && kbd->focus != view->surface)
Kristian Høgsbergcb406f12013-10-09 10:54:03 -07001498 send_modifiers_to_client_in_list(surface_client,
1499 &kbd->resource_list,
1500 serial,
1501 kbd);
1502
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001503 pointer->focus_client = pointer_client;
Neil Roberts96d790e2013-09-19 17:32:00 +01001504
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001505 focus_resource_list = &pointer->focus_client->pointer_resources;
Neil Roberts96d790e2013-09-19 17:32:00 +01001506 wl_resource_for_each(resource, focus_resource_list) {
1507 wl_pointer_send_enter(resource,
1508 serial,
Jason Ekstranda7af7042013-10-12 22:38:11 -05001509 view->surface->resource,
Neil Roberts96d790e2013-09-19 17:32:00 +01001510 sx, sy);
Peter Hutterer87743e92016-01-18 16:38:22 +10001511 pointer_send_frame(resource);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001512 }
Neil Roberts96d790e2013-09-19 17:32:00 +01001513
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001514 pointer->focus_serial = serial;
1515 }
1516
Giulio Camuffo65a07f82013-12-06 12:46:27 +01001517 wl_list_remove(&pointer->focus_view_listener.link);
1518 wl_list_init(&pointer->focus_view_listener.link);
1519 wl_list_remove(&pointer->focus_resource_listener.link);
1520 wl_list_init(&pointer->focus_resource_listener.link);
Emilio Pozuelo Monfortaa7a4762013-11-19 11:37:15 +01001521 if (view)
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001522 wl_signal_add(&view->destroy_signal, &pointer->focus_view_listener);
Giulio Camuffo65a07f82013-12-06 12:46:27 +01001523 if (view && view->surface->resource)
1524 wl_resource_add_destroy_listener(view->surface->resource,
1525 &pointer->focus_resource_listener);
1526
1527 pointer->focus = view;
1528 pointer->focus_view_listener.notify = pointer_focus_view_destroyed;
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -08001529 pointer->sx = sx;
1530 pointer->sy = sy;
1531
Derek Foremanf9318d12015-05-11 15:40:11 -05001532 assert(view || sx == wl_fixed_from_int(-1000000));
1533 assert(view || sy == wl_fixed_from_int(-1000000));
1534
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001535 wl_signal_emit(&pointer->focus_signal, pointer);
1536}
1537
Neil Roberts96d790e2013-09-19 17:32:00 +01001538static void
1539send_enter_to_resource_list(struct wl_list *list,
1540 struct weston_keyboard *keyboard,
1541 struct weston_surface *surface,
1542 uint32_t serial)
1543{
1544 struct wl_resource *resource;
1545
1546 wl_resource_for_each(resource, list) {
Neil Roberts96d790e2013-09-19 17:32:00 +01001547 wl_keyboard_send_enter(resource, serial,
1548 surface->resource,
1549 &keyboard->keys);
Kirill Chibisovc46c70d2020-06-17 01:43:57 +03001550 send_modifiers_to_resource(keyboard, resource, serial);
Neil Roberts96d790e2013-09-19 17:32:00 +01001551 }
1552}
1553
leng.fang32af9fc2024-06-13 11:22:15 +08001554static bool weston_keyboard_need_enter_surface( struct weston_keyboard *keyboard,
1555 struct weston_surface *surface)
1556{
1557 bool enter = false;
1558 if ( (find_resource_for_surface(&keyboard->resource_list, surface)
1559 || find_resource_for_surface(&keyboard->focus_resource_list, surface)) &&
1560 keyboard->focus != surface ) {
1561 enter = true;
1562 }
1563 weston_log("\n %s %d, enter surface:%p, enter:%d222\n", __FUNCTION__,__LINE__, surface, enter);
1564 return enter;
1565}
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001566WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -04001567weston_keyboard_set_focus(struct weston_keyboard *keyboard,
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -04001568 struct weston_surface *surface)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001569{
Quentin Glidic85d55542017-07-21 14:02:40 +02001570 struct weston_seat *seat = keyboard->seat;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001571 struct wl_resource *resource;
Rob Bradford880ebc72013-07-22 17:31:38 +01001572 struct wl_display *display = keyboard->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001573 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +01001574 struct wl_list *focus_resource_list;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001575
Pekka Paalanen72e183b2018-02-22 16:55:15 +02001576 /* Keyboard focus on a surface without a client is equivalent to NULL
1577 * focus as nothing would react to the keyboard events anyway.
1578 * Just set focus to NULL instead - the destroy listener hangs on the
1579 * wl_resource anyway.
1580 */
1581 if (surface && !surface->resource)
1582 surface = NULL;
1583
Neil Roberts96d790e2013-09-19 17:32:00 +01001584 focus_resource_list = &keyboard->focus_resource_list;
1585
leng.fang32af9fc2024-06-13 11:22:15 +08001586 if (weston_keyboard_need_enter_surface( keyboard, surface ) || surface == NULL)
1587 {
1588 if (!wl_list_empty(focus_resource_list) && keyboard->focus != surface) {
1589 serial = wl_display_next_serial(display);
1590 wl_resource_for_each(resource, focus_resource_list) {
leng.fange9d800e2024-07-12 13:31:59 +08001591 if (keyboard && keyboard->focus)
1592 keyboard->focus->compositor->last_keyboard_focus = keyboard->focus;
leng.fang32af9fc2024-06-13 11:22:15 +08001593 weston_log("\n %s %d, leave surface:%p\n", __FUNCTION__,__LINE__, keyboard->focus);
1594 wl_keyboard_send_leave(resource, serial,
1595 keyboard->focus->resource);
1596 }
1597 move_resources(&keyboard->resource_list, focus_resource_list);
leng.fangdbaf6fa2024-06-20 19:31:04 +08001598 }
1599 if ( surface == NULL && keyboard && keyboard->focus) {
1600 surface = keyboard->focus->compositor->last_keyboard_focus;
1601 if (surface == keyboard->focus)
1602 surface = NULL;
1603 weston_log("\n %s %d, need back to surface:%p\n", __FUNCTION__,__LINE__, surface);
Neil Roberts96d790e2013-09-19 17:32:00 +01001604 }
leng.fang32af9fc2024-06-13 11:22:15 +08001605
1606 if (find_resource_for_surface(&keyboard->resource_list, surface) &&
1607 keyboard->focus != surface) {
1608 struct wl_client *surface_client =
1609 wl_resource_get_client(surface->resource);
1610
1611 serial = wl_display_next_serial(display);
1612
1613 move_resources_for_client(focus_resource_list,
1614 &keyboard->resource_list,
1615 surface_client);
1616 send_enter_to_resource_list(focus_resource_list,
1617 keyboard,
1618 surface,
1619 serial);
1620 keyboard->focus_serial = serial;
1621 }
1622
1623 /* Since this function gets called from the surface destroy handler
1624 * we can't just remove the kbd focus listener, or we might corrupt
1625 * the list it's in.
1626 * Instead, we'll just set a flag to ignore the focus when the
1627 * compositor regains kbd focus.
1628 */
1629 seat->use_saved_kbd_focus = false;
1630
1631 wl_list_remove(&keyboard->focus_resource_listener.link);
1632 wl_list_init(&keyboard->focus_resource_listener.link);
1633 if (surface)
1634 wl_resource_add_destroy_listener(surface->resource,
1635 &keyboard->focus_resource_listener);
1636
1637 keyboard->focus = surface;
1638 wl_signal_emit(&keyboard->focus_signal, keyboard);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001639 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001640}
1641
Giulio Camuffoa20ca812014-11-22 11:16:56 +02001642/* Users of this function must manually manage the keyboard focus */
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001643WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -04001644weston_keyboard_start_grab(struct weston_keyboard *keyboard,
1645 struct weston_keyboard_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001646{
1647 keyboard->grab = grab;
1648 grab->keyboard = keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001649}
1650
1651WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -04001652weston_keyboard_end_grab(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001653{
1654 keyboard->grab = &keyboard->default_grab;
1655}
1656
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02001657static void
1658weston_keyboard_cancel_grab(struct weston_keyboard *keyboard)
1659{
1660 keyboard->grab->interface->cancel(keyboard->grab);
1661}
1662
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001663WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001664weston_pointer_start_grab(struct weston_pointer *pointer,
1665 struct weston_pointer_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001666{
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001667 pointer->grab = grab;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001668 grab->pointer = pointer;
Kristian Høgsbergda751b82013-07-04 00:58:07 -04001669 pointer->grab->interface->focus(pointer->grab);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001670}
1671
1672WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001673weston_pointer_end_grab(struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001674{
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001675 pointer->grab = &pointer->default_grab;
Kristian Høgsbergda751b82013-07-04 00:58:07 -04001676 pointer->grab->interface->focus(pointer->grab);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001677}
1678
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02001679static void
1680weston_pointer_cancel_grab(struct weston_pointer *pointer)
1681{
1682 pointer->grab->interface->cancel(pointer->grab);
1683}
1684
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001685WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -04001686weston_touch_start_grab(struct weston_touch *touch, struct weston_touch_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001687{
1688 touch->grab = grab;
1689 grab->touch = touch;
1690}
1691
1692WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -04001693weston_touch_end_grab(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001694{
1695 touch->grab = &touch->default_grab;
1696}
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001697
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02001698static void
1699weston_touch_cancel_grab(struct weston_touch *touch)
1700{
1701 touch->grab->interface->cancel(touch->grab);
1702}
1703
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001704static void
1705weston_pointer_clamp_for_output(struct weston_pointer *pointer,
1706 struct weston_output *output,
1707 wl_fixed_t *fx, wl_fixed_t *fy)
1708{
1709 int x, y;
1710
1711 x = wl_fixed_to_int(*fx);
1712 y = wl_fixed_to_int(*fy);
1713
1714 if (x < output->x)
1715 *fx = wl_fixed_from_int(output->x);
1716 else if (x >= output->x + output->width)
1717 *fx = wl_fixed_from_int(output->x +
1718 output->width - 1);
1719 if (y < output->y)
1720 *fy = wl_fixed_from_int(output->y);
1721 else if (y >= output->y + output->height)
1722 *fy = wl_fixed_from_int(output->y +
1723 output->height - 1);
1724}
1725
Rob Bradford806d8c02013-06-25 18:56:41 +01001726WL_EXPORT void
1727weston_pointer_clamp(struct weston_pointer *pointer, wl_fixed_t *fx, wl_fixed_t *fy)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001728{
Rob Bradford806d8c02013-06-25 18:56:41 +01001729 struct weston_compositor *ec = pointer->seat->compositor;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001730 struct weston_output *output, *prev = NULL;
1731 int x, y, old_x, old_y, valid = 0;
1732
1733 x = wl_fixed_to_int(*fx);
1734 y = wl_fixed_to_int(*fy);
Rob Bradford806d8c02013-06-25 18:56:41 +01001735 old_x = wl_fixed_to_int(pointer->x);
1736 old_y = wl_fixed_to_int(pointer->y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001737
1738 wl_list_for_each(output, &ec->output_list, link) {
Rob Bradford66bd9f52013-06-25 18:56:42 +01001739 if (pointer->seat->output && pointer->seat->output != output)
1740 continue;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001741 if (pixman_region32_contains_point(&output->region,
1742 x, y, NULL))
1743 valid = 1;
1744 if (pixman_region32_contains_point(&output->region,
1745 old_x, old_y, NULL))
1746 prev = output;
1747 }
1748
Rob Bradford66bd9f52013-06-25 18:56:42 +01001749 if (!prev)
1750 prev = pointer->seat->output;
1751
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001752 if (prev && !valid)
1753 weston_pointer_clamp_for_output(pointer, prev, fx, fy);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001754}
1755
Jonas Ådahld2510102014-10-05 21:39:14 +02001756static void
1757weston_pointer_move_to(struct weston_pointer *pointer,
1758 wl_fixed_t x, wl_fixed_t y)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001759{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001760 int32_t ix, iy;
1761
Rob Bradford806d8c02013-06-25 18:56:41 +01001762 weston_pointer_clamp (pointer, &x, &y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001763
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001764 pointer->x = x;
1765 pointer->y = y;
1766
1767 ix = wl_fixed_to_int(x);
1768 iy = wl_fixed_to_int(y);
1769
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001770 if (pointer->sprite) {
Jason Ekstranda7af7042013-10-12 22:38:11 -05001771 weston_view_set_position(pointer->sprite,
1772 ix - pointer->hotspot_x,
1773 iy - pointer->hotspot_y);
1774 weston_view_schedule_repaint(pointer->sprite);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001775 }
Giulio Camuffo6fcb3782013-11-14 23:42:50 +01001776
Giulio Camuffo1959ab82013-11-14 23:42:52 +01001777 pointer->grab->interface->focus(pointer->grab);
Giulio Camuffo6fcb3782013-11-14 23:42:50 +01001778 wl_signal_emit(&pointer->motion_signal, pointer);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001779}
1780
Jonas Ådahld2510102014-10-05 21:39:14 +02001781WL_EXPORT void
Jonas Ådahld2510102014-10-05 21:39:14 +02001782weston_pointer_move(struct weston_pointer *pointer,
1783 struct weston_pointer_motion_event *event)
1784{
1785 wl_fixed_t x, y;
1786
1787 weston_pointer_motion_to_abs(pointer, event, &x, &y);
1788 weston_pointer_move_to(pointer, x, y);
1789}
1790
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001791/** Verify if the pointer is in a valid position and move it if it isn't.
1792 */
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001793static void
1794weston_pointer_handle_output_destroy(struct wl_listener *listener, void *data)
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001795{
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001796 struct weston_pointer *pointer;
1797 struct weston_compositor *ec;
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001798 struct weston_output *output, *closest = NULL;
1799 int x, y, distance, min = INT_MAX;
1800 wl_fixed_t fx, fy;
1801
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001802 pointer = container_of(listener, struct weston_pointer,
1803 output_destroy_listener);
1804 ec = pointer->seat->compositor;
1805
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001806 x = wl_fixed_to_int(pointer->x);
1807 y = wl_fixed_to_int(pointer->y);
1808
1809 wl_list_for_each(output, &ec->output_list, link) {
1810 if (pixman_region32_contains_point(&output->region,
1811 x, y, NULL))
1812 return;
1813
1814 /* Aproximante the distance from the pointer to the center of
1815 * the output. */
1816 distance = abs(output->x + output->width / 2 - x) +
1817 abs(output->y + output->height / 2 - y);
1818 if (distance < min) {
1819 min = distance;
1820 closest = output;
1821 }
1822 }
1823
1824 /* Nothing to do if there's no output left. */
1825 if (!closest)
1826 return;
1827
1828 fx = pointer->x;
1829 fy = pointer->y;
1830
1831 weston_pointer_clamp_for_output(pointer, closest, &fx, &fy);
Jonas Ådahld2510102014-10-05 21:39:14 +02001832 weston_pointer_move_to(pointer, fx, fy);
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001833}
1834
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001835WL_EXPORT void
1836notify_motion(struct weston_seat *seat,
Alexandros Frantzis84b31f82017-11-24 18:01:46 +02001837 const struct timespec *time,
Jonas Ådahld2510102014-10-05 21:39:14 +02001838 struct weston_pointer_motion_event *event)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001839{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001840 struct weston_compositor *ec = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001841 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001842
1843 weston_compositor_wake(ec);
Jonas Ådahld2510102014-10-05 21:39:14 +02001844 pointer->grab->interface->motion(pointer->grab, time, event);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001845}
1846
Daniel Stone96d47c02013-11-19 11:37:12 +01001847static void
1848run_modifier_bindings(struct weston_seat *seat, uint32_t old, uint32_t new)
1849{
1850 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001851 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Daniel Stone96d47c02013-11-19 11:37:12 +01001852 uint32_t diff;
1853 unsigned int i;
1854 struct {
1855 uint32_t xkb;
1856 enum weston_keyboard_modifier weston;
1857 } mods[] = {
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001858 { keyboard->xkb_info->ctrl_mod, MODIFIER_CTRL },
1859 { keyboard->xkb_info->alt_mod, MODIFIER_ALT },
1860 { keyboard->xkb_info->super_mod, MODIFIER_SUPER },
1861 { keyboard->xkb_info->shift_mod, MODIFIER_SHIFT },
Daniel Stone96d47c02013-11-19 11:37:12 +01001862 };
1863
1864 diff = new & ~old;
1865 for (i = 0; i < ARRAY_LENGTH(mods); i++) {
1866 if (diff & (1 << mods[i].xkb))
1867 weston_compositor_run_modifier_binding(compositor,
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001868 keyboard,
Daniel Stone96d47c02013-11-19 11:37:12 +01001869 mods[i].weston,
1870 WL_KEYBOARD_KEY_STATE_PRESSED);
1871 }
1872
1873 diff = old & ~new;
1874 for (i = 0; i < ARRAY_LENGTH(mods); i++) {
1875 if (diff & (1 << mods[i].xkb))
1876 weston_compositor_run_modifier_binding(compositor,
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001877 keyboard,
Daniel Stone96d47c02013-11-19 11:37:12 +01001878 mods[i].weston,
1879 WL_KEYBOARD_KEY_STATE_RELEASED);
1880 }
1881}
1882
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001883WL_EXPORT void
Alexandros Frantzis84b31f82017-11-24 18:01:46 +02001884notify_motion_absolute(struct weston_seat *seat, const struct timespec *time,
1885 double x, double y)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001886{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001887 struct weston_compositor *ec = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001888 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Jonas Ådahld2510102014-10-05 21:39:14 +02001889 struct weston_pointer_motion_event event = { 0 };
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001890
1891 weston_compositor_wake(ec);
Jonas Ådahld2510102014-10-05 21:39:14 +02001892
1893 event = (struct weston_pointer_motion_event) {
1894 .mask = WESTON_POINTER_MOTION_ABS,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001895 .x = x,
1896 .y = y,
Jonas Ådahld2510102014-10-05 21:39:14 +02001897 };
1898
1899 pointer->grab->interface->motion(pointer->grab, time, &event);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001900}
1901
Jonas Ådahl94e2e2d2014-10-18 18:42:19 +02001902static unsigned int
1903peek_next_activate_serial(struct weston_compositor *c)
1904{
1905 unsigned serial = c->activate_serial + 1;
1906
1907 return serial == 0 ? 1 : serial;
1908}
1909
1910static void
1911inc_activate_serial(struct weston_compositor *c)
1912{
1913 c->activate_serial = peek_next_activate_serial (c);
1914}
1915
1916WL_EXPORT void
Marius Vladd6ccc8b2021-03-05 22:07:30 +02001917weston_view_activate_input(struct weston_view *view,
Jonas Ådahl94e2e2d2014-10-18 18:42:19 +02001918 struct weston_seat *seat,
1919 uint32_t flags)
1920{
1921 struct weston_compositor *compositor = seat->compositor;
1922
1923 if (flags & WESTON_ACTIVATE_FLAG_CLICKED) {
1924 view->click_to_activate_serial =
1925 peek_next_activate_serial(compositor);
1926 }
1927
1928 weston_seat_set_keyboard_focus(seat, view->surface);
1929}
1930
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001931WL_EXPORT void
Alexandros Frantzis215bedc2017-11-16 18:20:55 +02001932notify_button(struct weston_seat *seat, const struct timespec *time,
1933 int32_t button, enum wl_pointer_button_state state)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001934{
1935 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001936 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001937
1938 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001939 weston_compositor_idle_inhibit(compositor);
1940 if (pointer->button_count == 0) {
1941 pointer->grab_button = button;
Alexandros Frantzis215bedc2017-11-16 18:20:55 +02001942 pointer->grab_time = *time;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001943 pointer->grab_x = pointer->x;
1944 pointer->grab_y = pointer->y;
1945 }
1946 pointer->button_count++;
1947 } else {
1948 weston_compositor_idle_release(compositor);
1949 pointer->button_count--;
1950 }
1951
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001952 weston_compositor_run_button_binding(compositor, pointer, time, button,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001953 state);
1954
1955 pointer->grab->interface->button(pointer->grab, time, button, state);
1956
1957 if (pointer->button_count == 1)
1958 pointer->grab_serial =
1959 wl_display_get_serial(compositor->wl_display);
1960}
1961
1962WL_EXPORT void
Alexandros Frantzis80321942017-11-16 18:20:56 +02001963notify_axis(struct weston_seat *seat, const struct timespec *time,
Peter Hutterer89b6a492016-01-18 15:58:17 +10001964 struct weston_pointer_axis_event *event)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001965{
1966 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001967 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001968
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001969 weston_compositor_wake(compositor);
1970
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001971 if (weston_compositor_run_axis_binding(compositor, pointer,
Peter Hutterer89b6a492016-01-18 15:58:17 +10001972 time, event))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001973 return;
1974
Peter Hutterer89b6a492016-01-18 15:58:17 +10001975 pointer->grab->interface->axis(pointer->grab, time, event);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001976}
1977
Peter Hutterer87743e92016-01-18 16:38:22 +10001978WL_EXPORT void
1979notify_axis_source(struct weston_seat *seat, uint32_t source)
1980{
1981 struct weston_compositor *compositor = seat->compositor;
1982 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1983
1984 weston_compositor_wake(compositor);
1985
1986 pointer->grab->interface->axis_source(pointer->grab, source);
1987}
1988
1989WL_EXPORT void
1990notify_pointer_frame(struct weston_seat *seat)
1991{
1992 struct weston_compositor *compositor = seat->compositor;
1993 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1994
1995 weston_compositor_wake(compositor);
1996
1997 pointer->grab->interface->frame(pointer->grab);
1998}
1999
Giulio Camuffo6ef444d2014-08-28 19:44:09 +03002000WL_EXPORT int
2001weston_keyboard_set_locks(struct weston_keyboard *keyboard,
2002 uint32_t mask, uint32_t value)
2003{
Giulio Camuffo6ef444d2014-08-28 19:44:09 +03002004 uint32_t serial;
2005 xkb_mod_mask_t mods_depressed, mods_latched, mods_locked, group;
2006 xkb_mod_mask_t num, caps;
2007
2008 /* We don't want the leds to go out of sync with the actual state
2009 * so if the backend has no way to change the leds don't try to
2010 * change the state */
2011 if (!keyboard->seat->led_update)
2012 return -1;
2013
2014 mods_depressed = xkb_state_serialize_mods(keyboard->xkb_state.state,
2015 XKB_STATE_DEPRESSED);
2016 mods_latched = xkb_state_serialize_mods(keyboard->xkb_state.state,
2017 XKB_STATE_LATCHED);
2018 mods_locked = xkb_state_serialize_mods(keyboard->xkb_state.state,
2019 XKB_STATE_LOCKED);
2020 group = xkb_state_serialize_group(keyboard->xkb_state.state,
Emmanuel Gil Peyroteff793a2021-07-31 17:25:41 +02002021 XKB_STATE_EFFECTIVE);
Giulio Camuffo6ef444d2014-08-28 19:44:09 +03002022
2023 num = (1 << keyboard->xkb_info->mod2_mod);
2024 caps = (1 << keyboard->xkb_info->caps_mod);
2025 if (mask & WESTON_NUM_LOCK) {
2026 if (value & WESTON_NUM_LOCK)
2027 mods_locked |= num;
2028 else
2029 mods_locked &= ~num;
2030 }
2031 if (mask & WESTON_CAPS_LOCK) {
2032 if (value & WESTON_CAPS_LOCK)
2033 mods_locked |= caps;
2034 else
2035 mods_locked &= ~caps;
2036 }
2037
2038 xkb_state_update_mask(keyboard->xkb_state.state, mods_depressed,
2039 mods_latched, mods_locked, 0, 0, group);
2040
2041 serial = wl_display_next_serial(
2042 keyboard->seat->compositor->wl_display);
2043 notify_modifiers(keyboard->seat, serial);
2044
2045 return 0;
Giulio Camuffo6ef444d2014-08-28 19:44:09 +03002046}
2047
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002048WL_EXPORT void
2049notify_modifiers(struct weston_seat *seat, uint32_t serial)
2050{
Derek Foreman1281a362015-07-31 16:55:32 -05002051 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002052 struct weston_keyboard_grab *grab = keyboard->grab;
2053 uint32_t mods_depressed, mods_latched, mods_locked, group;
2054 uint32_t mods_lookup;
2055 enum weston_led leds = 0;
2056 int changed = 0;
2057
2058 /* Serialize and update our internal state, checking to see if it's
2059 * different to the previous state. */
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002060 mods_depressed = xkb_state_serialize_mods(keyboard->xkb_state.state,
Ran Benita2e1968f2014-08-19 23:59:51 +03002061 XKB_STATE_MODS_DEPRESSED);
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002062 mods_latched = xkb_state_serialize_mods(keyboard->xkb_state.state,
Ran Benita2e1968f2014-08-19 23:59:51 +03002063 XKB_STATE_MODS_LATCHED);
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002064 mods_locked = xkb_state_serialize_mods(keyboard->xkb_state.state,
Ran Benita2e1968f2014-08-19 23:59:51 +03002065 XKB_STATE_MODS_LOCKED);
2066 group = xkb_state_serialize_layout(keyboard->xkb_state.state,
2067 XKB_STATE_LAYOUT_EFFECTIVE);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002068
Derek Foreman244e99e2015-06-03 15:53:26 -05002069 if (mods_depressed != keyboard->modifiers.mods_depressed ||
2070 mods_latched != keyboard->modifiers.mods_latched ||
2071 mods_locked != keyboard->modifiers.mods_locked ||
2072 group != keyboard->modifiers.group)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002073 changed = 1;
2074
Derek Foreman244e99e2015-06-03 15:53:26 -05002075 run_modifier_bindings(seat, keyboard->modifiers.mods_depressed,
Daniel Stone96d47c02013-11-19 11:37:12 +01002076 mods_depressed);
2077
Derek Foreman244e99e2015-06-03 15:53:26 -05002078 keyboard->modifiers.mods_depressed = mods_depressed;
2079 keyboard->modifiers.mods_latched = mods_latched;
2080 keyboard->modifiers.mods_locked = mods_locked;
2081 keyboard->modifiers.group = group;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002082
2083 /* And update the modifier_state for bindings. */
2084 mods_lookup = mods_depressed | mods_latched;
2085 seat->modifier_state = 0;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002086 if (mods_lookup & (1 << keyboard->xkb_info->ctrl_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002087 seat->modifier_state |= MODIFIER_CTRL;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002088 if (mods_lookup & (1 << keyboard->xkb_info->alt_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002089 seat->modifier_state |= MODIFIER_ALT;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002090 if (mods_lookup & (1 << keyboard->xkb_info->super_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002091 seat->modifier_state |= MODIFIER_SUPER;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002092 if (mods_lookup & (1 << keyboard->xkb_info->shift_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002093 seat->modifier_state |= MODIFIER_SHIFT;
2094
2095 /* Finally, notify the compositor that LEDs have changed. */
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002096 if (xkb_state_led_index_is_active(keyboard->xkb_state.state,
2097 keyboard->xkb_info->num_led))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002098 leds |= LED_NUM_LOCK;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002099 if (xkb_state_led_index_is_active(keyboard->xkb_state.state,
2100 keyboard->xkb_info->caps_led))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002101 leds |= LED_CAPS_LOCK;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002102 if (xkb_state_led_index_is_active(keyboard->xkb_state.state,
2103 keyboard->xkb_info->scroll_led))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002104 leds |= LED_SCROLL_LOCK;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002105 if (leds != keyboard->xkb_state.leds && seat->led_update)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002106 seat->led_update(seat, leds);
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002107 keyboard->xkb_state.leds = leds;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002108
2109 if (changed) {
2110 grab->interface->modifiers(grab,
2111 serial,
2112 keyboard->modifiers.mods_depressed,
2113 keyboard->modifiers.mods_latched,
2114 keyboard->modifiers.mods_locked,
2115 keyboard->modifiers.group);
2116 }
2117}
2118
2119static void
2120update_modifier_state(struct weston_seat *seat, uint32_t serial, uint32_t key,
2121 enum wl_keyboard_key_state state)
2122{
Derek Foreman1281a362015-07-31 16:55:32 -05002123 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002124 enum xkb_key_direction direction;
2125
2126 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
2127 direction = XKB_KEY_DOWN;
2128 else
2129 direction = XKB_KEY_UP;
2130
2131 /* Offset the keycode by 8, as the evdev XKB rules reflect X's
2132 * broken keycode system, which starts at 8. */
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002133 xkb_state_update_key(keyboard->xkb_state.state, key + 8, direction);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002134
2135 notify_modifiers(seat, serial);
2136}
Rui Matos65196bc2013-10-10 19:44:19 +02002137
Derek Foremanf8f7fd62017-06-28 11:41:43 -05002138WL_EXPORT void
2139weston_keyboard_send_keymap(struct weston_keyboard *kbd, struct wl_resource *resource)
Rui Matos65196bc2013-10-10 19:44:19 +02002140{
Derek Foremanf8f7fd62017-06-28 11:41:43 -05002141 struct weston_xkb_info *xkb_info = kbd->xkb_info;
Derek Foreman76829fc2017-06-28 12:17:46 -05002142 int fd;
Sebastian Wickabec5122019-11-01 02:38:45 +01002143 size_t size;
2144 enum ro_anonymous_file_mapmode mapmode;
Derek Foremanf8f7fd62017-06-28 11:41:43 -05002145
Sebastian Wickabec5122019-11-01 02:38:45 +01002146 if (wl_resource_get_version(resource) < 7)
2147 mapmode = RO_ANONYMOUS_FILE_MAPMODE_SHARED;
2148 else
2149 mapmode = RO_ANONYMOUS_FILE_MAPMODE_PRIVATE;
2150
2151 fd = os_ro_anonymous_file_get_fd(xkb_info->keymap_rofile, mapmode);
2152 size = os_ro_anonymous_file_size(xkb_info->keymap_rofile);
2153
2154 if (fd == -1) {
2155 weston_log("creating a keymap file failed: %s\n",
Antonio Borneo39578632019-04-26 23:57:31 +02002156 strerror(errno));
Derek Foreman76829fc2017-06-28 12:17:46 -05002157 return;
2158 }
2159
Rui Matos65196bc2013-10-10 19:44:19 +02002160 wl_keyboard_send_keymap(resource,
2161 WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
Derek Foreman76829fc2017-06-28 12:17:46 -05002162 fd,
Sebastian Wickabec5122019-11-01 02:38:45 +01002163 size);
2164
2165 os_ro_anonymous_file_put_fd(fd);
Rui Matos65196bc2013-10-10 19:44:19 +02002166}
2167
2168static void
2169send_modifiers(struct wl_resource *resource, uint32_t serial, struct weston_keyboard *keyboard)
2170{
2171 wl_keyboard_send_modifiers(resource, serial,
2172 keyboard->modifiers.mods_depressed,
2173 keyboard->modifiers.mods_latched,
2174 keyboard->modifiers.mods_locked,
2175 keyboard->modifiers.group);
2176}
2177
2178static struct weston_xkb_info *
2179weston_xkb_info_create(struct xkb_keymap *keymap);
Rui Matos65196bc2013-10-10 19:44:19 +02002180
2181static void
2182update_keymap(struct weston_seat *seat)
2183{
Derek Foreman1281a362015-07-31 16:55:32 -05002184 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Rui Matos65196bc2013-10-10 19:44:19 +02002185 struct wl_resource *resource;
2186 struct weston_xkb_info *xkb_info;
2187 struct xkb_state *state;
2188 xkb_mod_mask_t latched_mods;
2189 xkb_mod_mask_t locked_mods;
2190
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002191 xkb_info = weston_xkb_info_create(keyboard->pending_keymap);
Rui Matos65196bc2013-10-10 19:44:19 +02002192
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002193 xkb_keymap_unref(keyboard->pending_keymap);
2194 keyboard->pending_keymap = NULL;
Rui Matos65196bc2013-10-10 19:44:19 +02002195
2196 if (!xkb_info) {
2197 weston_log("failed to create XKB info\n");
2198 return;
2199 }
2200
2201 state = xkb_state_new(xkb_info->keymap);
2202 if (!state) {
2203 weston_log("failed to initialise XKB state\n");
2204 weston_xkb_info_destroy(xkb_info);
2205 return;
2206 }
2207
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002208 latched_mods = xkb_state_serialize_mods(keyboard->xkb_state.state,
2209 XKB_STATE_MODS_LATCHED);
2210 locked_mods = xkb_state_serialize_mods(keyboard->xkb_state.state,
2211 XKB_STATE_MODS_LOCKED);
Rui Matos65196bc2013-10-10 19:44:19 +02002212 xkb_state_update_mask(state,
2213 0, /* depressed */
2214 latched_mods,
2215 locked_mods,
2216 0, 0, 0);
2217
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002218 weston_xkb_info_destroy(keyboard->xkb_info);
2219 keyboard->xkb_info = xkb_info;
Rui Matos65196bc2013-10-10 19:44:19 +02002220
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002221 xkb_state_unref(keyboard->xkb_state.state);
2222 keyboard->xkb_state.state = state;
Rui Matos65196bc2013-10-10 19:44:19 +02002223
Derek Foremanbc91e542015-06-03 15:53:27 -05002224 wl_resource_for_each(resource, &keyboard->resource_list)
Derek Foremanf8f7fd62017-06-28 11:41:43 -05002225 weston_keyboard_send_keymap(keyboard, resource);
Derek Foremanbc91e542015-06-03 15:53:27 -05002226 wl_resource_for_each(resource, &keyboard->focus_resource_list)
Derek Foremanf8f7fd62017-06-28 11:41:43 -05002227 weston_keyboard_send_keymap(keyboard, resource);
Rui Matos65196bc2013-10-10 19:44:19 +02002228
2229 notify_modifiers(seat, wl_display_next_serial(seat->compositor->wl_display));
2230
2231 if (!latched_mods && !locked_mods)
2232 return;
2233
Derek Foremanbc91e542015-06-03 15:53:27 -05002234 wl_resource_for_each(resource, &keyboard->resource_list)
2235 send_modifiers(resource, wl_display_get_serial(seat->compositor->wl_display), keyboard);
2236 wl_resource_for_each(resource, &keyboard->focus_resource_list)
2237 send_modifiers(resource, wl_display_get_serial(seat->compositor->wl_display), keyboard);
Rui Matos65196bc2013-10-10 19:44:19 +02002238}
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002239
2240WL_EXPORT void
Alexandros Frantzis47e79c82017-11-16 18:20:57 +02002241notify_key(struct weston_seat *seat, const struct timespec *time, uint32_t key,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002242 enum wl_keyboard_key_state state,
2243 enum weston_key_state_update update_state)
2244{
2245 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05002246 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002247 struct weston_keyboard_grab *grab = keyboard->grab;
Pekka Paalanen86b53962014-11-19 13:43:32 +02002248 uint32_t *k, *end;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002249
2250 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002251 weston_compositor_idle_inhibit(compositor);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002252 } else {
2253 weston_compositor_idle_release(compositor);
2254 }
2255
Pekka Paalanen86b53962014-11-19 13:43:32 +02002256 end = keyboard->keys.data + keyboard->keys.size;
2257 for (k = keyboard->keys.data; k < end; k++) {
2258 if (*k == key) {
2259 /* Ignore server-generated repeats. */
2260 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
2261 return;
2262 *k = *--end;
2263 }
2264 }
2265 keyboard->keys.size = (void *) end - keyboard->keys.data;
2266 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
2267 k = wl_array_add(&keyboard->keys, sizeof *k);
2268 *k = key;
2269 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002270
2271 if (grab == &keyboard->default_grab ||
2272 grab == &keyboard->input_method_grab) {
Derek Foreman99a6a2d2015-07-15 13:00:43 -05002273 weston_compositor_run_key_binding(compositor, keyboard, time,
2274 key, state);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002275 grab = keyboard->grab;
2276 }
2277
2278 grab->interface->key(grab, time, key, state);
2279
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002280 if (keyboard->pending_keymap &&
Pekka Paalanen86b53962014-11-19 13:43:32 +02002281 keyboard->keys.size == 0)
Rui Matos65196bc2013-10-10 19:44:19 +02002282 update_keymap(seat);
2283
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002284 if (update_state == STATE_UPDATE_AUTOMATIC) {
2285 update_modifier_state(seat,
2286 wl_display_get_serial(compositor->wl_display),
2287 key,
2288 state);
2289 }
Giulio Camuffob6ddf6c2015-02-06 19:06:54 +02002290
Olivier Fourdandf84dbe2016-06-30 16:01:56 +02002291 keyboard->grab_serial = wl_display_get_serial(compositor->wl_display);
Giulio Camuffob6ddf6c2015-02-06 19:06:54 +02002292 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
Alexandros Frantzis47e79c82017-11-16 18:20:57 +02002293 keyboard->grab_time = *time;
Giulio Camuffob6ddf6c2015-02-06 19:06:54 +02002294 keyboard->grab_key = key;
2295 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002296}
2297
2298WL_EXPORT void
2299notify_pointer_focus(struct weston_seat *seat, struct weston_output *output,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02002300 double x, double y)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002301{
Derek Foreman1281a362015-07-31 16:55:32 -05002302 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
2303
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002304 if (output) {
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02002305 weston_pointer_move_to(pointer,
2306 wl_fixed_from_double(x),
2307 wl_fixed_from_double(y));
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002308 } else {
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04002309 /* FIXME: We should call weston_pointer_set_focus(seat,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002310 * NULL) here, but somehow that breaks re-entry... */
2311 }
2312}
2313
2314static void
2315destroy_device_saved_kbd_focus(struct wl_listener *listener, void *data)
2316{
2317 struct weston_seat *ws;
2318
2319 ws = container_of(listener, struct weston_seat,
2320 saved_kbd_focus_listener);
2321
2322 ws->saved_kbd_focus = NULL;
Derek Foremana822afa2021-08-10 17:17:24 -05002323
2324 wl_list_remove(&ws->saved_kbd_focus_listener.link);
2325 ws->saved_kbd_focus_listener.notify = NULL;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002326}
2327
2328WL_EXPORT void
2329notify_keyboard_focus_in(struct weston_seat *seat, struct wl_array *keys,
2330 enum weston_key_state_update update_state)
2331{
2332 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05002333 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -04002334 struct weston_surface *surface;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002335 uint32_t *k, serial;
2336
2337 serial = wl_display_next_serial(compositor->wl_display);
2338 wl_array_copy(&keyboard->keys, keys);
2339 wl_array_for_each(k, &keyboard->keys) {
2340 weston_compositor_idle_inhibit(compositor);
2341 if (update_state == STATE_UPDATE_AUTOMATIC)
2342 update_modifier_state(seat, serial, *k,
2343 WL_KEYBOARD_KEY_STATE_PRESSED);
2344 }
2345
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002346 surface = seat->saved_kbd_focus;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002347 if (surface) {
Derek Foremana822afa2021-08-10 17:17:24 -05002348 wl_list_remove(&seat->saved_kbd_focus_listener.link);
2349 seat->saved_kbd_focus_listener.notify = NULL;
2350 seat->saved_kbd_focus = NULL;
2351 if (seat->use_saved_kbd_focus)
2352 weston_keyboard_set_focus(keyboard, surface);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002353 }
2354}
2355
2356WL_EXPORT void
2357notify_keyboard_focus_out(struct weston_seat *seat)
2358{
2359 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05002360 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
2361 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Quentin Glidic85d55542017-07-21 14:02:40 +02002362 struct weston_surface *focus = keyboard->focus;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002363 uint32_t *k, serial;
2364
2365 serial = wl_display_next_serial(compositor->wl_display);
2366 wl_array_for_each(k, &keyboard->keys) {
2367 weston_compositor_idle_release(compositor);
2368 update_modifier_state(seat, serial, *k,
2369 WL_KEYBOARD_KEY_STATE_RELEASED);
2370 }
2371
2372 seat->modifier_state = 0;
2373
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002374 weston_keyboard_set_focus(keyboard, NULL);
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02002375 weston_keyboard_cancel_grab(keyboard);
Derek Foreman1281a362015-07-31 16:55:32 -05002376 if (pointer)
2377 weston_pointer_cancel_grab(pointer);
Quentin Glidic85d55542017-07-21 14:02:40 +02002378
2379 if (focus) {
Derek Foremana822afa2021-08-10 17:17:24 -05002380 seat->use_saved_kbd_focus = true;
Quentin Glidic85d55542017-07-21 14:02:40 +02002381 seat->saved_kbd_focus = focus;
2382 seat->saved_kbd_focus_listener.notify =
2383 destroy_device_saved_kbd_focus;
2384 wl_signal_add(&focus->destroy_signal,
2385 &seat->saved_kbd_focus_listener);
2386 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002387}
2388
Michael Fua2bb7912013-07-23 15:51:06 +08002389WL_EXPORT void
Derek Foreman4c93c082015-04-30 16:45:41 -05002390weston_touch_set_focus(struct weston_touch *touch, struct weston_view *view)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002391{
Neil Roberts96d790e2013-09-19 17:32:00 +01002392 struct wl_list *focus_resource_list;
2393
Derek Foreman4c93c082015-04-30 16:45:41 -05002394 focus_resource_list = &touch->focus_resource_list;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002395
Derek Foreman4c93c082015-04-30 16:45:41 -05002396 if (view && touch->focus &&
2397 touch->focus->surface == view->surface) {
2398 touch->focus = view;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002399 return;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002400 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002401
Derek Foreman4c93c082015-04-30 16:45:41 -05002402 wl_list_remove(&touch->focus_resource_listener.link);
2403 wl_list_init(&touch->focus_resource_listener.link);
2404 wl_list_remove(&touch->focus_view_listener.link);
2405 wl_list_init(&touch->focus_view_listener.link);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01002406
Neil Roberts96d790e2013-09-19 17:32:00 +01002407 if (!wl_list_empty(focus_resource_list)) {
Derek Foreman4c93c082015-04-30 16:45:41 -05002408 move_resources(&touch->resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01002409 focus_resource_list);
2410 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002411
Jason Ekstranda7af7042013-10-12 22:38:11 -05002412 if (view) {
Derek Foreman362656b2014-09-04 10:23:05 -05002413 struct wl_client *surface_client;
2414
2415 if (!view->surface->resource) {
Derek Foreman4c93c082015-04-30 16:45:41 -05002416 touch->focus = NULL;
Derek Foreman362656b2014-09-04 10:23:05 -05002417 return;
2418 }
2419
2420 surface_client = wl_resource_get_client(view->surface->resource);
Neil Roberts96d790e2013-09-19 17:32:00 +01002421 move_resources_for_client(focus_resource_list,
Derek Foreman4c93c082015-04-30 16:45:41 -05002422 &touch->resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01002423 surface_client);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01002424 wl_resource_add_destroy_listener(view->surface->resource,
Derek Foreman4c93c082015-04-30 16:45:41 -05002425 &touch->focus_resource_listener);
2426 wl_signal_add(&view->destroy_signal, &touch->focus_view_listener);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002427 }
Derek Foreman4c93c082015-04-30 16:45:41 -05002428 touch->focus = view;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002429}
2430
Pekka Paalanenf4062532018-02-26 16:18:29 +02002431static void
2432process_touch_normal(struct weston_touch_device *device,
2433 const struct timespec *time, int touch_id,
2434 double double_x, double double_y, int touch_type)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002435{
Pekka Paalanenbcbce332018-02-26 14:43:00 +02002436 struct weston_touch *touch = device->aggregate;
2437 struct weston_touch_grab *grab = device->aggregate->grab;
2438 struct weston_compositor *ec = device->aggregate->seat->compositor;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002439 struct weston_view *ev;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002440 wl_fixed_t sx, sy;
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02002441 wl_fixed_t x = wl_fixed_from_double(double_x);
2442 wl_fixed_t y = wl_fixed_from_double(double_y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002443
2444 /* Update grab's global coordinates. */
Neil Roberts306fe082013-10-03 16:43:06 +01002445 if (touch_id == touch->grab_touch_id && touch_type != WL_TOUCH_UP) {
2446 touch->grab_x = x;
2447 touch->grab_y = y;
2448 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002449
2450 switch (touch_type) {
2451 case WL_TOUCH_DOWN:
Jason Ekstranda7af7042013-10-12 22:38:11 -05002452 /* the first finger down picks the view, and all further go
2453 * to that view for the remainder of the touch session i.e.
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002454 * until all touch points are up again. */
Jonas Ådahl9484b692013-12-02 22:05:03 +01002455 if (touch->num_tp == 1) {
Jason Ekstranda7af7042013-10-12 22:38:11 -05002456 ev = weston_compositor_pick_view(ec, x, y, &sx, &sy);
Derek Foreman4c93c082015-04-30 16:45:41 -05002457 weston_touch_set_focus(touch, ev);
Giulio Camuffo61ed7b62015-07-08 11:55:28 +03002458 } else if (!touch->focus) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002459 /* Unexpected condition: We have non-initial touch but
2460 * there is no focused surface.
2461 */
Chris Michael3f607d32015-10-07 11:59:49 -04002462 weston_log("touch event received with %d points down "
Jonas Ådahl9484b692013-12-02 22:05:03 +01002463 "but no surface focused\n", touch->num_tp);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002464 return;
2465 }
2466
Derek Foreman99a6a2d2015-07-15 13:00:43 -05002467 weston_compositor_run_touch_binding(ec, touch,
Kristian Høgsbergc8964012014-02-05 14:25:18 -08002468 time, touch_type);
2469
Giulio Camuffo61ed7b62015-07-08 11:55:28 +03002470 grab->interface->down(grab, time, touch_id, x, y);
Jonas Ådahl9484b692013-12-02 22:05:03 +01002471 if (touch->num_tp == 1) {
Rusty Lynchf1407ff2013-08-08 21:13:57 -07002472 touch->grab_serial =
2473 wl_display_get_serial(ec->wl_display);
Neil Roberts306fe082013-10-03 16:43:06 +01002474 touch->grab_touch_id = touch_id;
Alexandros Frantzis9448deb2017-11-16 18:20:58 +02002475 touch->grab_time = *time;
Rusty Lynchf1407ff2013-08-08 21:13:57 -07002476 touch->grab_x = x;
2477 touch->grab_y = y;
2478 }
2479
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002480 break;
2481 case WL_TOUCH_MOTION:
Jason Ekstranda7af7042013-10-12 22:38:11 -05002482 ev = touch->focus;
2483 if (!ev)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002484 break;
2485
Alexandros Frantzis7d2abcf2017-11-16 18:21:00 +02002486 grab->interface->motion(grab, time, touch_id, x, y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002487 break;
2488 case WL_TOUCH_UP:
Alexandros Frantzis27a51b82017-11-16 18:20:59 +02002489 grab->interface->up(grab, time, touch_id);
Jonas Ådahl9484b692013-12-02 22:05:03 +01002490 if (touch->num_tp == 0)
Derek Foreman4c93c082015-04-30 16:45:41 -05002491 weston_touch_set_focus(touch, NULL);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002492 break;
2493 }
2494}
2495
Louis-Francis Ratté-Bouliannec4689ff2017-11-28 20:42:47 -05002496static enum weston_touch_mode
2497get_next_touch_mode(enum weston_touch_mode from)
2498{
2499 switch (from) {
2500 case WESTON_TOUCH_MODE_PREP_NORMAL:
2501 return WESTON_TOUCH_MODE_NORMAL;
2502
2503 case WESTON_TOUCH_MODE_PREP_CALIB:
2504 return WESTON_TOUCH_MODE_CALIB;
2505
2506 case WESTON_TOUCH_MODE_NORMAL:
2507 case WESTON_TOUCH_MODE_CALIB:
2508 return from;
2509 }
2510
2511 return WESTON_TOUCH_MODE_NORMAL;
2512}
2513
2514/** Global touch mode update
2515 *
2516 * If no seat has a touch down and the compositor is in a PREP touch mode,
2517 * set the compositor to the goal touch mode.
2518 *
2519 * Calls calibrator if touch mode changed.
2520 */
2521static void
2522weston_compositor_update_touch_mode(struct weston_compositor *compositor)
2523{
2524 struct weston_seat *seat;
2525 struct weston_touch *touch;
2526 enum weston_touch_mode goal;
2527
2528 wl_list_for_each(seat, &compositor->seat_list, link) {
2529 touch = weston_seat_get_touch(seat);
2530 if (!touch)
2531 continue;
2532
2533 if (touch->num_tp > 0)
2534 return;
2535 }
2536
2537 goal = get_next_touch_mode(compositor->touch_mode);
2538 if (compositor->touch_mode != goal) {
2539 compositor->touch_mode = goal;
2540 touch_calibrator_mode_changed(compositor);
2541 }
2542}
2543
2544/** Start transition to normal touch event handling
2545 *
2546 * The touch event mode changes when all touches on all touch devices have
2547 * been lifted. If no touches are currently down, the transition is immediate.
2548 *
2549 * \sa weston_touch_mode
2550 */
2551void
2552weston_compositor_set_touch_mode_normal(struct weston_compositor *compositor)
2553{
2554 switch (compositor->touch_mode) {
2555 case WESTON_TOUCH_MODE_PREP_NORMAL:
2556 case WESTON_TOUCH_MODE_NORMAL:
2557 return;
2558 case WESTON_TOUCH_MODE_PREP_CALIB:
2559 compositor->touch_mode = WESTON_TOUCH_MODE_NORMAL;
2560 touch_calibrator_mode_changed(compositor);
2561 return;
2562 case WESTON_TOUCH_MODE_CALIB:
2563 compositor->touch_mode = WESTON_TOUCH_MODE_PREP_NORMAL;
2564 }
2565
2566 weston_compositor_update_touch_mode(compositor);
2567}
2568
2569/** Start transition to calibrator touch event handling
2570 *
2571 * The touch event mode changes when all touches on all touch devices have
2572 * been lifted. If no touches are currently down, the transition is immediate.
2573 *
2574 * \sa weston_touch_mode
2575 */
2576void
2577weston_compositor_set_touch_mode_calib(struct weston_compositor *compositor)
2578{
2579 switch (compositor->touch_mode) {
2580 case WESTON_TOUCH_MODE_PREP_CALIB:
2581 case WESTON_TOUCH_MODE_CALIB:
2582 assert(0);
2583 return;
2584 case WESTON_TOUCH_MODE_PREP_NORMAL:
2585 compositor->touch_mode = WESTON_TOUCH_MODE_CALIB;
2586 touch_calibrator_mode_changed(compositor);
2587 return;
2588 case WESTON_TOUCH_MODE_NORMAL:
2589 compositor->touch_mode = WESTON_TOUCH_MODE_PREP_CALIB;
2590 }
2591
2592 weston_compositor_update_touch_mode(compositor);
2593}
2594
Pekka Paalanenf4062532018-02-26 16:18:29 +02002595/** Feed in touch down, motion, and up events, calibratable device.
2596 *
2597 * It assumes always the correct cycle sequence until it gets here: touch_down
2598 * → touch_update → ... → touch_update → touch_end. The driver is responsible
2599 * for sending along such order.
2600 *
2601 * \param device The physical device that generated the event.
2602 * \param time The event timestamp.
2603 * \param touch_id ID for the touch point of this event (multi-touch).
Marius Vlada2dace22019-06-12 16:05:44 +03002604 * \param x X coordinate in compositor global space.
2605 * \param y Y coordinate in compositor global space.
Pekka Paalanenf4062532018-02-26 16:18:29 +02002606 * \param norm Normalized device X, Y coordinates in calibration space, or NULL.
2607 * \param touch_type Either WL_TOUCH_DOWN, WL_TOUCH_UP, or WL_TOUCH_MOTION.
2608 *
2609 * Coordinates double_x and double_y are used for normal operation.
2610 *
2611 * Coordinates norm are only used for touch device calibration. If and only if
2612 * the weston_touch_device does not support calibrating, norm must be NULL.
2613 *
2614 * The calibration space is the normalized coordinate space
2615 * [0.0, 1.0]×[0.0, 1.0] of the weston_touch_device. This is assumed to
2616 * map to the similar normalized coordinate space of the associated
2617 * weston_output.
2618 */
2619WL_EXPORT void
2620notify_touch_normalized(struct weston_touch_device *device,
2621 const struct timespec *time,
2622 int touch_id,
2623 double x, double y,
2624 const struct weston_point2d_device_normalized *norm,
2625 int touch_type)
2626{
Louis-Francis Ratté-Boulianne813a06e2017-11-28 20:42:47 -05002627 struct weston_seat *seat = device->aggregate->seat;
2628 struct weston_touch *touch = device->aggregate;
2629
Pekka Paalanenf4062532018-02-26 16:18:29 +02002630 if (touch_type != WL_TOUCH_UP) {
2631 if (weston_touch_device_can_calibrate(device))
2632 assert(norm != NULL);
2633 else
2634 assert(norm == NULL);
2635 }
2636
Louis-Francis Ratté-Boulianne813a06e2017-11-28 20:42:47 -05002637 /* Update touchpoints count regardless of the current mode. */
2638 switch (touch_type) {
2639 case WL_TOUCH_DOWN:
2640 weston_compositor_idle_inhibit(seat->compositor);
2641
2642 touch->num_tp++;
2643 break;
2644 case WL_TOUCH_UP:
2645 if (touch->num_tp == 0) {
2646 /* This can happen if we start out with one or
2647 * more fingers on the touch screen, in which
2648 * case we didn't get the corresponding down
2649 * event. */
Pekka Paalanen332a45e2018-03-02 14:20:59 +02002650 weston_log("Unmatched touch up event on seat %s, device %s\n",
2651 seat->seat_name, device->syspath);
2652 return;
Louis-Francis Ratté-Boulianne813a06e2017-11-28 20:42:47 -05002653 }
2654 weston_compositor_idle_release(seat->compositor);
2655
2656 touch->num_tp--;
2657 break;
2658 default:
2659 break;
2660 }
2661
Louis-Francis Ratté-Bouliannec4689ff2017-11-28 20:42:47 -05002662 /* Properly forward the touch event */
2663 switch (weston_touch_device_get_mode(device)) {
2664 case WESTON_TOUCH_MODE_NORMAL:
2665 case WESTON_TOUCH_MODE_PREP_CALIB:
2666 process_touch_normal(device, time, touch_id, x, y, touch_type);
2667 break;
2668 case WESTON_TOUCH_MODE_CALIB:
2669 case WESTON_TOUCH_MODE_PREP_NORMAL:
Louis-Francis Ratté-Boulianne83630982017-11-28 20:42:47 -05002670 notify_touch_calibrator(device, time, touch_id,
2671 norm, touch_type);
Louis-Francis Ratté-Bouliannec4689ff2017-11-28 20:42:47 -05002672 break;
2673 }
Pekka Paalanenf4062532018-02-26 16:18:29 +02002674}
2675
Jonas Ådahl1679f232014-04-12 09:39:51 +02002676WL_EXPORT void
Pekka Paalanenbcbce332018-02-26 14:43:00 +02002677notify_touch_frame(struct weston_touch_device *device)
Jonas Ådahl1679f232014-04-12 09:39:51 +02002678{
Louis-Francis Ratté-Bouliannec4689ff2017-11-28 20:42:47 -05002679 struct weston_touch_grab *grab;
Jonas Ådahl1679f232014-04-12 09:39:51 +02002680
Louis-Francis Ratté-Bouliannec4689ff2017-11-28 20:42:47 -05002681 switch (weston_touch_device_get_mode(device)) {
2682 case WESTON_TOUCH_MODE_NORMAL:
2683 case WESTON_TOUCH_MODE_PREP_CALIB:
2684 grab = device->aggregate->grab;
2685 grab->interface->frame(grab);
2686 break;
2687 case WESTON_TOUCH_MODE_CALIB:
2688 case WESTON_TOUCH_MODE_PREP_NORMAL:
Louis-Francis Ratté-Boulianne83630982017-11-28 20:42:47 -05002689 notify_touch_calibrator_frame(device);
Louis-Francis Ratté-Bouliannec4689ff2017-11-28 20:42:47 -05002690 break;
2691 }
2692
2693 weston_compositor_update_touch_mode(device->aggregate->seat->compositor);
Jonas Ådahl1679f232014-04-12 09:39:51 +02002694}
2695
Derek Foreman3cc004a2015-11-06 15:56:09 -06002696WL_EXPORT void
Pekka Paalanenbcbce332018-02-26 14:43:00 +02002697notify_touch_cancel(struct weston_touch_device *device)
Derek Foreman3cc004a2015-11-06 15:56:09 -06002698{
Louis-Francis Ratté-Bouliannec4689ff2017-11-28 20:42:47 -05002699 struct weston_touch_grab *grab;
Derek Foreman3cc004a2015-11-06 15:56:09 -06002700
Louis-Francis Ratté-Bouliannec4689ff2017-11-28 20:42:47 -05002701 switch (weston_touch_device_get_mode(device)) {
2702 case WESTON_TOUCH_MODE_NORMAL:
2703 case WESTON_TOUCH_MODE_PREP_CALIB:
2704 grab = device->aggregate->grab;
2705 grab->interface->cancel(grab);
2706 break;
2707 case WESTON_TOUCH_MODE_CALIB:
2708 case WESTON_TOUCH_MODE_PREP_NORMAL:
Louis-Francis Ratté-Boulianne83630982017-11-28 20:42:47 -05002709 notify_touch_calibrator_cancel(device);
Louis-Francis Ratté-Bouliannec4689ff2017-11-28 20:42:47 -05002710 break;
2711 }
2712
2713 weston_compositor_update_touch_mode(device->aggregate->seat->compositor);
Derek Foreman3cc004a2015-11-06 15:56:09 -06002714}
2715
Pekka Paalanen8274d902014-08-06 19:36:51 +03002716static int
2717pointer_cursor_surface_get_label(struct weston_surface *surface,
2718 char *buf, size_t len)
2719{
2720 return snprintf(buf, len, "cursor");
2721}
2722
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002723static void
Quentin Glidic2edc3d52016-08-12 10:41:33 +02002724pointer_cursor_surface_committed(struct weston_surface *es,
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06002725 int32_t dx, int32_t dy)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002726{
Quentin Glidic2edc3d52016-08-12 10:41:33 +02002727 struct weston_pointer *pointer = es->committed_private;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002728 int x, y;
2729
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06002730 if (es->width == 0)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002731 return;
2732
Jason Ekstranda7af7042013-10-12 22:38:11 -05002733 assert(es == pointer->sprite->surface);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002734
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002735 pointer->hotspot_x -= dx;
2736 pointer->hotspot_y -= dy;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002737
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002738 x = wl_fixed_to_int(pointer->x) - pointer->hotspot_x;
2739 y = wl_fixed_to_int(pointer->y) - pointer->hotspot_y;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002740
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06002741 weston_view_set_position(pointer->sprite, x, y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002742
2743 empty_region(&es->pending.input);
Ander Conselvan de Oliveira23900f72014-01-31 16:07:51 +02002744 empty_region(&es->input);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002745
2746 if (!weston_surface_is_mapped(es)) {
Giulio Camuffo412e6a52014-07-09 22:12:56 +03002747 weston_layer_entry_insert(&es->compositor->cursor_layer.view_list,
2748 &pointer->sprite->layer_link);
Jason Ekstranda7af7042013-10-12 22:38:11 -05002749 weston_view_update_transform(pointer->sprite);
Armin Krezovićf8486c32016-06-30 06:04:28 +02002750 es->is_mapped = true;
2751 pointer->sprite->is_mapped = true;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002752 }
2753}
2754
2755static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002756pointer_set_cursor(struct wl_client *client, struct wl_resource *resource,
2757 uint32_t serial, struct wl_resource *surface_resource,
2758 int32_t x, int32_t y)
2759{
Jason Ekstrand44a38632013-06-14 10:08:00 -05002760 struct weston_pointer *pointer = wl_resource_get_user_data(resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002761 struct weston_surface *surface = NULL;
2762
Alexandros Frantzis1c3a40e2018-02-08 15:37:53 +02002763 if (!pointer)
2764 return;
2765
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002766 if (surface_resource)
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05002767 surface = wl_resource_get_user_data(surface_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002768
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002769 if (pointer->focus == NULL)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002770 return;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002771 /* pointer->focus->surface->resource can be NULL. Surfaces like the
Giulio Camuffo1fd4b012013-06-20 18:13:07 +02002772 black_surface used in shell.c for fullscreen don't have
2773 a resource, but can still have focus */
Jason Ekstranda7af7042013-10-12 22:38:11 -05002774 if (pointer->focus->surface->resource == NULL)
Giulio Camuffo1fd4b012013-06-20 18:13:07 +02002775 return;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002776 if (wl_resource_get_client(pointer->focus->surface->resource) != client)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002777 return;
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002778 if (pointer->focus_serial - serial > UINT32_MAX / 2)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002779 return;
2780
Derek Foreman4e53c532015-03-23 10:55:32 -05002781 if (!surface) {
2782 if (pointer->sprite)
2783 pointer_unmap_sprite(pointer);
2784 return;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002785 }
2786
Jonas Ådahlb4070242015-03-18 15:08:03 +08002787 if (pointer->sprite && pointer->sprite->surface == surface &&
2788 pointer->hotspot_x == x && pointer->hotspot_y == y)
2789 return;
2790
Derek Foreman4e53c532015-03-23 10:55:32 -05002791 if (!pointer->sprite || pointer->sprite->surface != surface) {
2792 if (weston_surface_set_role(surface, "wl_pointer-cursor",
2793 resource,
2794 WL_POINTER_ERROR_ROLE) < 0)
2795 return;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002796
Derek Foreman4e53c532015-03-23 10:55:32 -05002797 if (pointer->sprite)
2798 pointer_unmap_sprite(pointer);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002799
Derek Foreman4e53c532015-03-23 10:55:32 -05002800 wl_signal_add(&surface->destroy_signal,
2801 &pointer->sprite_destroy_listener);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002802
Quentin Glidic2edc3d52016-08-12 10:41:33 +02002803 surface->committed = pointer_cursor_surface_committed;
2804 surface->committed_private = pointer;
Derek Foreman4e53c532015-03-23 10:55:32 -05002805 weston_surface_set_label_func(surface,
2806 pointer_cursor_surface_get_label);
2807 pointer->sprite = weston_view_create(surface);
2808 }
2809
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002810 pointer->hotspot_x = x;
2811 pointer->hotspot_y = y;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002812
Alexandros Frantzis28d66342021-06-09 10:56:26 +03002813 if (surface->width != 0) {
Quentin Glidic2edc3d52016-08-12 10:41:33 +02002814 pointer_cursor_surface_committed(surface, 0, 0);
Jonas Ådahl16fe4dc2014-09-08 19:33:41 +02002815 weston_view_schedule_repaint(pointer->sprite);
2816 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002817}
2818
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002819static void
2820pointer_release(struct wl_client *client, struct wl_resource *resource)
2821{
2822 wl_resource_destroy(resource);
2823}
2824
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002825static const struct wl_pointer_interface pointer_interface = {
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002826 pointer_set_cursor,
2827 pointer_release
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002828};
2829
2830static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002831seat_get_pointer(struct wl_client *client, struct wl_resource *resource,
2832 uint32_t id)
2833{
Jason Ekstrand44a38632013-06-14 10:08:00 -05002834 struct weston_seat *seat = wl_resource_get_user_data(resource);
Derek Foreman1281a362015-07-31 16:55:32 -05002835 /* We use the pointer_state directly, which means we'll
2836 * give a wl_pointer if the seat has ever had one - even though
2837 * the spec explicitly states that this request only takes effect
2838 * if the seat has the pointer capability.
2839 *
2840 * This prevents a race between the compositor sending new
2841 * capabilities and the client trying to use the old ones.
2842 */
Alexandros Frantzis8480d132018-02-15 13:07:09 +02002843 struct weston_pointer *pointer = seat ? seat->pointer_state : NULL;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002844 struct wl_resource *cr;
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08002845 struct weston_pointer_client *pointer_client;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002846
Emmanuel Gil Peyroteff793a2021-07-31 17:25:41 +02002847 cr = wl_resource_create(client, &wl_pointer_interface,
Jason Ekstranda85118c2013-06-27 20:17:02 -05002848 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07002849 if (cr == NULL) {
2850 wl_client_post_no_memory(client);
2851 return;
2852 }
2853
Alexandros Frantzis8480d132018-02-15 13:07:09 +02002854 wl_list_init(wl_resource_get_link(cr));
2855 wl_resource_set_implementation(cr, &pointer_interface, pointer,
2856 unbind_pointer_client_resource);
2857
2858 /* If we don't have a pointer_state, the resource is inert, so there
2859 * is nothing more to set up */
2860 if (!pointer)
2861 return;
2862
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08002863 pointer_client = weston_pointer_ensure_pointer_client(pointer, client);
2864 if (!pointer_client) {
2865 wl_client_post_no_memory(client);
2866 return;
2867 }
2868
2869 wl_list_insert(&pointer_client->pointer_resources,
2870 wl_resource_get_link(cr));
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002871
Derek Foreman1281a362015-07-31 16:55:32 -05002872 if (pointer->focus && pointer->focus->surface->resource &&
2873 wl_resource_get_client(pointer->focus->surface->resource) == client) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002874 wl_fixed_t sx, sy;
2875
Derek Foreman1281a362015-07-31 16:55:32 -05002876 weston_view_from_global_fixed(pointer->focus,
2877 pointer->x,
2878 pointer->y,
Jason Ekstranda7af7042013-10-12 22:38:11 -05002879 &sx, &sy);
Neil Roberts96d790e2013-09-19 17:32:00 +01002880
Neil Roberts96d790e2013-09-19 17:32:00 +01002881 wl_pointer_send_enter(cr,
Derek Foreman1281a362015-07-31 16:55:32 -05002882 pointer->focus_serial,
2883 pointer->focus->surface->resource,
Neil Roberts96d790e2013-09-19 17:32:00 +01002884 sx, sy);
Peter Hutterer87743e92016-01-18 16:38:22 +10002885 pointer_send_frame(cr);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002886 }
2887}
2888
2889static void
Alexandros Frantzis2b442482018-02-20 14:05:50 +02002890destroy_keyboard_resource(struct wl_resource *resource)
2891{
2892 struct weston_keyboard *keyboard = wl_resource_get_user_data(resource);
2893
2894 wl_list_remove(wl_resource_get_link(resource));
2895
2896 if (keyboard) {
2897 remove_input_resource_from_timestamps(resource,
2898 &keyboard->timestamps_list);
leng.fangdbaf6fa2024-06-20 19:31:04 +08002899 weston_keyboard_clear_key_info_for_resource(keyboard, resource);
Alexandros Frantzis2b442482018-02-20 14:05:50 +02002900 }
2901}
2902
2903static void
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002904keyboard_release(struct wl_client *client, struct wl_resource *resource)
2905{
2906 wl_resource_destroy(resource);
2907}
2908
2909static const struct wl_keyboard_interface keyboard_interface = {
2910 keyboard_release
2911};
2912
2913static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002914seat_get_keyboard(struct wl_client *client, struct wl_resource *resource,
2915 uint32_t id)
2916{
Jason Ekstrand44a38632013-06-14 10:08:00 -05002917 struct weston_seat *seat = wl_resource_get_user_data(resource);
Derek Foreman1281a362015-07-31 16:55:32 -05002918 /* We use the keyboard_state directly, which means we'll
2919 * give a wl_keyboard if the seat has ever had one - even though
2920 * the spec explicitly states that this request only takes effect
2921 * if the seat has the keyboard capability.
2922 *
2923 * This prevents a race between the compositor sending new
2924 * capabilities and the client trying to use the old ones.
2925 */
Alexandros Frantzis8480d132018-02-15 13:07:09 +02002926 struct weston_keyboard *keyboard = seat ? seat->keyboard_state : NULL;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002927 struct wl_resource *cr;
2928
leng.fange9d800e2024-07-12 13:31:59 +08002929 if (weston_keyboard_need_skip_get_keyboard(client, keyboard))
2930 return;
2931
Emmanuel Gil Peyroteff793a2021-07-31 17:25:41 +02002932 cr = wl_resource_create(client, &wl_keyboard_interface,
Jason Ekstranda85118c2013-06-27 20:17:02 -05002933 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07002934 if (cr == NULL) {
2935 wl_client_post_no_memory(client);
2936 return;
2937 }
2938
Alexandros Frantzis8480d132018-02-15 13:07:09 +02002939 wl_list_init(wl_resource_get_link(cr));
2940 wl_resource_set_implementation(cr, &keyboard_interface,
Alexandros Frantzis2b442482018-02-20 14:05:50 +02002941 keyboard, destroy_keyboard_resource);
Alexandros Frantzis8480d132018-02-15 13:07:09 +02002942
2943 /* If we don't have a keyboard_state, the resource is inert, so there
2944 * is nothing more to set up */
2945 if (!keyboard)
2946 return;
2947
Neil Roberts96d790e2013-09-19 17:32:00 +01002948 /* May be moved to focused list later by either
2949 * weston_keyboard_set_focus or directly if this client is already
2950 * focused */
Derek Foreman345c9f32015-06-03 15:53:28 -05002951 wl_list_insert(&keyboard->resource_list, wl_resource_get_link(cr));
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002952
Jonny Lamb66a41a02014-08-12 14:58:25 +02002953 if (wl_resource_get_version(cr) >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) {
2954 wl_keyboard_send_repeat_info(cr,
2955 seat->compositor->kb_repeat_rate,
2956 seat->compositor->kb_repeat_delay);
2957 }
Jasper St. Pierred8c6aeb2014-08-04 13:43:24 -04002958
Derek Foremanf8f7fd62017-06-28 11:41:43 -05002959 weston_keyboard_send_keymap(keyboard, cr);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002960
Derek Foreman345c9f32015-06-03 15:53:28 -05002961 if (keyboard->focus && keyboard->focus->resource &&
2962 wl_resource_get_client(keyboard->focus->resource) == client) {
Neil Roberts96d790e2013-09-19 17:32:00 +01002963 struct weston_surface *surface =
Derek Foreman345c9f32015-06-03 15:53:28 -05002964 (struct weston_surface *)keyboard->focus;
Neil Roberts96d790e2013-09-19 17:32:00 +01002965
2966 wl_list_remove(wl_resource_get_link(cr));
Derek Foreman345c9f32015-06-03 15:53:28 -05002967 wl_list_insert(&keyboard->focus_resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01002968 wl_resource_get_link(cr));
2969 wl_keyboard_send_enter(cr,
Derek Foreman345c9f32015-06-03 15:53:28 -05002970 keyboard->focus_serial,
Neil Roberts96d790e2013-09-19 17:32:00 +01002971 surface->resource,
Derek Foreman345c9f32015-06-03 15:53:28 -05002972 &keyboard->keys);
Neil Roberts96d790e2013-09-19 17:32:00 +01002973
Kirill Chibisovc46c70d2020-06-17 01:43:57 +03002974 send_modifiers_to_resource(keyboard,
2975 cr,
2976 keyboard->focus_serial);
2977
Neil Roberts96d790e2013-09-19 17:32:00 +01002978 /* If this is the first keyboard resource for this
2979 * client... */
Derek Foreman345c9f32015-06-03 15:53:28 -05002980 if (keyboard->focus_resource_list.prev ==
Neil Roberts96d790e2013-09-19 17:32:00 +01002981 wl_resource_get_link(cr))
2982 wl_data_device_set_keyboard_focus(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002983 }
2984}
2985
2986static void
Alexandros Frantzisd7157842018-02-20 14:07:03 +02002987destroy_touch_resource(struct wl_resource *resource)
2988{
2989 struct weston_touch *touch = wl_resource_get_user_data(resource);
2990
2991 wl_list_remove(wl_resource_get_link(resource));
2992
2993 if (touch) {
2994 remove_input_resource_from_timestamps(resource,
2995 &touch->timestamps_list);
2996 }
2997}
2998
2999static void
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01003000touch_release(struct wl_client *client, struct wl_resource *resource)
3001{
3002 wl_resource_destroy(resource);
3003}
3004
3005static const struct wl_touch_interface touch_interface = {
3006 touch_release
3007};
3008
3009static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003010seat_get_touch(struct wl_client *client, struct wl_resource *resource,
3011 uint32_t id)
3012{
Jason Ekstrand44a38632013-06-14 10:08:00 -05003013 struct weston_seat *seat = wl_resource_get_user_data(resource);
Derek Foreman1281a362015-07-31 16:55:32 -05003014 /* We use the touch_state directly, which means we'll
3015 * give a wl_touch if the seat has ever had one - even though
3016 * the spec explicitly states that this request only takes effect
3017 * if the seat has the touch capability.
3018 *
3019 * This prevents a race between the compositor sending new
3020 * capabilities and the client trying to use the old ones.
3021 */
Alexandros Frantzis8480d132018-02-15 13:07:09 +02003022 struct weston_touch *touch = seat ? seat->touch_state : NULL;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003023 struct wl_resource *cr;
3024
Emmanuel Gil Peyroteff793a2021-07-31 17:25:41 +02003025 cr = wl_resource_create(client, &wl_touch_interface,
Jason Ekstranda85118c2013-06-27 20:17:02 -05003026 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07003027 if (cr == NULL) {
3028 wl_client_post_no_memory(client);
3029 return;
3030 }
3031
Alexandros Frantzis8480d132018-02-15 13:07:09 +02003032 wl_list_init(wl_resource_get_link(cr));
3033 wl_resource_set_implementation(cr, &touch_interface,
Alexandros Frantzisd7157842018-02-20 14:07:03 +02003034 touch, destroy_touch_resource);
Alexandros Frantzis8480d132018-02-15 13:07:09 +02003035
3036 /* If we don't have a touch_state, the resource is inert, so there
3037 * is nothing more to set up */
3038 if (!touch)
3039 return;
3040
Derek Foreman1281a362015-07-31 16:55:32 -05003041 if (touch->focus &&
3042 wl_resource_get_client(touch->focus->surface->resource) == client) {
Chokshi, Mituld6697142015-10-09 08:28:47 +00003043 wl_list_insert(&touch->focus_resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01003044 wl_resource_get_link(cr));
3045 } else {
Chokshi, Mituld6697142015-10-09 08:28:47 +00003046 wl_list_insert(&touch->resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01003047 wl_resource_get_link(cr));
3048 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003049}
3050
Quentin Glidicaab1d362016-03-13 17:49:08 +01003051static void
3052seat_release(struct wl_client *client, struct wl_resource *resource)
3053{
3054 wl_resource_destroy(resource);
3055}
3056
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003057static const struct wl_seat_interface seat_interface = {
3058 seat_get_pointer,
3059 seat_get_keyboard,
3060 seat_get_touch,
Quentin Glidicaab1d362016-03-13 17:49:08 +01003061 seat_release,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003062};
3063
3064static void
3065bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
3066{
Kristian Høgsberge3148752013-05-06 23:19:49 -04003067 struct weston_seat *seat = data;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003068 struct wl_resource *resource;
3069 enum wl_seat_capability caps = 0;
3070
Jason Ekstranda85118c2013-06-27 20:17:02 -05003071 resource = wl_resource_create(client,
Derek Foreman1909c102015-11-26 14:17:47 -06003072 &wl_seat_interface, version, id);
Jason Ekstrand44a38632013-06-14 10:08:00 -05003073 wl_list_insert(&seat->base_resource_list, wl_resource_get_link(resource));
Jason Ekstranda85118c2013-06-27 20:17:02 -05003074 wl_resource_set_implementation(resource, &seat_interface, data,
3075 unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003076
Derek Foreman1281a362015-07-31 16:55:32 -05003077 if (weston_seat_get_pointer(seat))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003078 caps |= WL_SEAT_CAPABILITY_POINTER;
Derek Foreman1281a362015-07-31 16:55:32 -05003079 if (weston_seat_get_keyboard(seat))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003080 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
Derek Foreman1281a362015-07-31 16:55:32 -05003081 if (weston_seat_get_touch(seat))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003082 caps |= WL_SEAT_CAPABILITY_TOUCH;
3083
3084 wl_seat_send_capabilities(resource, caps);
Jasper St. Pierre0013a292014-08-07 16:43:11 -04003085 if (version >= WL_SEAT_NAME_SINCE_VERSION)
Rob Bradforde445ae62013-05-31 18:09:51 +01003086 wl_seat_send_name(resource, seat->seat_name);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003087}
3088
Jonas Ådahl30d61d82014-10-22 21:21:17 +02003089static void
3090relative_pointer_destroy(struct wl_client *client,
3091 struct wl_resource *resource)
3092{
3093 wl_resource_destroy(resource);
3094}
3095
3096static const struct zwp_relative_pointer_v1_interface relative_pointer_interface = {
3097 relative_pointer_destroy
3098};
3099
3100static void
3101relative_pointer_manager_destroy(struct wl_client *client,
3102 struct wl_resource *resource)
3103{
3104 wl_resource_destroy(resource);
3105}
3106
3107static void
3108relative_pointer_manager_get_relative_pointer(struct wl_client *client,
3109 struct wl_resource *resource,
3110 uint32_t id,
3111 struct wl_resource *pointer_resource)
3112{
3113 struct weston_pointer *pointer =
3114 wl_resource_get_user_data(pointer_resource);
3115 struct weston_pointer_client *pointer_client;
3116 struct wl_resource *cr;
3117
3118 cr = wl_resource_create(client, &zwp_relative_pointer_v1_interface,
3119 wl_resource_get_version(resource), id);
3120 if (cr == NULL) {
3121 wl_client_post_no_memory(client);
3122 return;
3123 }
3124
3125 pointer_client = weston_pointer_ensure_pointer_client(pointer, client);
3126 if (!pointer_client) {
3127 wl_client_post_no_memory(client);
3128 return;
3129 }
3130
3131 wl_list_insert(&pointer_client->relative_pointer_resources,
3132 wl_resource_get_link(cr));
3133 wl_resource_set_implementation(cr, &relative_pointer_interface,
3134 pointer,
3135 unbind_pointer_client_resource);
3136}
3137
3138static const struct zwp_relative_pointer_manager_v1_interface relative_pointer_manager = {
3139 relative_pointer_manager_destroy,
3140 relative_pointer_manager_get_relative_pointer,
3141};
3142
3143static void
3144bind_relative_pointer_manager(struct wl_client *client, void *data,
3145 uint32_t version, uint32_t id)
3146{
3147 struct weston_compositor *compositor = data;
3148 struct wl_resource *resource;
3149
3150 resource = wl_resource_create(client,
3151 &zwp_relative_pointer_manager_v1_interface,
3152 1, id);
3153
3154 wl_resource_set_implementation(resource, &relative_pointer_manager,
3155 compositor,
3156 NULL);
3157}
3158
Giulio Camuffo0358af42016-06-02 21:48:08 +03003159WL_EXPORT int
3160weston_compositor_set_xkb_rule_names(struct weston_compositor *ec,
3161 struct xkb_rule_names *names)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003162{
3163 if (ec->xkb_context == NULL) {
Peter Hutterera2086bb2020-05-13 15:24:27 +10003164 ec->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003165 if (ec->xkb_context == NULL) {
3166 weston_log("failed to create XKB context\n");
3167 return -1;
3168 }
3169 }
3170
3171 if (names)
3172 ec->xkb_names = *names;
3173 if (!ec->xkb_names.rules)
3174 ec->xkb_names.rules = strdup("evdev");
3175 if (!ec->xkb_names.model)
3176 ec->xkb_names.model = strdup("pc105");
3177 if (!ec->xkb_names.layout)
3178 ec->xkb_names.layout = strdup("us");
3179
3180 return 0;
3181}
3182
Stefan Schmidtfda26522013-09-17 10:54:09 +01003183static void
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00003184weston_xkb_info_destroy(struct weston_xkb_info *xkb_info)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003185{
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00003186 if (--xkb_info->ref_count > 0)
3187 return;
3188
Ran Benitac9c74152014-08-19 23:59:52 +03003189 xkb_keymap_unref(xkb_info->keymap);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003190
Sebastian Wickabec5122019-11-01 02:38:45 +01003191 os_ro_anonymous_file_destroy(xkb_info->keymap_rofile);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00003192 free(xkb_info);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003193}
3194
3195void
3196weston_compositor_xkb_destroy(struct weston_compositor *ec)
3197{
3198 free((char *) ec->xkb_names.rules);
3199 free((char *) ec->xkb_names.model);
3200 free((char *) ec->xkb_names.layout);
3201 free((char *) ec->xkb_names.variant);
3202 free((char *) ec->xkb_names.options);
Stefan Schmidtfda26522013-09-17 10:54:09 +01003203
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00003204 if (ec->xkb_info)
3205 weston_xkb_info_destroy(ec->xkb_info);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003206 xkb_context_unref(ec->xkb_context);
3207}
3208
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00003209static struct weston_xkb_info *
3210weston_xkb_info_create(struct xkb_keymap *keymap)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003211{
Sebastian Wickabec5122019-11-01 02:38:45 +01003212 char *keymap_string;
3213 size_t keymap_size;
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00003214 struct weston_xkb_info *xkb_info = zalloc(sizeof *xkb_info);
3215 if (xkb_info == NULL)
3216 return NULL;
3217
Ran Benita2e1968f2014-08-19 23:59:51 +03003218 xkb_info->keymap = xkb_keymap_ref(keymap);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00003219 xkb_info->ref_count = 1;
3220
Ran Benita2e1968f2014-08-19 23:59:51 +03003221 xkb_info->shift_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
3222 XKB_MOD_NAME_SHIFT);
3223 xkb_info->caps_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
3224 XKB_MOD_NAME_CAPS);
3225 xkb_info->ctrl_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
3226 XKB_MOD_NAME_CTRL);
3227 xkb_info->alt_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
3228 XKB_MOD_NAME_ALT);
3229 xkb_info->mod2_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
3230 "Mod2");
3231 xkb_info->mod3_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
3232 "Mod3");
3233 xkb_info->super_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
3234 XKB_MOD_NAME_LOGO);
3235 xkb_info->mod5_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
3236 "Mod5");
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003237
Ran Benita2e1968f2014-08-19 23:59:51 +03003238 xkb_info->num_led = xkb_keymap_led_get_index(xkb_info->keymap,
3239 XKB_LED_NAME_NUM);
3240 xkb_info->caps_led = xkb_keymap_led_get_index(xkb_info->keymap,
3241 XKB_LED_NAME_CAPS);
3242 xkb_info->scroll_led = xkb_keymap_led_get_index(xkb_info->keymap,
3243 XKB_LED_NAME_SCROLL);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003244
Sebastian Wickabec5122019-11-01 02:38:45 +01003245 keymap_string = xkb_keymap_get_as_string(xkb_info->keymap,
Derek Foreman76829fc2017-06-28 12:17:46 -05003246 XKB_KEYMAP_FORMAT_TEXT_V1);
Sebastian Wickabec5122019-11-01 02:38:45 +01003247 if (keymap_string == NULL) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003248 weston_log("failed to get string version of keymap\n");
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00003249 goto err_keymap;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003250 }
Sebastian Wickabec5122019-11-01 02:38:45 +01003251 keymap_size = strlen(keymap_string) + 1;
3252
3253 xkb_info->keymap_rofile = os_ro_anonymous_file_create(keymap_size,
3254 keymap_string);
3255 free(keymap_string);
3256
3257 if (!xkb_info->keymap_rofile) {
3258 weston_log("failed to create anonymous file for keymap\n");
3259 goto err_keymap;
3260 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003261
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00003262 return xkb_info;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003263
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00003264err_keymap:
Ran Benita2e1968f2014-08-19 23:59:51 +03003265 xkb_keymap_unref(xkb_info->keymap);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00003266 free(xkb_info);
3267 return NULL;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003268}
3269
3270static int
3271weston_compositor_build_global_keymap(struct weston_compositor *ec)
3272{
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00003273 struct xkb_keymap *keymap;
3274
3275 if (ec->xkb_info != NULL)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003276 return 0;
3277
Ran Benita2e1968f2014-08-19 23:59:51 +03003278 keymap = xkb_keymap_new_from_names(ec->xkb_context,
3279 &ec->xkb_names,
3280 0);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00003281 if (keymap == NULL) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003282 weston_log("failed to compile global XKB keymap\n");
3283 weston_log(" tried rules %s, model %s, layout %s, variant %s, "
3284 "options %s\n",
3285 ec->xkb_names.rules, ec->xkb_names.model,
3286 ec->xkb_names.layout, ec->xkb_names.variant,
3287 ec->xkb_names.options);
3288 return -1;
3289 }
3290
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00003291 ec->xkb_info = weston_xkb_info_create(keymap);
Rui Matos73d93952013-10-24 19:28:41 +02003292 xkb_keymap_unref(keymap);
Stefan Schmidtfda26522013-09-17 10:54:09 +01003293 if (ec->xkb_info == NULL)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003294 return -1;
3295
3296 return 0;
3297}
3298
Rui Matos65196bc2013-10-10 19:44:19 +02003299WL_EXPORT void
3300weston_seat_update_keymap(struct weston_seat *seat, struct xkb_keymap *keymap)
3301{
Derek Foreman1281a362015-07-31 16:55:32 -05003302 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
3303
3304 if (!keyboard || !keymap)
Rui Matos65196bc2013-10-10 19:44:19 +02003305 return;
3306
Derek Foreman1281a362015-07-31 16:55:32 -05003307 xkb_keymap_unref(keyboard->pending_keymap);
3308 keyboard->pending_keymap = xkb_keymap_ref(keymap);
Rui Matos65196bc2013-10-10 19:44:19 +02003309
Derek Foreman1281a362015-07-31 16:55:32 -05003310 if (keyboard->keys.size == 0)
Rui Matos65196bc2013-10-10 19:44:19 +02003311 update_keymap(seat);
Rui Matos65196bc2013-10-10 19:44:19 +02003312}
3313
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003314WL_EXPORT int
3315weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap)
3316{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04003317 struct weston_keyboard *keyboard;
3318
Derek Foreman1281a362015-07-31 16:55:32 -05003319 if (seat->keyboard_state) {
Jonas Ådahld6e1c342013-10-17 23:04:05 +02003320 seat->keyboard_device_count += 1;
3321 if (seat->keyboard_device_count == 1)
3322 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003323 return 0;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02003324 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003325
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04003326 keyboard = weston_keyboard_create();
3327 if (keyboard == NULL) {
3328 weston_log("failed to allocate weston keyboard struct\n");
3329 return -1;
3330 }
3331
Derek Foreman185d1582017-06-28 11:17:23 -05003332 if (keymap != NULL) {
3333 keyboard->xkb_info = weston_xkb_info_create(keymap);
3334 if (keyboard->xkb_info == NULL)
Ander Conselvan de Oliveira4d363cf2014-01-31 17:35:45 +02003335 goto err;
Derek Foreman185d1582017-06-28 11:17:23 -05003336 } else {
3337 if (weston_compositor_build_global_keymap(seat->compositor) < 0)
3338 goto err;
3339 keyboard->xkb_info = seat->compositor->xkb_info;
3340 keyboard->xkb_info->ref_count++;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01003341 }
Derek Foreman185d1582017-06-28 11:17:23 -05003342
3343 keyboard->xkb_state.state = xkb_state_new(keyboard->xkb_info->keymap);
3344 if (keyboard->xkb_state.state == NULL) {
3345 weston_log("failed to initialise XKB state\n");
3346 goto err;
3347 }
3348
3349 keyboard->xkb_state.leds = 0;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01003350
Derek Foreman1281a362015-07-31 16:55:32 -05003351 seat->keyboard_state = keyboard;
Ander Conselvan de Oliveira4d363cf2014-01-31 17:35:45 +02003352 seat->keyboard_device_count = 1;
3353 keyboard->seat = seat;
3354
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04003355 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003356
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003357 return 0;
Ander Conselvan de Oliveira4d363cf2014-01-31 17:35:45 +02003358
3359err:
3360 if (keyboard->xkb_info)
3361 weston_xkb_info_destroy(keyboard->xkb_info);
3362 free(keyboard);
3363
3364 return -1;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003365}
3366
Jonas Ådahl91fed542013-12-03 09:14:27 +01003367static void
3368weston_keyboard_reset_state(struct weston_keyboard *keyboard)
3369{
3370 struct weston_seat *seat = keyboard->seat;
3371 struct xkb_state *state;
3372
Derek Foreman185d1582017-06-28 11:17:23 -05003373 state = xkb_state_new(keyboard->xkb_info->keymap);
3374 if (!state) {
3375 weston_log("failed to reset XKB state\n");
3376 return;
Jonas Ådahl91fed542013-12-03 09:14:27 +01003377 }
Derek Foreman185d1582017-06-28 11:17:23 -05003378 xkb_state_unref(keyboard->xkb_state.state);
3379 keyboard->xkb_state.state = state;
3380
3381 keyboard->xkb_state.leds = 0;
Jonas Ådahl91fed542013-12-03 09:14:27 +01003382
3383 seat->modifier_state = 0;
3384}
3385
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003386WL_EXPORT void
Jonas Ådahld6e1c342013-10-17 23:04:05 +02003387weston_seat_release_keyboard(struct weston_seat *seat)
3388{
3389 seat->keyboard_device_count--;
Derek Foremand621df22014-11-19 11:04:12 -06003390 assert(seat->keyboard_device_count >= 0);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02003391 if (seat->keyboard_device_count == 0) {
Derek Foreman1281a362015-07-31 16:55:32 -05003392 weston_keyboard_set_focus(seat->keyboard_state, NULL);
3393 weston_keyboard_cancel_grab(seat->keyboard_state);
3394 weston_keyboard_reset_state(seat->keyboard_state);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02003395 seat_send_updated_caps(seat);
3396 }
3397}
3398
Marius Vladeb34f822021-03-30 23:09:05 +03003399WL_EXPORT int
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003400weston_seat_init_pointer(struct weston_seat *seat)
3401{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04003402 struct weston_pointer *pointer;
3403
Derek Foreman1281a362015-07-31 16:55:32 -05003404 if (seat->pointer_state) {
Jonas Ådahld6e1c342013-10-17 23:04:05 +02003405 seat->pointer_device_count += 1;
3406 if (seat->pointer_device_count == 1)
3407 seat_send_updated_caps(seat);
Marius Vladeb34f822021-03-30 23:09:05 +03003408 return 0;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02003409 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003410
Giulio Camuffocdb4d292013-11-14 23:42:53 +01003411 pointer = weston_pointer_create(seat);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04003412 if (pointer == NULL)
Marius Vladeb34f822021-03-30 23:09:05 +03003413 return -1;
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04003414
Derek Foreman1281a362015-07-31 16:55:32 -05003415 seat->pointer_state = pointer;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02003416 seat->pointer_device_count = 1;
3417 pointer->seat = seat;
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04003418
3419 seat_send_updated_caps(seat);
Marius Vladeb34f822021-03-30 23:09:05 +03003420
3421 return 0;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003422}
3423
3424WL_EXPORT void
Jonas Ådahld6e1c342013-10-17 23:04:05 +02003425weston_seat_release_pointer(struct weston_seat *seat)
3426{
Derek Foreman1281a362015-07-31 16:55:32 -05003427 struct weston_pointer *pointer = seat->pointer_state;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02003428
3429 seat->pointer_device_count--;
3430 if (seat->pointer_device_count == 0) {
Derek Foremanf9318d12015-05-11 15:40:11 -05003431 weston_pointer_clear_focus(pointer);
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02003432 weston_pointer_cancel_grab(pointer);
Jonas Ådahl630bae82013-10-17 23:04:06 +02003433
Jonas Ådahla4932742013-10-17 23:04:07 +02003434 if (pointer->sprite)
3435 pointer_unmap_sprite(pointer);
3436
Jonas Ådahl3e12e632013-12-02 22:05:05 +01003437 weston_pointer_reset_state(pointer);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02003438 seat_send_updated_caps(seat);
Derek Foremanfd5ca512015-01-07 15:00:25 -06003439
3440 /* seat->pointer is intentionally not destroyed so that
3441 * a newly attached pointer on this seat will retain
3442 * the previous cursor co-ordinates.
3443 */
Jonas Ådahld6e1c342013-10-17 23:04:05 +02003444 }
3445}
3446
Marius Vladeb34f822021-03-30 23:09:05 +03003447WL_EXPORT int
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003448weston_seat_init_touch(struct weston_seat *seat)
3449{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04003450 struct weston_touch *touch;
3451
Derek Foreman1281a362015-07-31 16:55:32 -05003452 if (seat->touch_state) {
Jonas Ådahld6e1c342013-10-17 23:04:05 +02003453 seat->touch_device_count += 1;
3454 if (seat->touch_device_count == 1)
3455 seat_send_updated_caps(seat);
Marius Vladeb34f822021-03-30 23:09:05 +03003456 return 0;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02003457 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003458
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04003459 touch = weston_touch_create();
3460 if (touch == NULL)
Marius Vladeb34f822021-03-30 23:09:05 +03003461 return -1;
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04003462
Derek Foreman1281a362015-07-31 16:55:32 -05003463 seat->touch_state = touch;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02003464 seat->touch_device_count = 1;
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04003465 touch->seat = seat;
3466
3467 seat_send_updated_caps(seat);
Marius Vladeb34f822021-03-30 23:09:05 +03003468
3469 return 0;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003470}
3471
3472WL_EXPORT void
Jonas Ådahld6e1c342013-10-17 23:04:05 +02003473weston_seat_release_touch(struct weston_seat *seat)
3474{
3475 seat->touch_device_count--;
3476 if (seat->touch_device_count == 0) {
Derek Foreman1281a362015-07-31 16:55:32 -05003477 weston_touch_set_focus(seat->touch_state, NULL);
3478 weston_touch_cancel_grab(seat->touch_state);
3479 weston_touch_reset_state(seat->touch_state);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02003480 seat_send_updated_caps(seat);
3481 }
3482}
3483
3484WL_EXPORT void
Rob Bradford9af5f9e2013-05-31 18:09:50 +01003485weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec,
3486 const char *seat_name)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003487{
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04003488 memset(seat, 0, sizeof *seat);
3489
Kristian Høgsberge3148752013-05-06 23:19:49 -04003490 seat->selection_data_source = NULL;
3491 wl_list_init(&seat->base_resource_list);
3492 wl_signal_init(&seat->selection_signal);
3493 wl_list_init(&seat->drag_resource_list);
Kristian Høgsberge3148752013-05-06 23:19:49 -04003494 wl_signal_init(&seat->destroy_signal);
Jason Ekstranda4ab5422014-04-02 19:53:45 -05003495 wl_signal_init(&seat->updated_caps_signal);
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04003496
Sebastian Wickabec5122019-11-01 02:38:45 +01003497 seat->global = wl_global_create(ec->wl_display, &wl_seat_interface,
3498 MIN(wl_seat_interface.version, 7),
Kristian Høgsberg919cddb2013-07-08 19:03:57 -04003499 seat, bind_seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003500
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003501 seat->compositor = ec;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003502 seat->modifier_state = 0;
Rob Bradford9af5f9e2013-05-31 18:09:50 +01003503 seat->seat_name = strdup(seat_name);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003504
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003505 wl_list_insert(ec->seat_list.prev, &seat->link);
3506
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003507 clipboard_create(seat);
3508
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003509 wl_signal_emit(&ec->seat_created_signal, seat);
3510}
3511
3512WL_EXPORT void
3513weston_seat_release(struct weston_seat *seat)
3514{
Alexandros Frantzis8480d132018-02-15 13:07:09 +02003515 struct wl_resource *resource;
3516
3517 wl_resource_for_each(resource, &seat->base_resource_list) {
3518 wl_resource_set_user_data(resource, NULL);
3519 }
3520
3521 wl_resource_for_each(resource, &seat->drag_resource_list) {
3522 wl_resource_set_user_data(resource, NULL);
3523 }
3524
3525 wl_list_remove(&seat->base_resource_list);
3526 wl_list_remove(&seat->drag_resource_list);
3527
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003528 wl_list_remove(&seat->link);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003529
Jonas Ådahl1afb2382014-01-03 19:46:51 +01003530 if (seat->saved_kbd_focus)
3531 wl_list_remove(&seat->saved_kbd_focus_listener.link);
3532
Derek Foreman1281a362015-07-31 16:55:32 -05003533 if (seat->pointer_state)
3534 weston_pointer_destroy(seat->pointer_state);
3535 if (seat->keyboard_state)
3536 weston_keyboard_destroy(seat->keyboard_state);
3537 if (seat->touch_state)
3538 weston_touch_destroy(seat->touch_state);
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04003539
Rob Bradford9af5f9e2013-05-31 18:09:50 +01003540 free (seat->seat_name);
3541
Kristian Høgsberg919cddb2013-07-08 19:03:57 -04003542 wl_global_destroy(seat->global);
Kristian Høgsbergaaadc772013-07-08 16:20:31 -04003543
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003544 wl_signal_emit(&seat->destroy_signal, seat);
3545}
Derek Foreman1281a362015-07-31 16:55:32 -05003546
3547/** Get a seat's keyboard pointer
3548 *
3549 * \param seat The seat to query
3550 * \return The seat's keyboard pointer, or NULL if no keyboard is present
3551 *
3552 * The keyboard pointer for a seat isn't freed when all keyboards are removed,
3553 * so it should only be used when the seat's keyboard_device_count is greater
3554 * than zero. This function does that test and only returns a pointer
3555 * when a keyboard is present.
3556 */
3557WL_EXPORT struct weston_keyboard *
3558weston_seat_get_keyboard(struct weston_seat *seat)
3559{
3560 if (!seat)
3561 return NULL;
3562
3563 if (seat->keyboard_device_count)
3564 return seat->keyboard_state;
3565
3566 return NULL;
3567}
3568
3569/** Get a seat's pointer pointer
3570 *
3571 * \param seat The seat to query
3572 * \return The seat's pointer pointer, or NULL if no pointer device is present
3573 *
3574 * The pointer pointer for a seat isn't freed when all mice are removed,
3575 * so it should only be used when the seat's pointer_device_count is greater
3576 * than zero. This function does that test and only returns a pointer
3577 * when a pointing device is present.
3578 */
3579WL_EXPORT struct weston_pointer *
3580weston_seat_get_pointer(struct weston_seat *seat)
3581{
3582 if (!seat)
3583 return NULL;
3584
3585 if (seat->pointer_device_count)
3586 return seat->pointer_state;
3587
3588 return NULL;
3589}
3590
Jonas Ådahld3414f22016-07-22 17:56:31 +08003591static const struct zwp_locked_pointer_v1_interface locked_pointer_interface;
3592static const struct zwp_confined_pointer_v1_interface confined_pointer_interface;
3593
3594static enum pointer_constraint_type
3595pointer_constraint_get_type(struct weston_pointer_constraint *constraint)
3596{
3597 if (wl_resource_instance_of(constraint->resource,
3598 &zwp_locked_pointer_v1_interface,
3599 &locked_pointer_interface)) {
3600 return POINTER_CONSTRAINT_TYPE_LOCK;
3601 } else if (wl_resource_instance_of(constraint->resource,
3602 &zwp_confined_pointer_v1_interface,
3603 &confined_pointer_interface)) {
3604 return POINTER_CONSTRAINT_TYPE_CONFINE;
3605 }
3606
3607 abort();
3608 return 0;
3609}
3610
3611static void
3612pointer_constraint_notify_activated(struct weston_pointer_constraint *constraint)
3613{
3614 struct wl_resource *resource = constraint->resource;
3615
3616 switch (pointer_constraint_get_type(constraint)) {
3617 case POINTER_CONSTRAINT_TYPE_LOCK:
3618 zwp_locked_pointer_v1_send_locked(resource);
3619 break;
3620 case POINTER_CONSTRAINT_TYPE_CONFINE:
3621 zwp_confined_pointer_v1_send_confined(resource);
3622 break;
3623 }
3624}
3625
3626static void
3627pointer_constraint_notify_deactivated(struct weston_pointer_constraint *constraint)
3628{
3629 struct wl_resource *resource = constraint->resource;
3630
3631 switch (pointer_constraint_get_type(constraint)) {
3632 case POINTER_CONSTRAINT_TYPE_LOCK:
3633 zwp_locked_pointer_v1_send_unlocked(resource);
3634 break;
3635 case POINTER_CONSTRAINT_TYPE_CONFINE:
3636 zwp_confined_pointer_v1_send_unconfined(resource);
3637 break;
3638 }
3639}
3640
3641static struct weston_pointer_constraint *
3642get_pointer_constraint_for_pointer(struct weston_surface *surface,
3643 struct weston_pointer *pointer)
3644{
3645 struct weston_pointer_constraint *constraint;
3646
3647 wl_list_for_each(constraint, &surface->pointer_constraints, link) {
3648 if (constraint->pointer == pointer)
3649 return constraint;
3650 }
3651
3652 return NULL;
3653}
3654
Derek Foreman1281a362015-07-31 16:55:32 -05003655/** Get a seat's touch pointer
3656 *
3657 * \param seat The seat to query
3658 * \return The seat's touch pointer, or NULL if no touch device is present
3659 *
3660 * The touch pointer for a seat isn't freed when all touch devices are removed,
3661 * so it should only be used when the seat's touch_device_count is greater
3662 * than zero. This function does that test and only returns a pointer
3663 * when a touch device is present.
3664 */
3665WL_EXPORT struct weston_touch *
3666weston_seat_get_touch(struct weston_seat *seat)
3667{
3668 if (!seat)
3669 return NULL;
3670
3671 if (seat->touch_device_count)
3672 return seat->touch_state;
3673
3674 return NULL;
3675}
Bryce Harrington24f917e2016-06-29 19:04:07 -07003676
3677/** Sets the keyboard focus to the given surface
3678 *
Marius Vlada2dace22019-06-12 16:05:44 +03003679 * \param surface the surface to focus on
Bryce Harrington24f917e2016-06-29 19:04:07 -07003680 * \param seat The seat to query
3681 */
3682WL_EXPORT void
3683weston_seat_set_keyboard_focus(struct weston_seat *seat,
3684 struct weston_surface *surface)
3685{
3686 struct weston_compositor *compositor = seat->compositor;
Jonas Ådahlf7deb6a2016-07-22 17:50:26 +08003687 struct weston_surface_activation_data activation_data;
Bryce Harrington24f917e2016-06-29 19:04:07 -07003688
Jonas Ådahl94e2e2d2014-10-18 18:42:19 +02003689 inc_activate_serial(compositor);
Jonas Ådahlf7deb6a2016-07-22 17:50:26 +08003690
3691 activation_data = (struct weston_surface_activation_data) {
3692 .surface = surface,
3693 .seat = seat,
3694 };
3695 wl_signal_emit(&compositor->activate_signal, &activation_data);
Bryce Harrington24f917e2016-06-29 19:04:07 -07003696}
Jonas Ådahl30d61d82014-10-22 21:21:17 +02003697
Jonas Ådahld3414f22016-07-22 17:56:31 +08003698static void
3699enable_pointer_constraint(struct weston_pointer_constraint *constraint,
3700 struct weston_view *view)
3701{
3702 assert(constraint->view == NULL);
3703 constraint->view = view;
3704 pointer_constraint_notify_activated(constraint);
3705 weston_pointer_start_grab(constraint->pointer, &constraint->grab);
3706 wl_list_remove(&constraint->surface_destroy_listener.link);
3707 wl_list_init(&constraint->surface_destroy_listener.link);
3708}
3709
3710static bool
3711is_pointer_constraint_enabled(struct weston_pointer_constraint *constraint)
3712{
3713 return constraint->view != NULL;
3714}
3715
3716static void
3717weston_pointer_constraint_disable(struct weston_pointer_constraint *constraint)
3718{
3719 constraint->view = NULL;
3720 pointer_constraint_notify_deactivated(constraint);
3721 weston_pointer_end_grab(constraint->grab.pointer);
3722}
3723
3724void
3725weston_pointer_constraint_destroy(struct weston_pointer_constraint *constraint)
3726{
3727 if (is_pointer_constraint_enabled(constraint))
3728 weston_pointer_constraint_disable(constraint);
3729
3730 wl_list_remove(&constraint->pointer_destroy_listener.link);
3731 wl_list_remove(&constraint->surface_destroy_listener.link);
3732 wl_list_remove(&constraint->surface_commit_listener.link);
3733 wl_list_remove(&constraint->surface_activate_listener.link);
3734
3735 wl_resource_set_user_data(constraint->resource, NULL);
3736 pixman_region32_fini(&constraint->region);
3737 wl_list_remove(&constraint->link);
3738 free(constraint);
3739}
3740
3741static void
3742disable_pointer_constraint(struct weston_pointer_constraint *constraint)
3743{
3744 switch (constraint->lifetime) {
3745 case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT:
3746 weston_pointer_constraint_destroy(constraint);
3747 break;
3748 case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT:
3749 weston_pointer_constraint_disable(constraint);
3750 break;
3751 }
3752}
3753
3754static bool
3755is_within_constraint_region(struct weston_pointer_constraint *constraint,
3756 wl_fixed_t sx, wl_fixed_t sy)
3757{
3758 struct weston_surface *surface = constraint->surface;
3759 pixman_region32_t constraint_region;
3760 bool result;
3761
3762 pixman_region32_init(&constraint_region);
3763 pixman_region32_intersect(&constraint_region,
3764 &surface->input,
3765 &constraint->region);
3766 result = pixman_region32_contains_point(&constraint_region,
3767 wl_fixed_to_int(sx),
3768 wl_fixed_to_int(sy),
3769 NULL);
3770 pixman_region32_fini(&constraint_region);
3771
3772 return result;
3773}
3774
3775static void
3776maybe_enable_pointer_constraint(struct weston_pointer_constraint *constraint)
3777{
3778 struct weston_surface *surface = constraint->surface;
3779 struct weston_view *vit;
3780 struct weston_view *view = NULL;
3781 struct weston_pointer *pointer = constraint->pointer;
3782 struct weston_keyboard *keyboard;
3783 struct weston_seat *seat = pointer->seat;
3784 int32_t x, y;
3785
3786 /* Postpone if no view of the surface was most recently clicked. */
3787 wl_list_for_each(vit, &surface->views, surface_link) {
3788 if (vit->click_to_activate_serial ==
3789 surface->compositor->activate_serial) {
3790 view = vit;
3791 }
3792 }
3793 if (view == NULL)
3794 return;
3795
3796 /* Postpone if surface doesn't have keyboard focus. */
3797 keyboard = weston_seat_get_keyboard(seat);
3798 if (!keyboard || keyboard->focus != surface)
3799 return;
3800
3801 /* Postpone constraint if the pointer is not within the
3802 * constraint region.
3803 */
3804 weston_view_from_global(view,
3805 wl_fixed_to_int(pointer->x),
3806 wl_fixed_to_int(pointer->y),
3807 &x, &y);
3808 if (!is_within_constraint_region(constraint,
3809 wl_fixed_from_int(x),
3810 wl_fixed_from_int(y)))
3811 return;
3812
3813 enable_pointer_constraint(constraint, view);
3814}
3815
3816static void
3817locked_pointer_grab_pointer_focus(struct weston_pointer_grab *grab)
3818{
3819}
3820
3821static void
3822locked_pointer_grab_pointer_motion(struct weston_pointer_grab *grab,
Alexandros Frantzis84b31f82017-11-24 18:01:46 +02003823 const struct timespec *time,
Jonas Ådahld3414f22016-07-22 17:56:31 +08003824 struct weston_pointer_motion_event *event)
3825{
Quentin Glidiccde13452016-08-12 10:41:32 +02003826 pointer_send_relative_motion(grab->pointer, time, event);
Jonas Ådahld3414f22016-07-22 17:56:31 +08003827}
3828
3829static void
3830locked_pointer_grab_pointer_button(struct weston_pointer_grab *grab,
Alexandros Frantzis215bedc2017-11-16 18:20:55 +02003831 const struct timespec *time,
Jonas Ådahld3414f22016-07-22 17:56:31 +08003832 uint32_t button,
3833 uint32_t state_w)
3834{
3835 weston_pointer_send_button(grab->pointer, time, button, state_w);
3836}
3837
3838static void
3839locked_pointer_grab_pointer_axis(struct weston_pointer_grab *grab,
Alexandros Frantzis80321942017-11-16 18:20:56 +02003840 const struct timespec *time,
Jonas Ådahld3414f22016-07-22 17:56:31 +08003841 struct weston_pointer_axis_event *event)
3842{
3843 weston_pointer_send_axis(grab->pointer, time, event);
3844}
3845
3846static void
3847locked_pointer_grab_pointer_axis_source(struct weston_pointer_grab *grab,
3848 uint32_t source)
3849{
3850 weston_pointer_send_axis_source(grab->pointer, source);
3851}
3852
3853static void
3854locked_pointer_grab_pointer_frame(struct weston_pointer_grab *grab)
3855{
3856 weston_pointer_send_frame(grab->pointer);
3857}
3858
3859static void
3860locked_pointer_grab_pointer_cancel(struct weston_pointer_grab *grab)
3861{
3862 struct weston_pointer_constraint *constraint =
3863 container_of(grab, struct weston_pointer_constraint, grab);
3864
3865 disable_pointer_constraint(constraint);
3866}
3867
3868static const struct weston_pointer_grab_interface
3869 locked_pointer_grab_interface = {
3870 locked_pointer_grab_pointer_focus,
3871 locked_pointer_grab_pointer_motion,
3872 locked_pointer_grab_pointer_button,
3873 locked_pointer_grab_pointer_axis,
3874 locked_pointer_grab_pointer_axis_source,
3875 locked_pointer_grab_pointer_frame,
3876 locked_pointer_grab_pointer_cancel,
3877};
3878
3879static void
3880pointer_constraint_constrain_resource_destroyed(struct wl_resource *resource)
3881{
3882 struct weston_pointer_constraint *constraint =
3883 wl_resource_get_user_data(resource);
3884
3885 if (!constraint)
3886 return;
3887
3888 weston_pointer_constraint_destroy(constraint);
3889}
3890
3891static void
3892pointer_constraint_surface_activate(struct wl_listener *listener, void *data)
3893{
3894 struct weston_surface_activation_data *activation = data;
3895 struct weston_pointer *pointer;
3896 struct weston_surface *focus = activation->surface;
3897 struct weston_pointer_constraint *constraint =
3898 container_of(listener, struct weston_pointer_constraint,
3899 surface_activate_listener);
3900 bool is_constraint_surface;
3901
3902 pointer = weston_seat_get_pointer(activation->seat);
3903 if (!pointer)
3904 return;
3905
3906 is_constraint_surface =
3907 get_pointer_constraint_for_pointer(focus, pointer) == constraint;
3908
3909 if (is_constraint_surface &&
3910 !is_pointer_constraint_enabled(constraint))
3911 maybe_enable_pointer_constraint(constraint);
3912 else if (!is_constraint_surface &&
3913 is_pointer_constraint_enabled(constraint))
3914 disable_pointer_constraint(constraint);
3915}
3916
3917static void
3918pointer_constraint_pointer_destroyed(struct wl_listener *listener, void *data)
3919{
3920 struct weston_pointer_constraint *constraint =
3921 container_of(listener, struct weston_pointer_constraint,
3922 pointer_destroy_listener);
3923
3924 weston_pointer_constraint_destroy(constraint);
3925}
3926
3927static void
3928pointer_constraint_surface_destroyed(struct wl_listener *listener, void *data)
3929{
3930 struct weston_pointer_constraint *constraint =
3931 container_of(listener, struct weston_pointer_constraint,
3932 surface_destroy_listener);
3933
3934 weston_pointer_constraint_destroy(constraint);
3935}
3936
3937static void
3938pointer_constraint_surface_committed(struct wl_listener *listener, void *data)
3939{
3940 struct weston_pointer_constraint *constraint =
3941 container_of(listener, struct weston_pointer_constraint,
3942 surface_commit_listener);
3943
3944 if (constraint->region_is_pending) {
3945 constraint->region_is_pending = false;
3946 pixman_region32_copy(&constraint->region,
3947 &constraint->region_pending);
3948 pixman_region32_fini(&constraint->region_pending);
3949 pixman_region32_init(&constraint->region_pending);
3950 }
3951
3952 if (constraint->hint_is_pending) {
3953 constraint->hint_is_pending = false;
3954
3955 constraint->hint_is_pending = true;
3956 constraint->hint_x = constraint->hint_x_pending;
3957 constraint->hint_y = constraint->hint_y_pending;
3958 }
3959
3960 if (pointer_constraint_get_type(constraint) ==
3961 POINTER_CONSTRAINT_TYPE_CONFINE &&
3962 is_pointer_constraint_enabled(constraint))
3963 maybe_warp_confined_pointer(constraint);
3964}
3965
3966static struct weston_pointer_constraint *
3967weston_pointer_constraint_create(struct weston_surface *surface,
3968 struct weston_pointer *pointer,
3969 struct weston_region *region,
3970 enum zwp_pointer_constraints_v1_lifetime lifetime,
3971 struct wl_resource *cr,
3972 const struct weston_pointer_grab_interface *grab_interface)
3973{
3974 struct weston_pointer_constraint *constraint;
3975
3976 constraint = zalloc(sizeof *constraint);
3977 if (!constraint)
3978 return NULL;
3979
3980 constraint->lifetime = lifetime;
3981 pixman_region32_init(&constraint->region);
3982 pixman_region32_init(&constraint->region_pending);
3983 wl_list_insert(&surface->pointer_constraints, &constraint->link);
3984 constraint->surface = surface;
3985 constraint->pointer = pointer;
3986 constraint->resource = cr;
3987 constraint->grab.interface = grab_interface;
3988 if (region) {
3989 pixman_region32_copy(&constraint->region,
3990 &region->region);
3991 } else {
3992 pixman_region32_fini(&constraint->region);
3993 region_init_infinite(&constraint->region);
3994 }
3995
3996 constraint->surface_activate_listener.notify =
3997 pointer_constraint_surface_activate;
3998 constraint->surface_destroy_listener.notify =
3999 pointer_constraint_surface_destroyed;
4000 constraint->surface_commit_listener.notify =
4001 pointer_constraint_surface_committed;
4002 constraint->pointer_destroy_listener.notify =
4003 pointer_constraint_pointer_destroyed;
4004
4005 wl_signal_add(&surface->compositor->activate_signal,
4006 &constraint->surface_activate_listener);
4007 wl_signal_add(&pointer->destroy_signal,
4008 &constraint->pointer_destroy_listener);
4009 wl_signal_add(&surface->destroy_signal,
4010 &constraint->surface_destroy_listener);
4011 wl_signal_add(&surface->commit_signal,
4012 &constraint->surface_commit_listener);
4013
4014 return constraint;
4015}
4016
4017static void
4018init_pointer_constraint(struct wl_resource *pointer_constraints_resource,
4019 uint32_t id,
4020 struct weston_surface *surface,
4021 struct weston_pointer *pointer,
4022 struct weston_region *region,
4023 enum zwp_pointer_constraints_v1_lifetime lifetime,
4024 const struct wl_interface *interface,
4025 const void *implementation,
4026 const struct weston_pointer_grab_interface *grab_interface)
4027{
4028 struct wl_client *client =
4029 wl_resource_get_client(pointer_constraints_resource);
4030 struct wl_resource *cr;
4031 struct weston_pointer_constraint *constraint;
4032
Alexandros Frantzis0f14ae92018-02-08 15:37:52 +02004033 if (pointer && get_pointer_constraint_for_pointer(surface, pointer)) {
Jonas Ådahld3414f22016-07-22 17:56:31 +08004034 wl_resource_post_error(pointer_constraints_resource,
4035 ZWP_POINTER_CONSTRAINTS_V1_ERROR_ALREADY_CONSTRAINED,
4036 "the pointer has a lock/confine request on this surface");
4037 return;
4038 }
4039
4040 cr = wl_resource_create(client, interface,
4041 wl_resource_get_version(pointer_constraints_resource),
4042 id);
4043 if (cr == NULL) {
4044 wl_client_post_no_memory(client);
4045 return;
4046 }
4047
Alexandros Frantzis0f14ae92018-02-08 15:37:52 +02004048 if (pointer) {
4049 constraint = weston_pointer_constraint_create(surface, pointer,
4050 region, lifetime,
4051 cr, grab_interface);
4052 if (constraint == NULL) {
4053 wl_client_post_no_memory(client);
4054 return;
4055 }
4056 } else {
4057 constraint = NULL;
Jonas Ådahld3414f22016-07-22 17:56:31 +08004058 }
4059
4060 wl_resource_set_implementation(cr, implementation, constraint,
4061 pointer_constraint_constrain_resource_destroyed);
4062
Alexandros Frantzis0f14ae92018-02-08 15:37:52 +02004063 if (constraint)
4064 maybe_enable_pointer_constraint(constraint);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004065}
4066
4067static void
4068pointer_constraints_destroy(struct wl_client *client,
4069 struct wl_resource *resource)
4070{
4071 wl_resource_destroy(resource);
4072}
4073
4074static void
4075locked_pointer_destroy(struct wl_client *client,
4076 struct wl_resource *resource)
4077{
4078 struct weston_pointer_constraint *constraint =
4079 wl_resource_get_user_data(resource);
4080 wl_fixed_t x, y;
4081
4082 if (constraint && constraint->view && constraint->hint_is_pending &&
4083 is_within_constraint_region(constraint,
4084 constraint->hint_x,
4085 constraint->hint_y)) {
4086 weston_view_to_global_fixed(constraint->view,
4087 constraint->hint_x,
4088 constraint->hint_y,
4089 &x, &y);
4090 weston_pointer_move_to(constraint->pointer, x, y);
4091 }
4092 wl_resource_destroy(resource);
4093}
4094
4095static void
4096locked_pointer_set_cursor_position_hint(struct wl_client *client,
4097 struct wl_resource *resource,
4098 wl_fixed_t surface_x,
4099 wl_fixed_t surface_y)
4100{
4101 struct weston_pointer_constraint *constraint =
4102 wl_resource_get_user_data(resource);
4103
4104 /* Ignore a set cursor hint that was sent after the lock was cancelled.
4105 */
4106 if (!constraint ||
4107 !constraint->resource ||
4108 constraint->resource != resource)
4109 return;
4110
4111 constraint->hint_is_pending = true;
4112 constraint->hint_x_pending = surface_x;
4113 constraint->hint_y_pending = surface_y;
4114}
4115
4116static void
4117locked_pointer_set_region(struct wl_client *client,
4118 struct wl_resource *resource,
4119 struct wl_resource *region_resource)
4120{
4121 struct weston_pointer_constraint *constraint =
4122 wl_resource_get_user_data(resource);
4123 struct weston_region *region = region_resource ?
4124 wl_resource_get_user_data(region_resource) : NULL;
4125
4126 if (!constraint)
4127 return;
4128
4129 if (region) {
4130 pixman_region32_copy(&constraint->region_pending,
4131 &region->region);
4132 } else {
4133 pixman_region32_fini(&constraint->region_pending);
4134 region_init_infinite(&constraint->region_pending);
4135 }
4136 constraint->region_is_pending = true;
4137}
4138
4139
4140static const struct zwp_locked_pointer_v1_interface locked_pointer_interface = {
4141 locked_pointer_destroy,
4142 locked_pointer_set_cursor_position_hint,
4143 locked_pointer_set_region,
4144};
4145
4146static void
4147pointer_constraints_lock_pointer(struct wl_client *client,
4148 struct wl_resource *resource,
4149 uint32_t id,
4150 struct wl_resource *surface_resource,
4151 struct wl_resource *pointer_resource,
4152 struct wl_resource *region_resource,
4153 uint32_t lifetime)
4154{
4155 struct weston_surface *surface =
4156 wl_resource_get_user_data(surface_resource);
4157 struct weston_pointer *pointer = wl_resource_get_user_data(pointer_resource);
4158 struct weston_region *region = region_resource ?
4159 wl_resource_get_user_data(region_resource) : NULL;
4160
4161 init_pointer_constraint(resource, id, surface, pointer, region, lifetime,
4162 &zwp_locked_pointer_v1_interface,
4163 &locked_pointer_interface,
4164 &locked_pointer_grab_interface);
4165}
4166
4167static void
4168confined_pointer_grab_pointer_focus(struct weston_pointer_grab *grab)
4169{
4170}
4171
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004172static double
4173vec2d_cross_product(struct vec2d a, struct vec2d b)
4174{
4175 return a.x * b.y - a.y * b.x;
4176}
4177
4178static struct vec2d
4179vec2d_add(struct vec2d a, struct vec2d b)
4180{
4181 return (struct vec2d) {
4182 .x = a.x + b.x,
4183 .y = a.y + b.y,
4184 };
4185}
4186
4187static struct vec2d
4188vec2d_subtract(struct vec2d a, struct vec2d b)
4189{
4190 return (struct vec2d) {
4191 .x = a.x - b.x,
4192 .y = a.y - b.y,
4193 };
4194}
4195
4196static struct vec2d
4197vec2d_multiply_constant(double c, struct vec2d a)
4198{
4199 return (struct vec2d) {
4200 .x = c * a.x,
4201 .y = c * a.y,
4202 };
4203}
4204
4205static bool
4206lines_intersect(struct line *line1, struct line *line2,
4207 struct vec2d *intersection)
4208{
4209 struct vec2d p = line1->a;
4210 struct vec2d r = vec2d_subtract(line1->b, line1->a);
4211 struct vec2d q = line2->a;
4212 struct vec2d s = vec2d_subtract(line2->b, line2->a);
4213 double rxs;
4214 double sxr;
4215 double t;
4216 double u;
4217
4218 /*
4219 * The line (p, r) and (q, s) intersects where
4220 *
4221 * p + t r = q + u s
4222 *
4223 * Calculate t:
4224 *
4225 * (p + t r) × s = (q + u s) × s
4226 * p × s + t (r × s) = q × s + u (s × s)
4227 * p × s + t (r × s) = q × s
4228 * t (r × s) = q × s - p × s
4229 * t (r × s) = (q - p) × s
4230 * t = ((q - p) × s) / (r × s)
4231 *
4232 * Using the same method, for u we get:
4233 *
4234 * u = ((p - q) × r) / (s × r)
4235 */
4236
4237 rxs = vec2d_cross_product(r, s);
4238 sxr = vec2d_cross_product(s, r);
4239
4240 /* If r × s = 0 then the lines are either parallel or collinear. */
4241 if (fabs(rxs) < DBL_MIN)
4242 return false;
4243
4244 t = vec2d_cross_product(vec2d_subtract(q, p), s) / rxs;
4245 u = vec2d_cross_product(vec2d_subtract(p, q), r) / sxr;
4246
4247 /* The lines only intersect if 0 ≤ t ≤ 1 and 0 ≤ u ≤ 1. */
4248 if (t < 0.0 || t > 1.0 || u < 0.0 || u > 1.0)
4249 return false;
4250
4251 *intersection = vec2d_add(p, vec2d_multiply_constant(t, r));
4252 return true;
4253}
4254
4255static struct border *
4256add_border(struct wl_array *array,
4257 double x1, double y1,
4258 double x2, double y2,
4259 enum motion_direction blocking_dir)
4260{
4261 struct border *border = wl_array_add(array, sizeof *border);
4262
4263 *border = (struct border) {
4264 .line = (struct line) {
4265 .a = (struct vec2d) {
4266 .x = x1,
4267 .y = y1,
4268 },
4269 .b = (struct vec2d) {
4270 .x = x2,
4271 .y = y2,
4272 },
4273 },
4274 .blocking_dir = blocking_dir,
4275 };
4276
4277 return border;
4278}
4279
4280static int
4281compare_lines_x(const void *a, const void *b)
4282{
4283 const struct border *border_a = a;
4284 const struct border *border_b = b;
4285
4286
4287 if (border_a->line.a.x == border_b->line.a.x)
4288 return border_a->line.b.x < border_b->line.b.x;
4289 else
4290 return border_a->line.a.x > border_b->line.a.x;
4291}
4292
4293static void
4294add_non_overlapping_edges(pixman_box32_t *boxes,
4295 int band_above_start,
4296 int band_below_start,
4297 int band_below_end,
4298 struct wl_array *borders)
4299{
4300 int i;
4301 struct wl_array band_merge;
4302 struct border *border;
4303 struct border *prev_border;
4304 struct border *new_border;
4305
4306 wl_array_init(&band_merge);
4307
4308 /* Add bottom band of previous row, and top band of current row, and
4309 * sort them so lower left x coordinate comes first. If there are two
4310 * borders with the same left x coordinate, the wider one comes first.
4311 */
4312 for (i = band_above_start; i < band_below_start; i++) {
4313 pixman_box32_t *box = &boxes[i];
4314 add_border(&band_merge, box->x1, box->y2, box->x2, box->y2,
4315 MOTION_DIRECTION_POSITIVE_Y);
4316 }
4317 for (i = band_below_start; i < band_below_end; i++) {
4318 pixman_box32_t *box= &boxes[i];
4319 add_border(&band_merge, box->x1, box->y1, box->x2, box->y1,
4320 MOTION_DIRECTION_NEGATIVE_Y);
4321 }
4322 qsort(band_merge.data,
4323 band_merge.size / sizeof *border,
4324 sizeof *border,
4325 compare_lines_x);
4326
4327 /* Combine the two combined bands so that any overlapping border is
4328 * eliminated. */
4329 prev_border = NULL;
4330 wl_array_for_each(border, &band_merge) {
4331 assert(border->line.a.y == border->line.b.y);
4332 assert(!prev_border ||
4333 prev_border->line.a.y == border->line.a.y);
4334 assert(!prev_border ||
4335 (prev_border->line.a.x != border->line.a.x ||
4336 prev_border->line.b.x != border->line.b.x));
4337 assert(!prev_border ||
4338 prev_border->line.a.x <= border->line.a.x);
4339
4340 if (prev_border &&
4341 prev_border->line.a.x == border->line.a.x) {
4342 /*
4343 * ------------ +
4344 * ------- =
4345 * [ ]-----
4346 */
4347 prev_border->line.a.x = border->line.b.x;
4348 } else if (prev_border &&
4349 prev_border->line.b.x == border->line.b.x) {
4350 /*
4351 * ------------ +
4352 * ------ =
4353 * ------[ ]
4354 */
4355 prev_border->line.b.x = border->line.a.x;
4356 } else if (prev_border &&
4357 prev_border->line.b.x == border->line.a.x) {
4358 /*
4359 * -------- +
4360 * ------ =
4361 * --------------
4362 */
4363 prev_border->line.b.x = border->line.b.x;
4364 } else if (prev_border &&
4365 prev_border->line.b.x >= border->line.a.x) {
4366 /*
4367 * --------------- +
4368 * ------ =
4369 * -----[ ]----
4370 */
4371 new_border = add_border(borders,
4372 border->line.b.x,
4373 border->line.b.y,
4374 prev_border->line.b.x,
4375 prev_border->line.b.y,
4376 prev_border->blocking_dir);
4377 prev_border->line.b.x = border->line.a.x;
4378 prev_border = new_border;
4379 } else {
4380 assert(!prev_border ||
4381 prev_border->line.b.x < border->line.a.x);
4382 /*
4383 * First border or non-overlapping.
4384 *
4385 * ----- +
4386 * ----- =
4387 * ----- -----
4388 */
4389 new_border = wl_array_add(borders, sizeof *border);
4390 *new_border = *border;
4391 prev_border = new_border;
4392 }
4393 }
4394
4395 wl_array_release(&band_merge);
4396}
4397
4398static void
4399add_band_bottom_edges(pixman_box32_t *boxes,
4400 int band_start,
4401 int band_end,
4402 struct wl_array *borders)
4403{
4404 int i;
4405
4406 for (i = band_start; i < band_end; i++) {
4407 add_border(borders,
4408 boxes[i].x1, boxes[i].y2,
4409 boxes[i].x2, boxes[i].y2,
4410 MOTION_DIRECTION_POSITIVE_Y);
4411 }
4412}
4413
4414static void
4415region_to_outline(pixman_region32_t *region, struct wl_array *borders)
4416{
4417 pixman_box32_t *boxes;
4418 int num_boxes;
4419 int i;
4420 int top_most, bottom_most;
4421 int current_roof;
4422 int prev_top;
4423 int band_start, prev_band_start;
4424
4425 /*
4426 * Remove any overlapping lines from the set of rectangles. Note that
4427 * pixman regions are grouped as rows of rectangles, where rectangles
4428 * in one row never touch or overlap and are all of the same height.
4429 *
4430 * -------- --- -------- ---
4431 * | | | | | | | |
4432 * ----------====---- --- ----------- ----- ---
4433 * | | => | |
4434 * ----==========--------- ----- ----------
4435 * | | | |
4436 * ------------------- -------------------
4437 *
4438 */
4439
4440 boxes = pixman_region32_rectangles(region, &num_boxes);
4441 prev_top = 0;
4442 top_most = boxes[0].y1;
4443 current_roof = top_most;
4444 bottom_most = boxes[num_boxes - 1].y2;
4445 band_start = 0;
4446 prev_band_start = 0;
4447 for (i = 0; i < num_boxes; i++) {
4448 /* Detect if there is a vertical empty space, and add the lower
4449 * level of the previous band if so was the case. */
4450 if (i > 0 &&
4451 boxes[i].y1 != prev_top &&
4452 boxes[i].y1 != boxes[i - 1].y2) {
4453 current_roof = boxes[i].y1;
4454 add_band_bottom_edges(boxes,
4455 band_start,
4456 i,
4457 borders);
4458 }
4459
4460 /* Special case adding the last band, since it won't be handled
4461 * by the band change detection below. */
4462 if (boxes[i].y1 != current_roof && i == num_boxes - 1) {
4463 if (boxes[i].y1 != prev_top) {
4464 /* The last band is a single box, so we don't
4465 * have a prev_band_start to tell us when the
4466 * previous band started. */
4467 add_non_overlapping_edges(boxes,
4468 band_start,
4469 i,
4470 i + 1,
4471 borders);
4472 } else {
4473 add_non_overlapping_edges(boxes,
4474 prev_band_start,
4475 band_start,
4476 i + 1,
4477 borders);
4478 }
4479 }
4480
4481 /* Detect when passing a band and combine the top border of the
4482 * just passed band with the bottom band of the previous band.
4483 */
4484 if (boxes[i].y1 != top_most && boxes[i].y1 != prev_top) {
4485 /* Combine the two passed bands. */
4486 if (prev_top != current_roof) {
4487 add_non_overlapping_edges(boxes,
4488 prev_band_start,
4489 band_start,
4490 i,
4491 borders);
4492 }
4493
4494 prev_band_start = band_start;
4495 band_start = i;
4496 }
4497
4498 /* Add the top border if the box is part of the current roof. */
4499 if (boxes[i].y1 == current_roof) {
4500 add_border(borders,
4501 boxes[i].x1, boxes[i].y1,
4502 boxes[i].x2, boxes[i].y1,
4503 MOTION_DIRECTION_NEGATIVE_Y);
4504 }
4505
4506 /* Add the bottom border of the last band. */
4507 if (boxes[i].y2 == bottom_most) {
4508 add_border(borders,
4509 boxes[i].x1, boxes[i].y2,
4510 boxes[i].x2, boxes[i].y2,
4511 MOTION_DIRECTION_POSITIVE_Y);
4512 }
4513
4514 /* Always add the left border. */
4515 add_border(borders,
4516 boxes[i].x1, boxes[i].y1,
4517 boxes[i].x1, boxes[i].y2,
4518 MOTION_DIRECTION_NEGATIVE_X);
4519
4520 /* Always add the right border. */
4521 add_border(borders,
4522 boxes[i].x2, boxes[i].y1,
4523 boxes[i].x2, boxes[i].y2,
4524 MOTION_DIRECTION_POSITIVE_X);
4525
4526 prev_top = boxes[i].y1;
4527 }
4528}
4529
4530static bool
4531is_border_horizontal (struct border *border)
4532{
4533 return border->line.a.y == border->line.b.y;
4534}
4535
4536static bool
4537is_border_blocking_directions(struct border *border,
4538 uint32_t directions)
4539{
4540 /* Don't block parallel motions. */
4541 if (is_border_horizontal(border)) {
4542 if ((directions & (MOTION_DIRECTION_POSITIVE_Y |
4543 MOTION_DIRECTION_NEGATIVE_Y)) == 0)
4544 return false;
4545 } else {
4546 if ((directions & (MOTION_DIRECTION_POSITIVE_X |
4547 MOTION_DIRECTION_NEGATIVE_X)) == 0)
4548 return false;
4549 }
4550
4551 return (~border->blocking_dir & directions) != directions;
4552}
4553
4554static struct border *
4555get_closest_border(struct wl_array *borders,
4556 struct line *motion,
4557 uint32_t directions)
4558{
4559 struct border *border;
4560 struct vec2d intersection;
4561 struct vec2d delta;
4562 double distance_2;
4563 struct border *closest_border = NULL;
4564 double closest_distance_2 = DBL_MAX;
4565
4566 wl_array_for_each(border, borders) {
4567 if (!is_border_blocking_directions(border, directions))
4568 continue;
4569
4570 if (!lines_intersect(&border->line, motion, &intersection))
4571 continue;
4572
4573 delta = vec2d_subtract(intersection, motion->a);
4574 distance_2 = delta.x*delta.x + delta.y*delta.y;
4575 if (distance_2 < closest_distance_2) {
4576 closest_border = border;
4577 closest_distance_2 = distance_2;
4578 }
4579 }
4580
4581 return closest_border;
4582}
4583
4584static void
4585clamp_to_border(struct border *border,
4586 struct line *motion,
4587 uint32_t *motion_dir)
4588{
4589 /*
4590 * When clamping either rightward or downward motions, the motion needs
4591 * to be clamped so that the destination coordinate does not end up on
4592 * the border (see weston_pointer_clamp_event_to_region). Do this by
4593 * clamping such motions to the border minus the smallest possible
4594 * wl_fixed_t value.
4595 */
4596 if (is_border_horizontal(border)) {
4597 if (*motion_dir & MOTION_DIRECTION_POSITIVE_Y)
4598 motion->b.y = border->line.a.y - wl_fixed_to_double(1);
4599 else
4600 motion->b.y = border->line.a.y;
4601 *motion_dir &= ~(MOTION_DIRECTION_POSITIVE_Y |
4602 MOTION_DIRECTION_NEGATIVE_Y);
4603 } else {
4604 if (*motion_dir & MOTION_DIRECTION_POSITIVE_X)
4605 motion->b.x = border->line.a.x - wl_fixed_to_double(1);
4606 else
4607 motion->b.x = border->line.a.x;
4608 *motion_dir &= ~(MOTION_DIRECTION_POSITIVE_X |
4609 MOTION_DIRECTION_NEGATIVE_X);
4610 }
4611}
4612
4613static uint32_t
4614get_motion_directions(struct line *motion)
4615{
4616 uint32_t directions = 0;
4617
4618 if (motion->a.x < motion->b.x)
4619 directions |= MOTION_DIRECTION_POSITIVE_X;
4620 else if (motion->a.x > motion->b.x)
4621 directions |= MOTION_DIRECTION_NEGATIVE_X;
4622 if (motion->a.y < motion->b.y)
4623 directions |= MOTION_DIRECTION_POSITIVE_Y;
4624 else if (motion->a.y > motion->b.y)
4625 directions |= MOTION_DIRECTION_NEGATIVE_Y;
4626
4627 return directions;
4628}
4629
Jonas Ådahld3414f22016-07-22 17:56:31 +08004630static void
4631weston_pointer_clamp_event_to_region(struct weston_pointer *pointer,
4632 struct weston_pointer_motion_event *event,
4633 pixman_region32_t *region,
4634 wl_fixed_t *clamped_x,
4635 wl_fixed_t *clamped_y)
4636{
4637 wl_fixed_t x, y;
4638 wl_fixed_t sx, sy;
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004639 wl_fixed_t old_sx = pointer->sx;
4640 wl_fixed_t old_sy = pointer->sy;
4641 struct wl_array borders;
4642 struct line motion;
4643 struct border *closest_border;
4644 float new_x_f, new_y_f;
4645 uint32_t directions;
Jonas Ådahld3414f22016-07-22 17:56:31 +08004646
4647 weston_pointer_motion_to_abs(pointer, event, &x, &y);
4648 weston_view_from_global_fixed(pointer->focus, x, y, &sx, &sy);
4649
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004650 wl_array_init(&borders);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004651
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004652 /*
4653 * Generate borders given the confine region we are to use. The borders
4654 * are defined to be the outer region of the allowed area. This means
4655 * top/left borders are "within" the allowed area, while bottom/right
4656 * borders are outside. This needs to be considered when clamping
4657 * confined motion vectors.
4658 */
4659 region_to_outline(region, &borders);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004660
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004661 motion = (struct line) {
4662 .a = (struct vec2d) {
4663 .x = wl_fixed_to_double(old_sx),
4664 .y = wl_fixed_to_double(old_sy),
4665 },
4666 .b = (struct vec2d) {
4667 .x = wl_fixed_to_double(sx),
4668 .y = wl_fixed_to_double(sy),
4669 },
4670 };
4671 directions = get_motion_directions(&motion);
4672
4673 while (directions) {
4674 closest_border = get_closest_border(&borders,
4675 &motion,
4676 directions);
4677 if (closest_border)
4678 clamp_to_border(closest_border, &motion, &directions);
4679 else
4680 break;
4681 }
4682
4683 weston_view_to_global_float(pointer->focus,
4684 (float) motion.b.x, (float) motion.b.y,
4685 &new_x_f, &new_y_f);
4686 *clamped_x = wl_fixed_from_double(new_x_f);
4687 *clamped_y = wl_fixed_from_double(new_y_f);
4688
4689 wl_array_release(&borders);
4690}
4691
4692static double
4693point_to_border_distance_2(struct border *border, double x, double y)
4694{
4695 double orig_x, orig_y;
4696 double dx, dy;
4697
4698 if (is_border_horizontal(border)) {
4699 if (x < border->line.a.x)
4700 orig_x = border->line.a.x;
4701 else if (x > border->line.b.x)
4702 orig_x = border->line.b.x;
4703 else
4704 orig_x = x;
4705 orig_y = border->line.a.y;
4706 } else {
4707 if (y < border->line.a.y)
4708 orig_y = border->line.a.y;
4709 else if (y > border->line.b.y)
4710 orig_y = border->line.b.y;
4711 else
4712 orig_y = y;
4713 orig_x = border->line.a.x;
4714 }
4715
4716
4717 dx = fabs(orig_x - x);
4718 dy = fabs(orig_y - y);
4719 return dx*dx + dy*dy;
4720}
4721
4722static void
4723warp_to_behind_border(struct border *border, wl_fixed_t *sx, wl_fixed_t *sy)
4724{
4725 switch (border->blocking_dir) {
4726 case MOTION_DIRECTION_POSITIVE_X:
4727 case MOTION_DIRECTION_NEGATIVE_X:
4728 if (border->blocking_dir == MOTION_DIRECTION_POSITIVE_X)
4729 *sx = wl_fixed_from_double(border->line.a.x) - 1;
4730 else
4731 *sx = wl_fixed_from_double(border->line.a.x) + 1;
4732 if (*sy < wl_fixed_from_double(border->line.a.y))
4733 *sy = wl_fixed_from_double(border->line.a.y) + 1;
4734 else if (*sy > wl_fixed_from_double(border->line.b.y))
4735 *sy = wl_fixed_from_double(border->line.b.y) - 1;
4736 break;
4737 case MOTION_DIRECTION_POSITIVE_Y:
4738 case MOTION_DIRECTION_NEGATIVE_Y:
4739 if (border->blocking_dir == MOTION_DIRECTION_POSITIVE_Y)
4740 *sy = wl_fixed_from_double(border->line.a.y) - 1;
4741 else
4742 *sy = wl_fixed_from_double(border->line.a.y) + 1;
4743 if (*sx < wl_fixed_from_double(border->line.a.x))
4744 *sx = wl_fixed_from_double(border->line.a.x) + 1;
4745 else if (*sx > wl_fixed_from_double(border->line.b.x))
4746 *sx = wl_fixed_from_double(border->line.b.x) - 1;
4747 break;
4748 }
Jonas Ådahld3414f22016-07-22 17:56:31 +08004749}
4750
4751static void
4752maybe_warp_confined_pointer(struct weston_pointer_constraint *constraint)
4753{
4754 wl_fixed_t x;
4755 wl_fixed_t y;
4756 wl_fixed_t sx;
4757 wl_fixed_t sy;
4758
4759 weston_view_from_global_fixed(constraint->view,
4760 constraint->pointer->x,
4761 constraint->pointer->y,
4762 &sx,
4763 &sy);
4764
4765 if (!is_within_constraint_region(constraint, sx, sy)) {
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004766 double xf = wl_fixed_to_double(sx);
4767 double yf = wl_fixed_to_double(sy);
4768 pixman_region32_t confine_region;
4769 struct wl_array borders;
4770 struct border *border;
4771 double closest_distance_2 = DBL_MAX;
4772 struct border *closest_border = NULL;
Jonas Ådahld3414f22016-07-22 17:56:31 +08004773
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004774 wl_array_init(&borders);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004775
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004776 pixman_region32_init(&confine_region);
4777 pixman_region32_intersect(&confine_region,
4778 &constraint->view->surface->input,
4779 &constraint->region);
4780 region_to_outline(&confine_region, &borders);
4781 pixman_region32_fini(&confine_region);
4782
4783 wl_array_for_each(border, &borders) {
4784 double distance_2;
4785
4786 distance_2 = point_to_border_distance_2(border, xf, yf);
4787 if (distance_2 < closest_distance_2) {
4788 closest_border = border;
4789 closest_distance_2 = distance_2;
4790 }
4791 }
4792 assert(closest_border);
4793
4794 warp_to_behind_border(closest_border, &sx, &sy);
4795
4796 wl_array_release(&borders);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004797
4798 weston_view_to_global_fixed(constraint->view, sx, sy, &x, &y);
4799 weston_pointer_move_to(constraint->pointer, x, y);
4800 }
4801}
4802
4803static void
4804confined_pointer_grab_pointer_motion(struct weston_pointer_grab *grab,
Alexandros Frantzis84b31f82017-11-24 18:01:46 +02004805 const struct timespec *time,
Jonas Ådahld3414f22016-07-22 17:56:31 +08004806 struct weston_pointer_motion_event *event)
4807{
4808 struct weston_pointer_constraint *constraint =
4809 container_of(grab, struct weston_pointer_constraint, grab);
4810 struct weston_pointer *pointer = grab->pointer;
4811 struct weston_surface *surface;
4812 wl_fixed_t x, y;
4813 wl_fixed_t old_sx = pointer->sx;
4814 wl_fixed_t old_sy = pointer->sy;
4815 pixman_region32_t confine_region;
4816
4817 assert(pointer->focus);
4818 assert(pointer->focus->surface == constraint->surface);
4819
4820 surface = pointer->focus->surface;
4821
4822 pixman_region32_init(&confine_region);
4823 pixman_region32_intersect(&confine_region,
4824 &surface->input,
4825 &constraint->region);
4826 weston_pointer_clamp_event_to_region(pointer, event,
4827 &confine_region, &x, &y);
4828 weston_pointer_move_to(pointer, x, y);
4829 pixman_region32_fini(&confine_region);
4830
4831 weston_view_from_global_fixed(pointer->focus, x, y,
4832 &pointer->sx, &pointer->sy);
4833
4834 if (old_sx != pointer->sx || old_sy != pointer->sy) {
Quentin Glidiccde13452016-08-12 10:41:32 +02004835 pointer_send_motion(pointer, time,
4836 pointer->sx, pointer->sy);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004837 }
4838
Quentin Glidiccde13452016-08-12 10:41:32 +02004839 pointer_send_relative_motion(pointer, time, event);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004840}
4841
4842static void
4843confined_pointer_grab_pointer_button(struct weston_pointer_grab *grab,
Alexandros Frantzis215bedc2017-11-16 18:20:55 +02004844 const struct timespec *time,
Jonas Ådahld3414f22016-07-22 17:56:31 +08004845 uint32_t button,
4846 uint32_t state_w)
4847{
4848 weston_pointer_send_button(grab->pointer, time, button, state_w);
4849}
4850
4851static void
4852confined_pointer_grab_pointer_axis(struct weston_pointer_grab *grab,
Alexandros Frantzis80321942017-11-16 18:20:56 +02004853 const struct timespec *time,
Jonas Ådahld3414f22016-07-22 17:56:31 +08004854 struct weston_pointer_axis_event *event)
4855{
4856 weston_pointer_send_axis(grab->pointer, time, event);
4857}
4858
4859static void
4860confined_pointer_grab_pointer_axis_source(struct weston_pointer_grab *grab,
4861 uint32_t source)
4862{
4863 weston_pointer_send_axis_source(grab->pointer, source);
4864}
4865
4866static void
4867confined_pointer_grab_pointer_frame(struct weston_pointer_grab *grab)
4868{
4869 weston_pointer_send_frame(grab->pointer);
4870}
4871
4872static void
4873confined_pointer_grab_pointer_cancel(struct weston_pointer_grab *grab)
4874{
4875 struct weston_pointer_constraint *constraint =
4876 container_of(grab, struct weston_pointer_constraint, grab);
4877
4878 disable_pointer_constraint(constraint);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004879}
4880
4881static const struct weston_pointer_grab_interface
4882 confined_pointer_grab_interface = {
4883 confined_pointer_grab_pointer_focus,
4884 confined_pointer_grab_pointer_motion,
4885 confined_pointer_grab_pointer_button,
4886 confined_pointer_grab_pointer_axis,
4887 confined_pointer_grab_pointer_axis_source,
4888 confined_pointer_grab_pointer_frame,
4889 confined_pointer_grab_pointer_cancel,
4890};
4891
4892static void
4893confined_pointer_destroy(struct wl_client *client,
4894 struct wl_resource *resource)
4895{
4896 wl_resource_destroy(resource);
4897}
4898
4899static void
4900confined_pointer_set_region(struct wl_client *client,
4901 struct wl_resource *resource,
4902 struct wl_resource *region_resource)
4903{
4904 struct weston_pointer_constraint *constraint =
4905 wl_resource_get_user_data(resource);
4906 struct weston_region *region = region_resource ?
4907 wl_resource_get_user_data(region_resource) : NULL;
4908
4909 if (!constraint)
4910 return;
4911
4912 if (region) {
4913 pixman_region32_copy(&constraint->region_pending,
4914 &region->region);
4915 } else {
4916 pixman_region32_fini(&constraint->region_pending);
4917 region_init_infinite(&constraint->region_pending);
4918 }
4919 constraint->region_is_pending = true;
4920}
4921
4922static const struct zwp_confined_pointer_v1_interface confined_pointer_interface = {
4923 confined_pointer_destroy,
4924 confined_pointer_set_region,
4925};
4926
4927static void
4928pointer_constraints_confine_pointer(struct wl_client *client,
4929 struct wl_resource *resource,
4930 uint32_t id,
4931 struct wl_resource *surface_resource,
4932 struct wl_resource *pointer_resource,
4933 struct wl_resource *region_resource,
4934 uint32_t lifetime)
4935{
4936 struct weston_surface *surface =
4937 wl_resource_get_user_data(surface_resource);
4938 struct weston_pointer *pointer = wl_resource_get_user_data(pointer_resource);
4939 struct weston_region *region = region_resource ?
4940 wl_resource_get_user_data(region_resource) : NULL;
4941
4942 init_pointer_constraint(resource, id, surface, pointer, region, lifetime,
4943 &zwp_confined_pointer_v1_interface,
4944 &confined_pointer_interface,
4945 &confined_pointer_grab_interface);
4946}
4947
4948static const struct zwp_pointer_constraints_v1_interface pointer_constraints_interface = {
4949 pointer_constraints_destroy,
4950 pointer_constraints_lock_pointer,
4951 pointer_constraints_confine_pointer,
4952};
4953
4954static void
4955bind_pointer_constraints(struct wl_client *client, void *data,
4956 uint32_t version, uint32_t id)
4957{
4958 struct wl_resource *resource;
4959
4960 resource = wl_resource_create(client,
4961 &zwp_pointer_constraints_v1_interface,
4962 1, id);
4963
4964 wl_resource_set_implementation(resource, &pointer_constraints_interface,
4965 NULL, NULL);
4966}
4967
Alexandros Frantzis538749d2018-02-16 18:44:16 +02004968static void
Alexandros Frantzis2b442482018-02-20 14:05:50 +02004969input_timestamps_destroy(struct wl_client *client,
4970 struct wl_resource *resource)
4971{
4972 wl_resource_destroy(resource);
4973}
4974
4975static const struct zwp_input_timestamps_v1_interface
4976 input_timestamps_interface = {
4977 input_timestamps_destroy,
4978};
4979
4980static void
Alexandros Frantzis538749d2018-02-16 18:44:16 +02004981input_timestamps_manager_destroy(struct wl_client *client,
4982 struct wl_resource *resource)
4983{
4984 wl_resource_destroy(resource);
4985}
4986
4987static void
4988input_timestamps_manager_get_keyboard_timestamps(struct wl_client *client,
4989 struct wl_resource *resource,
4990 uint32_t id,
4991 struct wl_resource *keyboard_resource)
4992{
Alexandros Frantzis2b442482018-02-20 14:05:50 +02004993 struct weston_keyboard *keyboard =
4994 wl_resource_get_user_data(keyboard_resource);
4995 struct wl_resource *input_ts;
4996
4997 input_ts = wl_resource_create(client,
4998 &zwp_input_timestamps_v1_interface,
4999 1, id);
5000 if (!input_ts) {
5001 wl_client_post_no_memory(client);
5002 return;
5003 }
5004
5005 if (keyboard) {
5006 wl_list_insert(&keyboard->timestamps_list,
5007 wl_resource_get_link(input_ts));
5008 } else {
5009 wl_list_init(wl_resource_get_link(input_ts));
5010 }
5011
5012 wl_resource_set_implementation(input_ts,
5013 &input_timestamps_interface,
5014 keyboard_resource,
5015 unbind_resource);
Alexandros Frantzis538749d2018-02-16 18:44:16 +02005016}
5017
5018static void
5019input_timestamps_manager_get_pointer_timestamps(struct wl_client *client,
5020 struct wl_resource *resource,
5021 uint32_t id,
5022 struct wl_resource *pointer_resource)
5023{
Alexandros Frantzisdb907b72018-02-20 14:06:26 +02005024 struct weston_pointer *pointer =
5025 wl_resource_get_user_data(pointer_resource);
5026 struct wl_resource *input_ts;
5027
5028 input_ts = wl_resource_create(client,
5029 &zwp_input_timestamps_v1_interface,
5030 1, id);
5031 if (!input_ts) {
5032 wl_client_post_no_memory(client);
5033 return;
5034 }
5035
5036 if (pointer) {
5037 wl_list_insert(&pointer->timestamps_list,
5038 wl_resource_get_link(input_ts));
5039 } else {
5040 wl_list_init(wl_resource_get_link(input_ts));
5041 }
5042
5043 wl_resource_set_implementation(input_ts,
5044 &input_timestamps_interface,
5045 pointer_resource,
5046 unbind_resource);
Alexandros Frantzis538749d2018-02-16 18:44:16 +02005047}
5048
5049static void
5050input_timestamps_manager_get_touch_timestamps(struct wl_client *client,
5051 struct wl_resource *resource,
5052 uint32_t id,
5053 struct wl_resource *touch_resource)
5054{
Alexandros Frantzisd7157842018-02-20 14:07:03 +02005055 struct weston_touch *touch = wl_resource_get_user_data(touch_resource);
5056 struct wl_resource *input_ts;
5057
5058 input_ts = wl_resource_create(client,
5059 &zwp_input_timestamps_v1_interface,
5060 1, id);
5061 if (!input_ts) {
5062 wl_client_post_no_memory(client);
5063 return;
5064 }
5065
5066 if (touch) {
5067 wl_list_insert(&touch->timestamps_list,
5068 wl_resource_get_link(input_ts));
5069 } else {
5070 wl_list_init(wl_resource_get_link(input_ts));
5071 }
5072
5073 wl_resource_set_implementation(input_ts,
5074 &input_timestamps_interface,
5075 touch_resource,
5076 unbind_resource);
Alexandros Frantzis538749d2018-02-16 18:44:16 +02005077}
5078
5079static const struct zwp_input_timestamps_manager_v1_interface
5080 input_timestamps_manager_interface = {
5081 input_timestamps_manager_destroy,
5082 input_timestamps_manager_get_keyboard_timestamps,
5083 input_timestamps_manager_get_pointer_timestamps,
5084 input_timestamps_manager_get_touch_timestamps,
5085};
5086
5087static void
5088bind_input_timestamps_manager(struct wl_client *client, void *data,
5089 uint32_t version, uint32_t id)
5090{
5091 struct wl_resource *resource =
5092 wl_resource_create(client,
5093 &zwp_input_timestamps_manager_v1_interface,
5094 1, id);
5095
5096 if (resource == NULL) {
5097 wl_client_post_no_memory(client);
5098 return;
5099 }
5100
5101 wl_resource_set_implementation(resource,
5102 &input_timestamps_manager_interface,
5103 NULL, NULL);
5104}
5105
Jonas Ådahl30d61d82014-10-22 21:21:17 +02005106int
5107weston_input_init(struct weston_compositor *compositor)
5108{
5109 if (!wl_global_create(compositor->wl_display,
5110 &zwp_relative_pointer_manager_v1_interface, 1,
5111 compositor, bind_relative_pointer_manager))
5112 return -1;
5113
Jonas Ådahld3414f22016-07-22 17:56:31 +08005114 if (!wl_global_create(compositor->wl_display,
5115 &zwp_pointer_constraints_v1_interface, 1,
5116 NULL, bind_pointer_constraints))
5117 return -1;
5118
Alexandros Frantzis538749d2018-02-16 18:44:16 +02005119 if (!wl_global_create(compositor->wl_display,
5120 &zwp_input_timestamps_manager_v1_interface, 1,
5121 NULL, bind_input_timestamps_manager))
5122 return -1;
5123
Jonas Ådahl30d61d82014-10-22 21:21:17 +02005124 return 0;
5125}