blob: a1085463ae092fc81caaf9fc59f95b5316590049 [file] [log] [blame]
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001/*
2 * Copyright © 2013 Intel Corporation
3 *
Bryce Harringtona0bbfea2015-06-11 15:35:43 -07004 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
Kristian Høgsberg2158a882013-04-18 15:07:39 -040011 *
Bryce Harringtona0bbfea2015-06-11 15:35:43 -070012 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial
14 * portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
Kristian Høgsberg2158a882013-04-18 15:07:39 -040024 */
25
Daniel Stone8e7a8bd2013-08-15 01:10:24 +010026#include "config.h"
27
Jonas Ådahld3414f22016-07-22 17:56:31 +080028#include <stdbool.h>
Kristian Høgsberg2158a882013-04-18 15:07:39 -040029#include <stdlib.h>
30#include <stdint.h>
31#include <string.h>
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040032#include <sys/mman.h>
33#include <assert.h>
34#include <unistd.h>
Jonas Ådahld0be2bb2015-04-30 17:56:37 +080035#include <values.h>
Matt Roper01a92732013-06-24 16:52:44 +010036#include <fcntl.h>
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +020037#include <limits.h>
Kristian Høgsberg2158a882013-04-18 15:07:39 -040038
Jon Cruz35b2eaa2015-06-15 15:37:08 -070039#include "shared/helpers.h"
Jon Cruz4678bab2015-06-15 15:37:07 -070040#include "shared/os-compatibility.h"
Alexandros Frantzis84b31f82017-11-24 18:01:46 +020041#include "shared/timespec-util.h"
Kristian Høgsberg2158a882013-04-18 15:07:39 -040042#include "compositor.h"
Daniel Stone7dbb0e12016-11-24 15:30:41 +000043#include "relative-pointer-unstable-v1-server-protocol.h"
44#include "pointer-constraints-unstable-v1-server-protocol.h"
Jonas Ådahld3414f22016-07-22 17:56:31 +080045
46enum pointer_constraint_type {
47 POINTER_CONSTRAINT_TYPE_LOCK,
48 POINTER_CONSTRAINT_TYPE_CONFINE,
49};
50
Jonas Ådahld0be2bb2015-04-30 17:56:37 +080051enum motion_direction {
52 MOTION_DIRECTION_POSITIVE_X = 1 << 0,
53 MOTION_DIRECTION_NEGATIVE_X = 1 << 1,
54 MOTION_DIRECTION_POSITIVE_Y = 1 << 2,
55 MOTION_DIRECTION_NEGATIVE_Y = 1 << 3,
56};
57
58struct vec2d {
59 double x, y;
60};
61
62struct line {
63 struct vec2d a;
64 struct vec2d b;
65};
66
67struct border {
68 struct line line;
69 enum motion_direction blocking_dir;
70};
71
Jonas Ådahld3414f22016-07-22 17:56:31 +080072static void
73maybe_warp_confined_pointer(struct weston_pointer_constraint *constraint);
Kristian Høgsberg2158a882013-04-18 15:07:39 -040074
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040075static void
76empty_region(pixman_region32_t *region)
77{
78 pixman_region32_fini(region);
79 pixman_region32_init(region);
80}
81
Jonas Ådahld3414f22016-07-22 17:56:31 +080082static void
83region_init_infinite(pixman_region32_t *region)
84{
85 pixman_region32_init_rect(region, INT32_MIN, INT32_MIN,
86 UINT32_MAX, UINT32_MAX);
87}
88
Jonas Ådahl2cbf2932015-07-22 12:05:38 +080089static struct weston_pointer_client *
90weston_pointer_client_create(struct wl_client *client)
91{
92 struct weston_pointer_client *pointer_client;
93
94 pointer_client = zalloc(sizeof *pointer_client);
95 if (!pointer_client)
96 return NULL;
97
98 pointer_client->client = client;
99 wl_list_init(&pointer_client->pointer_resources);
Jonas Ådahl30d61d82014-10-22 21:21:17 +0200100 wl_list_init(&pointer_client->relative_pointer_resources);
Jonas Ådahl2cbf2932015-07-22 12:05:38 +0800101
102 return pointer_client;
103}
104
105static void
106weston_pointer_client_destroy(struct weston_pointer_client *pointer_client)
107{
108 free(pointer_client);
109}
110
111static bool
112weston_pointer_client_is_empty(struct weston_pointer_client *pointer_client)
113{
Jonas Ådahl30d61d82014-10-22 21:21:17 +0200114 return (wl_list_empty(&pointer_client->pointer_resources) &&
115 wl_list_empty(&pointer_client->relative_pointer_resources));
Jonas Ådahl2cbf2932015-07-22 12:05:38 +0800116}
117
118static struct weston_pointer_client *
119weston_pointer_get_pointer_client(struct weston_pointer *pointer,
120 struct wl_client *client)
121{
122 struct weston_pointer_client *pointer_client;
123
124 wl_list_for_each(pointer_client, &pointer->pointer_clients, link) {
125 if (pointer_client->client == client)
126 return pointer_client;
127 }
128
129 return NULL;
130}
131
132static struct weston_pointer_client *
133weston_pointer_ensure_pointer_client(struct weston_pointer *pointer,
134 struct wl_client *client)
135{
136 struct weston_pointer_client *pointer_client;
137
138 pointer_client = weston_pointer_get_pointer_client(pointer, client);
139 if (pointer_client)
140 return pointer_client;
141
142 pointer_client = weston_pointer_client_create(client);
143 wl_list_insert(&pointer->pointer_clients, &pointer_client->link);
144
145 if (pointer->focus &&
146 pointer->focus->surface->resource &&
147 wl_resource_get_client(pointer->focus->surface->resource) == client) {
148 pointer->focus_client = pointer_client;
149 }
150
151 return pointer_client;
152}
153
154static void
155weston_pointer_cleanup_pointer_client(struct weston_pointer *pointer,
156 struct weston_pointer_client *pointer_client)
157{
158 if (weston_pointer_client_is_empty(pointer_client)) {
159 if (pointer->focus_client == pointer_client)
160 pointer->focus_client = NULL;
161 wl_list_remove(&pointer_client->link);
162 weston_pointer_client_destroy(pointer_client);
163 }
164}
165
166static void
167unbind_pointer_client_resource(struct wl_resource *resource)
168{
169 struct weston_pointer *pointer = wl_resource_get_user_data(resource);
170 struct wl_client *client = wl_resource_get_client(resource);
171 struct weston_pointer_client *pointer_client;
172
173 pointer_client = weston_pointer_get_pointer_client(pointer, client);
174 assert(pointer_client);
175
176 wl_list_remove(wl_resource_get_link(resource));
177 weston_pointer_cleanup_pointer_client(pointer, pointer_client);
178}
179
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400180static void unbind_resource(struct wl_resource *resource)
181{
Jason Ekstrand44a38632013-06-14 10:08:00 -0500182 wl_list_remove(wl_resource_get_link(resource));
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400183}
184
Jonas Ådahl3042ffe2013-10-17 23:04:08 +0200185WL_EXPORT void
Jonas Ådahl30d61d82014-10-22 21:21:17 +0200186weston_pointer_motion_to_abs(struct weston_pointer *pointer,
187 struct weston_pointer_motion_event *event,
188 wl_fixed_t *x, wl_fixed_t *y)
189{
190 if (event->mask & WESTON_POINTER_MOTION_ABS) {
191 *x = wl_fixed_from_double(event->x);
192 *y = wl_fixed_from_double(event->y);
193 } else if (event->mask & WESTON_POINTER_MOTION_REL) {
194 *x = pointer->x + wl_fixed_from_double(event->dx);
195 *y = pointer->y + wl_fixed_from_double(event->dy);
196 } else {
197 assert(!"invalid motion event");
198 *x = *y = 0;
199 }
200}
201
202static bool
203weston_pointer_motion_to_rel(struct weston_pointer *pointer,
204 struct weston_pointer_motion_event *event,
205 double *dx, double *dy,
206 double *dx_unaccel, double *dy_unaccel)
207{
208 if (event->mask & WESTON_POINTER_MOTION_REL &&
209 event->mask & WESTON_POINTER_MOTION_REL_UNACCEL) {
210 *dx = event->dx;
211 *dy = event->dy;
212 *dx_unaccel = event->dx_unaccel;
213 *dy_unaccel = event->dy_unaccel;
214 return true;
215 } else if (event->mask & WESTON_POINTER_MOTION_REL) {
216 *dx_unaccel = *dx = event->dx;
217 *dy_unaccel = *dy = event->dy;
218 return true;
219 } else if (event->mask & WESTON_POINTER_MOTION_REL_UNACCEL) {
220 *dx_unaccel = *dx = event->dx_unaccel;
221 *dy_unaccel = *dy = event->dy_unaccel;
222 return true;
223 } else {
224 return false;
225 }
226}
227
228WL_EXPORT void
Kristian Høgsberga71e8b22013-05-06 21:51:21 -0400229weston_seat_repick(struct weston_seat *seat)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400230{
Derek Foreman1281a362015-07-31 16:55:32 -0500231 const struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400232
Derek Foreman1b786ee2015-06-03 15:53:23 -0500233 if (!pointer)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400234 return;
235
Derek Foreman1b786ee2015-06-03 15:53:23 -0500236 pointer->grab->interface->focus(pointer->grab);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400237}
238
239static void
240weston_compositor_idle_inhibit(struct weston_compositor *compositor)
241{
242 weston_compositor_wake(compositor);
243 compositor->idle_inhibit++;
244}
245
246static void
247weston_compositor_idle_release(struct weston_compositor *compositor)
248{
249 compositor->idle_inhibit--;
250 weston_compositor_wake(compositor);
251}
252
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400253static void
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100254pointer_focus_view_destroyed(struct wl_listener *listener, void *data)
255{
256 struct weston_pointer *pointer =
257 container_of(listener, struct weston_pointer,
258 focus_view_listener);
259
Derek Foremanf9318d12015-05-11 15:40:11 -0500260 weston_pointer_clear_focus(pointer);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100261}
262
263static void
264pointer_focus_resource_destroyed(struct wl_listener *listener, void *data)
265{
266 struct weston_pointer *pointer =
267 container_of(listener, struct weston_pointer,
268 focus_resource_listener);
269
Derek Foremanf9318d12015-05-11 15:40:11 -0500270 weston_pointer_clear_focus(pointer);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100271}
272
273static void
274keyboard_focus_resource_destroyed(struct wl_listener *listener, void *data)
275{
276 struct weston_keyboard *keyboard =
277 container_of(listener, struct weston_keyboard,
278 focus_resource_listener);
279
280 weston_keyboard_set_focus(keyboard, NULL);
281}
282
283static void
284touch_focus_view_destroyed(struct wl_listener *listener, void *data)
285{
286 struct weston_touch *touch =
287 container_of(listener, struct weston_touch,
288 focus_view_listener);
289
Derek Foreman4c93c082015-04-30 16:45:41 -0500290 weston_touch_set_focus(touch, NULL);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100291}
292
293static void
294touch_focus_resource_destroyed(struct wl_listener *listener, void *data)
295{
296 struct weston_touch *touch =
297 container_of(listener, struct weston_touch,
298 focus_resource_listener);
299
Derek Foreman4c93c082015-04-30 16:45:41 -0500300 weston_touch_set_focus(touch, NULL);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100301}
302
303static void
Neil Roberts96d790e2013-09-19 17:32:00 +0100304move_resources(struct wl_list *destination, struct wl_list *source)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400305{
Neil Roberts96d790e2013-09-19 17:32:00 +0100306 wl_list_insert_list(destination, source);
307 wl_list_init(source);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400308}
309
310static void
Neil Roberts96d790e2013-09-19 17:32:00 +0100311move_resources_for_client(struct wl_list *destination,
312 struct wl_list *source,
313 struct wl_client *client)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400314{
Neil Roberts96d790e2013-09-19 17:32:00 +0100315 struct wl_resource *resource, *tmp;
316 wl_resource_for_each_safe(resource, tmp, source) {
317 if (wl_resource_get_client(resource) == client) {
318 wl_list_remove(wl_resource_get_link(resource));
319 wl_list_insert(destination,
320 wl_resource_get_link(resource));
321 }
322 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400323}
324
325static void
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700326default_grab_pointer_focus(struct weston_pointer_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400327{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400328 struct weston_pointer *pointer = grab->pointer;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500329 struct weston_view *view;
Kristian Høgsberg6848c252013-05-08 22:02:59 -0400330 wl_fixed_t sx, sy;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400331
332 if (pointer->button_count > 0)
333 return;
334
Jason Ekstranda7af7042013-10-12 22:38:11 -0500335 view = weston_compositor_pick_view(pointer->seat->compositor,
336 pointer->x, pointer->y,
337 &sx, &sy);
Kristian Høgsberg6848c252013-05-08 22:02:59 -0400338
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -0800339 if (pointer->focus != view || pointer->sx != sx || pointer->sy != sy)
Jason Ekstranda7af7042013-10-12 22:38:11 -0500340 weston_pointer_set_focus(pointer, view, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400341}
342
343static void
Quentin Glidiccde13452016-08-12 10:41:32 +0200344pointer_send_relative_motion(struct weston_pointer *pointer,
Alexandros Frantzis84b31f82017-11-24 18:01:46 +0200345 const struct timespec *time,
Quentin Glidiccde13452016-08-12 10:41:32 +0200346 struct weston_pointer_motion_event *event)
Jonas Ådahl30d61d82014-10-22 21:21:17 +0200347{
348 uint64_t time_usec;
349 double dx, dy, dx_unaccel, dy_unaccel;
350 wl_fixed_t dxf, dyf, dxf_unaccel, dyf_unaccel;
351 struct wl_list *resource_list;
352 struct wl_resource *resource;
353
354 if (!pointer->focus_client)
355 return;
356
357 if (!weston_pointer_motion_to_rel(pointer, event,
358 &dx, &dy,
359 &dx_unaccel, &dy_unaccel))
360 return;
361
362 resource_list = &pointer->focus_client->relative_pointer_resources;
Alexandros Frantzis84b31f82017-11-24 18:01:46 +0200363 time_usec = timespec_to_usec(&event->time);
Jonas Ådahl30d61d82014-10-22 21:21:17 +0200364 if (time_usec == 0)
Alexandros Frantzis84b31f82017-11-24 18:01:46 +0200365 time_usec = timespec_to_usec(time);
Jonas Ådahl30d61d82014-10-22 21:21:17 +0200366
367 dxf = wl_fixed_from_double(dx);
368 dyf = wl_fixed_from_double(dy);
369 dxf_unaccel = wl_fixed_from_double(dx_unaccel);
370 dyf_unaccel = wl_fixed_from_double(dy_unaccel);
371
372 wl_resource_for_each(resource, resource_list) {
373 zwp_relative_pointer_v1_send_relative_motion(
374 resource,
375 (uint32_t) (time_usec >> 32),
376 (uint32_t) time_usec,
377 dxf, dyf,
378 dxf_unaccel, dyf_unaccel);
379 }
380}
381
382static void
Alexandros Frantzis84b31f82017-11-24 18:01:46 +0200383pointer_send_motion(struct weston_pointer *pointer,
384 const struct timespec *time,
Quentin Glidiccde13452016-08-12 10:41:32 +0200385 wl_fixed_t sx, wl_fixed_t sy)
Jonas Ådahlf44942e2016-07-22 17:54:55 +0800386{
387 struct wl_list *resource_list;
388 struct wl_resource *resource;
Alexandros Frantzis84b31f82017-11-24 18:01:46 +0200389 uint32_t msecs;
Jonas Ådahlf44942e2016-07-22 17:54:55 +0800390
391 if (!pointer->focus_client)
392 return;
393
394 resource_list = &pointer->focus_client->pointer_resources;
Alexandros Frantzis84b31f82017-11-24 18:01:46 +0200395 msecs = timespec_to_msec(time);
Jonas Ådahlf44942e2016-07-22 17:54:55 +0800396 wl_resource_for_each(resource, resource_list)
Alexandros Frantzis84b31f82017-11-24 18:01:46 +0200397 wl_pointer_send_motion(resource, msecs, sx, sy);
Jonas Ådahlf44942e2016-07-22 17:54:55 +0800398}
399
Quentin Glidiccde13452016-08-12 10:41:32 +0200400WL_EXPORT void
Alexandros Frantzis84b31f82017-11-24 18:01:46 +0200401weston_pointer_send_motion(struct weston_pointer *pointer,
402 const struct timespec *time,
Quentin Glidiccde13452016-08-12 10:41:32 +0200403 struct weston_pointer_motion_event *event)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400404{
Jonas Ådahld2510102014-10-05 21:39:14 +0200405 wl_fixed_t x, y;
Jonas Ådahl8283c342015-04-24 15:26:17 +0800406 wl_fixed_t old_sx = pointer->sx;
407 wl_fixed_t old_sy = pointer->sy;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400408
Jonas Ådahld2510102014-10-05 21:39:14 +0200409 if (pointer->focus) {
410 weston_pointer_motion_to_abs(pointer, event, &x, &y);
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -0800411 weston_view_from_global_fixed(pointer->focus, x, y,
412 &pointer->sx, &pointer->sy);
Jonas Ådahld2510102014-10-05 21:39:14 +0200413 }
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -0800414
Jonas Ådahld2510102014-10-05 21:39:14 +0200415 weston_pointer_move(pointer, event);
Giulio Camuffo1959ab82013-11-14 23:42:52 +0100416
Jonas Ådahlf44942e2016-07-22 17:54:55 +0800417 if (old_sx != pointer->sx || old_sy != pointer->sy) {
Quentin Glidiccde13452016-08-12 10:41:32 +0200418 pointer_send_motion(pointer, time,
419 pointer->sx, pointer->sy);
Kristian Høgsbergbe6403e2013-05-08 21:03:21 -0400420 }
Jonas Ådahl30d61d82014-10-22 21:21:17 +0200421
Quentin Glidiccde13452016-08-12 10:41:32 +0200422 pointer_send_relative_motion(pointer, time, event);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400423}
424
425static void
Alexandros Frantzis84b31f82017-11-24 18:01:46 +0200426default_grab_pointer_motion(struct weston_pointer_grab *grab,
427 const struct timespec *time,
Quentin Glidiccde13452016-08-12 10:41:32 +0200428 struct weston_pointer_motion_event *event)
429{
430 weston_pointer_send_motion(grab->pointer, time, event);
431}
432
433/** Check if the pointer has focused resources.
434 *
435 * \param pointer The pointer to check for focused resources.
436 * \return Whether or not this pointer has focused resources
437 */
438WL_EXPORT bool
439weston_pointer_has_focus_resource(struct weston_pointer *pointer)
440{
441 if (!pointer->focus_client)
442 return false;
443
444 if (wl_list_empty(&pointer->focus_client->pointer_resources))
445 return false;
446
447 return true;
448}
449
450/** Send wl_pointer.button events to focused resources.
451 *
452 * \param pointer The pointer where the button events originates from.
453 * \param time The timestamp of the event
454 * \param button The button value of the event
455 * \param value The state enum value of the event
456 *
457 * For every resource that is currently in focus, send a wl_pointer.button event
458 * with the passed parameters. The focused resources are the wl_pointer
459 * resources of the client which currently has the surface with pointer focus.
460 */
461WL_EXPORT void
Jonas Ådahlc02ac112016-07-22 17:55:43 +0800462weston_pointer_send_button(struct weston_pointer *pointer,
Alexandros Frantzis215bedc2017-11-16 18:20:55 +0200463 const struct timespec *time, uint32_t button,
Quentin Glidiccde13452016-08-12 10:41:32 +0200464 enum wl_pointer_button_state state)
Jonas Ådahlc02ac112016-07-22 17:55:43 +0800465{
466 struct wl_display *display = pointer->seat->compositor->wl_display;
467 struct wl_list *resource_list;
468 struct wl_resource *resource;
469 uint32_t serial;
Alexandros Frantzis215bedc2017-11-16 18:20:55 +0200470 uint32_t msecs;
Jonas Ådahlc02ac112016-07-22 17:55:43 +0800471
Quentin Glidiccde13452016-08-12 10:41:32 +0200472 if (!weston_pointer_has_focus_resource(pointer))
Jonas Ådahlc02ac112016-07-22 17:55:43 +0800473 return;
474
475 resource_list = &pointer->focus_client->pointer_resources;
Quentin Glidiccde13452016-08-12 10:41:32 +0200476 serial = wl_display_next_serial(display);
Alexandros Frantzis215bedc2017-11-16 18:20:55 +0200477 msecs = timespec_to_msec(time);
Quentin Glidiccde13452016-08-12 10:41:32 +0200478 wl_resource_for_each(resource, resource_list)
Alexandros Frantzis215bedc2017-11-16 18:20:55 +0200479 wl_pointer_send_button(resource, serial, msecs, button, state);
Jonas Ådahlc02ac112016-07-22 17:55:43 +0800480}
481
482static void
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700483default_grab_pointer_button(struct weston_pointer_grab *grab,
Alexandros Frantzis215bedc2017-11-16 18:20:55 +0200484 const struct timespec *time, uint32_t button,
Quentin Glidiccde13452016-08-12 10:41:32 +0200485 enum wl_pointer_button_state state)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400486{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400487 struct weston_pointer *pointer = grab->pointer;
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400488 struct weston_compositor *compositor = pointer->seat->compositor;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500489 struct weston_view *view;
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400490 wl_fixed_t sx, sy;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400491
Quentin Glidiccde13452016-08-12 10:41:32 +0200492 weston_pointer_send_button(pointer, time, button, state);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400493
494 if (pointer->button_count == 0 &&
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400495 state == WL_POINTER_BUTTON_STATE_RELEASED) {
Jason Ekstranda7af7042013-10-12 22:38:11 -0500496 view = weston_compositor_pick_view(compositor,
497 pointer->x, pointer->y,
498 &sx, &sy);
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400499
Jason Ekstranda7af7042013-10-12 22:38:11 -0500500 weston_pointer_set_focus(pointer, view, sx, sy);
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400501 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400502}
503
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200504/** Send wl_pointer.axis events to focused resources.
505 *
506 * \param pointer The pointer where the axis events originates from.
507 * \param time The timestamp of the event
508 * \param axis The axis enum value of the event
509 * \param value The axis value of the event
510 *
511 * For every resource that is currently in focus, send a wl_pointer.axis event
512 * with the passed parameters. The focused resources are the wl_pointer
513 * resources of the client which currently has the surface with pointer focus.
514 */
515WL_EXPORT void
516weston_pointer_send_axis(struct weston_pointer *pointer,
Alexandros Frantzis80321942017-11-16 18:20:56 +0200517 const struct timespec *time,
Peter Hutterer89b6a492016-01-18 15:58:17 +1000518 struct weston_pointer_axis_event *event)
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200519{
520 struct wl_resource *resource;
521 struct wl_list *resource_list;
Alexandros Frantzis80321942017-11-16 18:20:56 +0200522 uint32_t msecs;
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200523
Quentin Glidiccde13452016-08-12 10:41:32 +0200524 if (!weston_pointer_has_focus_resource(pointer))
Jonas Ådahl2cbf2932015-07-22 12:05:38 +0800525 return;
526
527 resource_list = &pointer->focus_client->pointer_resources;
Alexandros Frantzis80321942017-11-16 18:20:56 +0200528 msecs = timespec_to_msec(time);
Peter Hutterer87743e92016-01-18 16:38:22 +1000529 wl_resource_for_each(resource, resource_list) {
530 if (event->has_discrete &&
531 wl_resource_get_version(resource) >=
532 WL_POINTER_AXIS_DISCRETE_SINCE_VERSION)
533 wl_pointer_send_axis_discrete(resource, event->axis,
534 event->discrete);
535
536 if (event->value)
Alexandros Frantzis80321942017-11-16 18:20:56 +0200537 wl_pointer_send_axis(resource, msecs,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +0200538 event->axis,
539 wl_fixed_from_double(event->value));
Peter Hutterer87743e92016-01-18 16:38:22 +1000540 else if (wl_resource_get_version(resource) >=
541 WL_POINTER_AXIS_STOP_SINCE_VERSION)
Alexandros Frantzis80321942017-11-16 18:20:56 +0200542 wl_pointer_send_axis_stop(resource, msecs,
Peter Hutterer87743e92016-01-18 16:38:22 +1000543 event->axis);
544 }
545}
546
Quentin Glidiccde13452016-08-12 10:41:32 +0200547/** Send wl_pointer.axis_source events to focused resources.
548 *
549 * \param pointer The pointer where the axis_source events originates from.
550 * \param source The axis_source enum value of the event
551 *
552 * For every resource that is currently in focus, send a wl_pointer.axis_source
553 * event with the passed parameter. The focused resources are the wl_pointer
554 * resources of the client which currently has the surface with pointer focus.
555 */
Peter Hutterer87743e92016-01-18 16:38:22 +1000556WL_EXPORT void
Quentin Glidiccde13452016-08-12 10:41:32 +0200557weston_pointer_send_axis_source(struct weston_pointer *pointer,
558 enum wl_pointer_axis_source source)
Peter Hutterer87743e92016-01-18 16:38:22 +1000559{
560 struct wl_resource *resource;
561 struct wl_list *resource_list;
562
Quentin Glidiccde13452016-08-12 10:41:32 +0200563 if (!weston_pointer_has_focus_resource(pointer))
Jonas Ådahled6014a2016-04-21 10:21:48 +0800564 return;
565
Peter Hutterer87743e92016-01-18 16:38:22 +1000566 resource_list = &pointer->focus_client->pointer_resources;
567 wl_resource_for_each(resource, resource_list) {
568 if (wl_resource_get_version(resource) >=
569 WL_POINTER_AXIS_SOURCE_SINCE_VERSION) {
570 wl_pointer_send_axis_source(resource, source);
571 }
572 }
573}
574
575static void
576pointer_send_frame(struct wl_resource *resource)
577{
578 if (wl_resource_get_version(resource) >=
579 WL_POINTER_FRAME_SINCE_VERSION) {
580 wl_pointer_send_frame(resource);
581 }
582}
583
Quentin Glidiccde13452016-08-12 10:41:32 +0200584/** Send wl_pointer.frame events to focused resources.
585 *
586 * \param pointer The pointer where the frame events originates from.
587 *
588 * For every resource that is currently in focus, send a wl_pointer.frame event.
589 * The focused resources are the wl_pointer resources of the client which
590 * currently has the surface with pointer focus.
591 */
Peter Hutterer87743e92016-01-18 16:38:22 +1000592WL_EXPORT void
593weston_pointer_send_frame(struct weston_pointer *pointer)
594{
595 struct wl_resource *resource;
596 struct wl_list *resource_list;
597
Quentin Glidiccde13452016-08-12 10:41:32 +0200598 if (!weston_pointer_has_focus_resource(pointer))
Derek Foreman8efa31b2016-01-29 10:29:46 -0600599 return;
600
Peter Hutterer87743e92016-01-18 16:38:22 +1000601 resource_list = &pointer->focus_client->pointer_resources;
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200602 wl_resource_for_each(resource, resource_list)
Peter Hutterer87743e92016-01-18 16:38:22 +1000603 pointer_send_frame(resource);
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200604}
605
606static void
607default_grab_pointer_axis(struct weston_pointer_grab *grab,
Alexandros Frantzis80321942017-11-16 18:20:56 +0200608 const struct timespec *time,
Peter Hutterer89b6a492016-01-18 15:58:17 +1000609 struct weston_pointer_axis_event *event)
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200610{
Peter Hutterer89b6a492016-01-18 15:58:17 +1000611 weston_pointer_send_axis(grab->pointer, time, event);
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200612}
613
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200614static void
Peter Hutterer87743e92016-01-18 16:38:22 +1000615default_grab_pointer_axis_source(struct weston_pointer_grab *grab,
Quentin Glidiccde13452016-08-12 10:41:32 +0200616 enum wl_pointer_axis_source source)
Peter Hutterer87743e92016-01-18 16:38:22 +1000617{
618 weston_pointer_send_axis_source(grab->pointer, source);
619}
620
621static void
622default_grab_pointer_frame(struct weston_pointer_grab *grab)
623{
624 weston_pointer_send_frame(grab->pointer);
625}
626
627static void
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200628default_grab_pointer_cancel(struct weston_pointer_grab *grab)
629{
630}
631
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400632static const struct weston_pointer_grab_interface
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400633 default_pointer_grab_interface = {
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700634 default_grab_pointer_focus,
635 default_grab_pointer_motion,
636 default_grab_pointer_button,
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200637 default_grab_pointer_axis,
Peter Hutterer87743e92016-01-18 16:38:22 +1000638 default_grab_pointer_axis_source,
639 default_grab_pointer_frame,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200640 default_grab_pointer_cancel,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400641};
642
Quentin Glidiccde13452016-08-12 10:41:32 +0200643/** Check if the touch has focused resources.
644 *
645 * \param touch The touch to check for focused resources.
646 * \return Whether or not this touch has focused resources
647 */
648WL_EXPORT bool
649weston_touch_has_focus_resource(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400650{
Quentin Glidiccde13452016-08-12 10:41:32 +0200651 if (!touch->focus)
652 return false;
653
654 if (wl_list_empty(&touch->focus_resource_list))
655 return false;
656
657 return true;
658}
659
660/** Send wl_touch.down events to focused resources.
661 *
662 * \param touch The touch where the down events originates from.
663 * \param time The timestamp of the event
664 * \param touch_id The touch_id value of the event
665 * \param x The x value of the event
666 * \param y The y value of the event
667 *
668 * For every resource that is currently in focus, send a wl_touch.down event
669 * with the passed parameters. The focused resources are the wl_touch
670 * resources of the client which currently has the surface with touch focus.
671 */
672WL_EXPORT void
673weston_touch_send_down(struct weston_touch *touch, uint32_t time,
674 int touch_id, wl_fixed_t x, wl_fixed_t y)
675{
Rob Bradford880ebc72013-07-22 17:31:38 +0100676 struct wl_display *display = touch->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400677 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +0100678 struct wl_resource *resource;
679 struct wl_list *resource_list;
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300680 wl_fixed_t sx, sy;
681
Quentin Glidiccde13452016-08-12 10:41:32 +0200682 if (!weston_touch_has_focus_resource(touch))
Bryce Harrington2c40d1d2016-02-02 10:18:48 -0800683 return;
684
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300685 weston_view_from_global_fixed(touch->focus, x, y, &sx, &sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400686
Neil Roberts96d790e2013-09-19 17:32:00 +0100687 resource_list = &touch->focus_resource_list;
Quentin Glidiccde13452016-08-12 10:41:32 +0200688 serial = wl_display_next_serial(display);
689 wl_resource_for_each(resource, resource_list)
690 wl_touch_send_down(resource, serial, time,
691 touch->focus->surface->resource,
692 touch_id, sx, sy);
693}
Neil Roberts96d790e2013-09-19 17:32:00 +0100694
Quentin Glidiccde13452016-08-12 10:41:32 +0200695static void
696default_grab_touch_down(struct weston_touch_grab *grab, uint32_t time,
697 int touch_id, wl_fixed_t x, wl_fixed_t y)
698{
699 weston_touch_send_down(grab->touch, time, touch_id, x, y);
700}
701
702/** Send wl_touch.up events to focused resources.
703 *
704 * \param touch The touch where the up events originates from.
705 * \param time The timestamp of the event
706 * \param touch_id The touch_id value of the event
707 *
708 * For every resource that is currently in focus, send a wl_touch.up event
709 * with the passed parameters. The focused resources are the wl_touch
710 * resources of the client which currently has the surface with touch focus.
711 */
712WL_EXPORT void
713weston_touch_send_up(struct weston_touch *touch, uint32_t time, int touch_id)
714{
715 struct wl_display *display = touch->seat->compositor->wl_display;
716 uint32_t serial;
717 struct wl_resource *resource;
718 struct wl_list *resource_list;
719
720 if (!weston_touch_has_focus_resource(touch))
721 return;
722
723 resource_list = &touch->focus_resource_list;
724 serial = wl_display_next_serial(display);
725 wl_resource_for_each(resource, resource_list)
726 wl_touch_send_up(resource, serial, time, touch_id);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400727}
728
Kristian Høgsberge329f362013-05-06 22:19:57 -0400729static void
730default_grab_touch_up(struct weston_touch_grab *grab,
731 uint32_t time, int touch_id)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400732{
Quentin Glidiccde13452016-08-12 10:41:32 +0200733 weston_touch_send_up(grab->touch, time, touch_id);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400734}
735
Quentin Glidiccde13452016-08-12 10:41:32 +0200736/** Send wl_touch.motion events to focused resources.
737 *
738 * \param touch The touch where the motion events originates from.
739 * \param time The timestamp of the event
740 * \param touch_id The touch_id value of the event
741 * \param x The x value of the event
742 * \param y The y value of the event
743 *
744 * For every resource that is currently in focus, send a wl_touch.motion event
745 * with the passed parameters. The focused resources are the wl_touch
746 * resources of the client which currently has the surface with touch focus.
747 */
748WL_EXPORT void
749weston_touch_send_motion(struct weston_touch *touch, uint32_t time,
750 int touch_id, wl_fixed_t x, wl_fixed_t y)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400751{
Neil Roberts96d790e2013-09-19 17:32:00 +0100752 struct wl_resource *resource;
753 struct wl_list *resource_list;
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300754 wl_fixed_t sx, sy;
755
Quentin Glidiccde13452016-08-12 10:41:32 +0200756 if (!weston_touch_has_focus_resource(touch))
757 return;
758
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300759 weston_view_from_global_fixed(touch->focus, x, y, &sx, &sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400760
Neil Roberts96d790e2013-09-19 17:32:00 +0100761 resource_list = &touch->focus_resource_list;
Neil Roberts96d790e2013-09-19 17:32:00 +0100762 wl_resource_for_each(resource, resource_list) {
763 wl_touch_send_motion(resource, time,
Kristian Høgsberge329f362013-05-06 22:19:57 -0400764 touch_id, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400765 }
766}
767
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200768static void
Quentin Glidiccde13452016-08-12 10:41:32 +0200769default_grab_touch_motion(struct weston_touch_grab *grab, uint32_t time,
770 int touch_id, wl_fixed_t x, wl_fixed_t y)
771{
772 weston_touch_send_motion(grab->touch, time, touch_id, x, y);
773}
774
775
776/** Send wl_touch.frame events to focused resources.
777 *
778 * \param touch The touch where the frame events originates from.
779 *
780 * For every resource that is currently in focus, send a wl_touch.frame event.
781 * The focused resources are the wl_touch resources of the client which
782 * currently has the surface with touch focus.
783 */
784WL_EXPORT void
785weston_touch_send_frame(struct weston_touch *touch)
Jonas Ådahl1679f232014-04-12 09:39:51 +0200786{
787 struct wl_resource *resource;
788
Quentin Glidiccde13452016-08-12 10:41:32 +0200789 if (!weston_touch_has_focus_resource(touch))
790 return;
791
792 wl_resource_for_each(resource, &touch->focus_resource_list)
Jonas Ådahl1679f232014-04-12 09:39:51 +0200793 wl_touch_send_frame(resource);
794}
795
796static void
Quentin Glidiccde13452016-08-12 10:41:32 +0200797default_grab_touch_frame(struct weston_touch_grab *grab)
798{
799 weston_touch_send_frame(grab->touch);
800}
801
802static void
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200803default_grab_touch_cancel(struct weston_touch_grab *grab)
804{
805}
806
Kristian Høgsberge329f362013-05-06 22:19:57 -0400807static const struct weston_touch_grab_interface default_touch_grab_interface = {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400808 default_grab_touch_down,
809 default_grab_touch_up,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200810 default_grab_touch_motion,
Jonas Ådahl1679f232014-04-12 09:39:51 +0200811 default_grab_touch_frame,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200812 default_grab_touch_cancel,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400813};
814
Quentin Glidiccde13452016-08-12 10:41:32 +0200815/** Check if the keyboard has focused resources.
816 *
817 * \param keyboard The keyboard to check for focused resources.
818 * \return Whether or not this keyboard has focused resources
819 */
820WL_EXPORT bool
821weston_keyboard_has_focus_resource(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400822{
Quentin Glidiccde13452016-08-12 10:41:32 +0200823 if (!keyboard->focus)
824 return false;
825
826 if (wl_list_empty(&keyboard->focus_resource_list))
827 return false;
828
829 return true;
830}
831
832/** Send wl_keyboard.key events to focused resources.
833 *
834 * \param keyboard The keyboard where the key events originates from.
835 * \param time The timestamp of the event
836 * \param key The key value of the event
837 * \param state The state enum value of the event
838 *
839 * For every resource that is currently in focus, send a wl_keyboard.key event
840 * with the passed parameters. The focused resources are the wl_keyboard
841 * resources of the client which currently has the surface with keyboard focus.
842 */
843WL_EXPORT void
844weston_keyboard_send_key(struct weston_keyboard *keyboard,
Alexandros Frantzis47e79c82017-11-16 18:20:57 +0200845 const struct timespec *time, uint32_t key,
Quentin Glidiccde13452016-08-12 10:41:32 +0200846 enum wl_keyboard_key_state state)
847{
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400848 struct wl_resource *resource;
Rob Bradford880ebc72013-07-22 17:31:38 +0100849 struct wl_display *display = keyboard->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400850 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +0100851 struct wl_list *resource_list;
Alexandros Frantzis47e79c82017-11-16 18:20:57 +0200852 uint32_t msecs;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400853
Quentin Glidiccde13452016-08-12 10:41:32 +0200854 if (!weston_keyboard_has_focus_resource(keyboard))
855 return;
856
Neil Roberts96d790e2013-09-19 17:32:00 +0100857 resource_list = &keyboard->focus_resource_list;
Quentin Glidiccde13452016-08-12 10:41:32 +0200858 serial = wl_display_next_serial(display);
Alexandros Frantzis47e79c82017-11-16 18:20:57 +0200859 msecs = timespec_to_msec(time);
Quentin Glidiccde13452016-08-12 10:41:32 +0200860 wl_resource_for_each(resource, resource_list)
Alexandros Frantzis47e79c82017-11-16 18:20:57 +0200861 wl_keyboard_send_key(resource, serial, msecs, key, state);
Quentin Glidiccde13452016-08-12 10:41:32 +0200862};
863
864static void
865default_grab_keyboard_key(struct weston_keyboard_grab *grab,
Alexandros Frantzis47e79c82017-11-16 18:20:57 +0200866 const struct timespec *time, uint32_t key,
867 uint32_t state)
Quentin Glidiccde13452016-08-12 10:41:32 +0200868{
869 weston_keyboard_send_key(grab->keyboard, time, key, state);
Neil Roberts96d790e2013-09-19 17:32:00 +0100870}
871
872static void
873send_modifiers_to_resource(struct weston_keyboard *keyboard,
874 struct wl_resource *resource,
875 uint32_t serial)
876{
877 wl_keyboard_send_modifiers(resource,
878 serial,
879 keyboard->modifiers.mods_depressed,
880 keyboard->modifiers.mods_latched,
881 keyboard->modifiers.mods_locked,
882 keyboard->modifiers.group);
883}
884
885static void
886send_modifiers_to_client_in_list(struct wl_client *client,
887 struct wl_list *list,
888 uint32_t serial,
889 struct weston_keyboard *keyboard)
890{
891 struct wl_resource *resource;
892
893 wl_resource_for_each(resource, list) {
894 if (wl_resource_get_client(resource) == client)
895 send_modifiers_to_resource(keyboard,
896 resource,
897 serial);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400898 }
899}
900
Jonas Ådahl2cbf2932015-07-22 12:05:38 +0800901static struct weston_pointer_client *
902find_pointer_client_for_surface(struct weston_pointer *pointer,
903 struct weston_surface *surface)
904{
905 struct wl_client *client;
906
907 if (!surface)
908 return NULL;
909
910 if (!surface->resource)
911 return NULL;
912
913 client = wl_resource_get_client(surface->resource);
914 return weston_pointer_get_pointer_client(pointer, client);
915}
916
917static struct weston_pointer_client *
918find_pointer_client_for_view(struct weston_pointer *pointer, struct weston_view *view)
919{
920 if (!view)
921 return NULL;
922
923 return find_pointer_client_for_surface(pointer, view->surface);
924}
925
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400926static struct wl_resource *
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400927find_resource_for_surface(struct wl_list *list, struct weston_surface *surface)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400928{
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400929 if (!surface)
930 return NULL;
931
Jason Ekstrand44a38632013-06-14 10:08:00 -0500932 if (!surface->resource)
933 return NULL;
Stefan Schmidtfda26522013-09-17 10:54:09 +0100934
Jason Ekstrand44a38632013-06-14 10:08:00 -0500935 return wl_resource_find_for_client(list, wl_resource_get_client(surface->resource));
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400936}
937
Quentin Glidiccde13452016-08-12 10:41:32 +0200938/** Send wl_keyboard.modifiers events to focused resources and pointer
939 * focused resources.
940 *
941 * \param keyboard The keyboard where the modifiers events originates from.
942 * \param serial The serial of the event
943 * \param mods_depressed The mods_depressed value of the event
944 * \param mods_latched The mods_latched value of the event
945 * \param mods_locked The mods_locked value of the event
946 * \param group The group value of the event
947 *
948 * For every resource that is currently in focus, send a wl_keyboard.modifiers
949 * event with the passed parameters. The focused resources are the wl_keyboard
950 * resources of the client which currently has the surface with keyboard focus.
951 * This also sends wl_keyboard.modifiers events to the wl_keyboard resources of
952 * the client having pointer focus (if different from the keyboard focus client).
953 */
954WL_EXPORT void
955weston_keyboard_send_modifiers(struct weston_keyboard *keyboard,
956 uint32_t serial, uint32_t mods_depressed,
957 uint32_t mods_latched,
958 uint32_t mods_locked, uint32_t group)
959{
960 struct weston_pointer *pointer =
961 weston_seat_get_pointer(keyboard->seat);
962
963 if (weston_keyboard_has_focus_resource(keyboard)) {
964 struct wl_list *resource_list;
965 struct wl_resource *resource;
966
967 resource_list = &keyboard->focus_resource_list;
968 wl_resource_for_each(resource, resource_list) {
969 wl_keyboard_send_modifiers(resource, serial,
970 mods_depressed, mods_latched,
971 mods_locked, group);
972 }
973 }
974
975 if (pointer && pointer->focus && pointer->focus->surface->resource &&
976 pointer->focus->surface != keyboard->focus) {
977 struct wl_client *pointer_client =
978 wl_resource_get_client(pointer->focus->surface->resource);
979
980 send_modifiers_to_client_in_list(pointer_client,
981 &keyboard->resource_list,
982 serial,
983 keyboard);
984 }
985}
986
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400987static void
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700988default_grab_keyboard_modifiers(struct weston_keyboard_grab *grab,
989 uint32_t serial, uint32_t mods_depressed,
990 uint32_t mods_latched,
991 uint32_t mods_locked, uint32_t group)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400992{
Quentin Glidiccde13452016-08-12 10:41:32 +0200993 weston_keyboard_send_modifiers(grab->keyboard, serial, mods_depressed,
994 mods_latched, mods_locked, group);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400995}
996
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200997static void
998default_grab_keyboard_cancel(struct weston_keyboard_grab *grab)
999{
1000}
1001
Kristian Høgsberg29139d42013-04-18 15:25:39 -04001002static const struct weston_keyboard_grab_interface
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001003 default_keyboard_grab_interface = {
Kristian Høgsbergb27901c2013-10-28 15:32:02 -07001004 default_grab_keyboard_key,
1005 default_grab_keyboard_modifiers,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02001006 default_grab_keyboard_cancel,
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001007};
1008
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001009static void
1010pointer_unmap_sprite(struct weston_pointer *pointer)
1011{
Pekka Paalanenc557ff72014-11-12 16:42:52 +02001012 struct weston_surface *surface = pointer->sprite->surface;
1013
1014 if (weston_surface_is_mapped(surface))
1015 weston_surface_unmap(surface);
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001016
1017 wl_list_remove(&pointer->sprite_destroy_listener.link);
Quentin Glidic2edc3d52016-08-12 10:41:33 +02001018 surface->committed = NULL;
1019 surface->committed_private = NULL;
Pekka Paalanen8274d902014-08-06 19:36:51 +03001020 weston_surface_set_label_func(surface, NULL);
Jason Ekstranda7af7042013-10-12 22:38:11 -05001021 weston_view_destroy(pointer->sprite);
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001022 pointer->sprite = NULL;
1023}
1024
1025static void
1026pointer_handle_sprite_destroy(struct wl_listener *listener, void *data)
1027{
1028 struct weston_pointer *pointer =
1029 container_of(listener, struct weston_pointer,
1030 sprite_destroy_listener);
1031
1032 pointer->sprite = NULL;
1033}
1034
Jonas Ådahl3e12e632013-12-02 22:05:05 +01001035static void
1036weston_pointer_reset_state(struct weston_pointer *pointer)
1037{
1038 pointer->button_count = 0;
1039}
1040
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001041static void
1042weston_pointer_handle_output_destroy(struct wl_listener *listener, void *data);
1043
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001044WL_EXPORT struct weston_pointer *
Giulio Camuffocdb4d292013-11-14 23:42:53 +01001045weston_pointer_create(struct weston_seat *seat)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001046{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001047 struct weston_pointer *pointer;
1048
Peter Huttererf3d62272013-08-08 11:57:05 +10001049 pointer = zalloc(sizeof *pointer);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001050 if (pointer == NULL)
1051 return NULL;
1052
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001053 wl_list_init(&pointer->pointer_clients);
Giulio Camuffocdb4d292013-11-14 23:42:53 +01001054 weston_pointer_set_default_grab(pointer,
1055 seat->compositor->default_pointer_grab);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001056 wl_list_init(&pointer->focus_resource_listener.link);
1057 pointer->focus_resource_listener.notify = pointer_focus_resource_destroyed;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001058 pointer->default_grab.pointer = pointer;
1059 pointer->grab = &pointer->default_grab;
Giulio Camuffo6fcb3782013-11-14 23:42:50 +01001060 wl_signal_init(&pointer->motion_signal);
Emilio Pozuelo Monfortaa7a4762013-11-19 11:37:15 +01001061 wl_signal_init(&pointer->focus_signal);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001062 wl_list_init(&pointer->focus_view_listener.link);
Jonas Ådahl3eb4ddd2016-07-22 17:52:58 +08001063 wl_signal_init(&pointer->destroy_signal);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001064
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001065 pointer->sprite_destroy_listener.notify = pointer_handle_sprite_destroy;
1066
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001067 /* FIXME: Pick better co-ords. */
1068 pointer->x = wl_fixed_from_int(100);
1069 pointer->y = wl_fixed_from_int(100);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001070
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001071 pointer->output_destroy_listener.notify =
1072 weston_pointer_handle_output_destroy;
1073 wl_signal_add(&seat->compositor->output_destroyed_signal,
1074 &pointer->output_destroy_listener);
1075
Derek Foremanf9318d12015-05-11 15:40:11 -05001076 pointer->sx = wl_fixed_from_int(-1000000);
1077 pointer->sy = wl_fixed_from_int(-1000000);
1078
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001079 return pointer;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001080}
1081
1082WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001083weston_pointer_destroy(struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001084{
Jonas Ådahl3eb4ddd2016-07-22 17:52:58 +08001085 wl_signal_emit(&pointer->destroy_signal, pointer);
1086
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001087 if (pointer->sprite)
1088 pointer_unmap_sprite(pointer);
1089
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001090 /* XXX: What about pointer->resource_list? */
Neil Roberts96d790e2013-09-19 17:32:00 +01001091
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001092 wl_list_remove(&pointer->focus_resource_listener.link);
1093 wl_list_remove(&pointer->focus_view_listener.link);
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001094 wl_list_remove(&pointer->output_destroy_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001095 free(pointer);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001096}
1097
Giulio Camuffocdb4d292013-11-14 23:42:53 +01001098void
1099weston_pointer_set_default_grab(struct weston_pointer *pointer,
1100 const struct weston_pointer_grab_interface *interface)
1101{
1102 if (interface)
1103 pointer->default_grab.interface = interface;
1104 else
1105 pointer->default_grab.interface =
1106 &default_pointer_grab_interface;
1107}
1108
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001109WL_EXPORT struct weston_keyboard *
1110weston_keyboard_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001111{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001112 struct weston_keyboard *keyboard;
1113
Peter Huttererf3d62272013-08-08 11:57:05 +10001114 keyboard = zalloc(sizeof *keyboard);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001115 if (keyboard == NULL)
Neil Roberts96d790e2013-09-19 17:32:00 +01001116 return NULL;
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001117
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001118 wl_list_init(&keyboard->resource_list);
Neil Roberts96d790e2013-09-19 17:32:00 +01001119 wl_list_init(&keyboard->focus_resource_list);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001120 wl_list_init(&keyboard->focus_resource_listener.link);
1121 keyboard->focus_resource_listener.notify = keyboard_focus_resource_destroyed;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001122 wl_array_init(&keyboard->keys);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001123 keyboard->default_grab.interface = &default_keyboard_grab_interface;
1124 keyboard->default_grab.keyboard = keyboard;
1125 keyboard->grab = &keyboard->default_grab;
1126 wl_signal_init(&keyboard->focus_signal);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001127
1128 return keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001129}
1130
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001131static void
1132weston_xkb_info_destroy(struct weston_xkb_info *xkb_info);
1133
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001134WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001135weston_keyboard_destroy(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001136{
1137 /* XXX: What about keyboard->resource_list? */
Neil Roberts96d790e2013-09-19 17:32:00 +01001138
Derek Foreman185d1582017-06-28 11:17:23 -05001139 xkb_state_unref(keyboard->xkb_state.state);
1140 if (keyboard->xkb_info)
1141 weston_xkb_info_destroy(keyboard->xkb_info);
1142 xkb_keymap_unref(keyboard->pending_keymap);
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001143
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001144 wl_array_release(&keyboard->keys);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001145 wl_list_remove(&keyboard->focus_resource_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001146 free(keyboard);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001147}
1148
Jonas Ådahlcbfa7f72013-12-02 22:05:04 +01001149static void
1150weston_touch_reset_state(struct weston_touch *touch)
1151{
1152 touch->num_tp = 0;
1153}
1154
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001155WL_EXPORT struct weston_touch *
1156weston_touch_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001157{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001158 struct weston_touch *touch;
1159
Peter Huttererf3d62272013-08-08 11:57:05 +10001160 touch = zalloc(sizeof *touch);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001161 if (touch == NULL)
1162 return NULL;
1163
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001164 wl_list_init(&touch->resource_list);
Neil Roberts96d790e2013-09-19 17:32:00 +01001165 wl_list_init(&touch->focus_resource_list);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001166 wl_list_init(&touch->focus_view_listener.link);
1167 touch->focus_view_listener.notify = touch_focus_view_destroyed;
1168 wl_list_init(&touch->focus_resource_listener.link);
1169 touch->focus_resource_listener.notify = touch_focus_resource_destroyed;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001170 touch->default_grab.interface = &default_touch_grab_interface;
1171 touch->default_grab.touch = touch;
1172 touch->grab = &touch->default_grab;
1173 wl_signal_init(&touch->focus_signal);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001174
1175 return touch;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001176}
1177
1178WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001179weston_touch_destroy(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001180{
1181 /* XXX: What about touch->resource_list? */
Neil Roberts96d790e2013-09-19 17:32:00 +01001182
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001183 wl_list_remove(&touch->focus_view_listener.link);
1184 wl_list_remove(&touch->focus_resource_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001185 free(touch);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001186}
1187
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001188static void
Kristian Høgsberge3148752013-05-06 23:19:49 -04001189seat_send_updated_caps(struct weston_seat *seat)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001190{
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001191 enum wl_seat_capability caps = 0;
Rob Bradford6e737f52013-09-06 17:48:19 +01001192 struct wl_resource *resource;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001193
Jonas Ådahld6e1c342013-10-17 23:04:05 +02001194 if (seat->pointer_device_count > 0)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001195 caps |= WL_SEAT_CAPABILITY_POINTER;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02001196 if (seat->keyboard_device_count > 0)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001197 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02001198 if (seat->touch_device_count > 0)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001199 caps |= WL_SEAT_CAPABILITY_TOUCH;
1200
Rob Bradford6e737f52013-09-06 17:48:19 +01001201 wl_resource_for_each(resource, &seat->base_resource_list) {
1202 wl_seat_send_capabilities(resource, caps);
Jason Ekstrand44a38632013-06-14 10:08:00 -05001203 }
Jason Ekstranda4ab5422014-04-02 19:53:45 -05001204 wl_signal_emit(&seat->updated_caps_signal, seat);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001205}
1206
Derek Foremanf9318d12015-05-11 15:40:11 -05001207
1208/** Clear the pointer focus
1209 *
1210 * \param pointer the pointer to clear focus for.
1211 *
1212 * This can be used to unset pointer focus and set the co-ordinates to the
1213 * arbitrary values we use for the no focus case.
1214 *
1215 * There's no requirement to use this function. For example, passing the
1216 * results of a weston_compositor_pick_view() directly to
1217 * weston_pointer_set_focus() will do the right thing when no view is found.
1218 */
1219WL_EXPORT void
1220weston_pointer_clear_focus(struct weston_pointer *pointer)
1221{
1222 weston_pointer_set_focus(pointer, NULL,
1223 wl_fixed_from_int(-1000000),
1224 wl_fixed_from_int(-1000000));
1225}
1226
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001227WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001228weston_pointer_set_focus(struct weston_pointer *pointer,
Jason Ekstranda7af7042013-10-12 22:38:11 -05001229 struct weston_view *view,
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001230 wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001231{
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001232 struct weston_pointer_client *pointer_client;
Derek Foreman1281a362015-07-31 16:55:32 -05001233 struct weston_keyboard *kbd = weston_seat_get_keyboard(pointer->seat);
Neil Roberts96d790e2013-09-19 17:32:00 +01001234 struct wl_resource *resource;
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001235 struct wl_resource *surface_resource;
Rob Bradford880ebc72013-07-22 17:31:38 +01001236 struct wl_display *display = pointer->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001237 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +01001238 struct wl_list *focus_resource_list;
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -08001239 int refocus = 0;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001240
1241 if ((!pointer->focus && view) ||
1242 (pointer->focus && !view) ||
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -08001243 (pointer->focus && pointer->focus->surface != view->surface) ||
1244 pointer->sx != sx || pointer->sy != sy)
1245 refocus = 1;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001246
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001247 if (pointer->focus_client && refocus) {
1248 focus_resource_list = &pointer->focus_client->pointer_resources;
1249 if (!wl_list_empty(focus_resource_list)) {
1250 serial = wl_display_next_serial(display);
1251 surface_resource = pointer->focus->surface->resource;
1252 wl_resource_for_each(resource, focus_resource_list) {
1253 wl_pointer_send_leave(resource, serial,
1254 surface_resource);
Peter Hutterer87743e92016-01-18 16:38:22 +10001255 pointer_send_frame(resource);
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001256 }
Neil Roberts96d790e2013-09-19 17:32:00 +01001257 }
1258
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001259 pointer->focus_client = NULL;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001260 }
1261
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001262 pointer_client = find_pointer_client_for_view(pointer, view);
1263 if (pointer_client && refocus) {
1264 struct wl_client *surface_client = pointer_client->client;
Neil Roberts96d790e2013-09-19 17:32:00 +01001265
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001266 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +01001267
Jason Ekstranda7af7042013-10-12 22:38:11 -05001268 if (kbd && kbd->focus != view->surface)
Kristian Høgsbergcb406f12013-10-09 10:54:03 -07001269 send_modifiers_to_client_in_list(surface_client,
1270 &kbd->resource_list,
1271 serial,
1272 kbd);
1273
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001274 pointer->focus_client = pointer_client;
Neil Roberts96d790e2013-09-19 17:32:00 +01001275
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001276 focus_resource_list = &pointer->focus_client->pointer_resources;
Neil Roberts96d790e2013-09-19 17:32:00 +01001277 wl_resource_for_each(resource, focus_resource_list) {
1278 wl_pointer_send_enter(resource,
1279 serial,
Jason Ekstranda7af7042013-10-12 22:38:11 -05001280 view->surface->resource,
Neil Roberts96d790e2013-09-19 17:32:00 +01001281 sx, sy);
Peter Hutterer87743e92016-01-18 16:38:22 +10001282 pointer_send_frame(resource);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001283 }
Neil Roberts96d790e2013-09-19 17:32:00 +01001284
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001285 pointer->focus_serial = serial;
1286 }
1287
Giulio Camuffo65a07f82013-12-06 12:46:27 +01001288 wl_list_remove(&pointer->focus_view_listener.link);
1289 wl_list_init(&pointer->focus_view_listener.link);
1290 wl_list_remove(&pointer->focus_resource_listener.link);
1291 wl_list_init(&pointer->focus_resource_listener.link);
Emilio Pozuelo Monfortaa7a4762013-11-19 11:37:15 +01001292 if (view)
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001293 wl_signal_add(&view->destroy_signal, &pointer->focus_view_listener);
Giulio Camuffo65a07f82013-12-06 12:46:27 +01001294 if (view && view->surface->resource)
1295 wl_resource_add_destroy_listener(view->surface->resource,
1296 &pointer->focus_resource_listener);
1297
1298 pointer->focus = view;
1299 pointer->focus_view_listener.notify = pointer_focus_view_destroyed;
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -08001300 pointer->sx = sx;
1301 pointer->sy = sy;
1302
Derek Foremanf9318d12015-05-11 15:40:11 -05001303 assert(view || sx == wl_fixed_from_int(-1000000));
1304 assert(view || sy == wl_fixed_from_int(-1000000));
1305
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001306 wl_signal_emit(&pointer->focus_signal, pointer);
1307}
1308
Neil Roberts96d790e2013-09-19 17:32:00 +01001309static void
1310send_enter_to_resource_list(struct wl_list *list,
1311 struct weston_keyboard *keyboard,
1312 struct weston_surface *surface,
1313 uint32_t serial)
1314{
1315 struct wl_resource *resource;
1316
1317 wl_resource_for_each(resource, list) {
1318 send_modifiers_to_resource(keyboard, resource, serial);
1319 wl_keyboard_send_enter(resource, serial,
1320 surface->resource,
1321 &keyboard->keys);
1322 }
1323}
1324
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001325WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -04001326weston_keyboard_set_focus(struct weston_keyboard *keyboard,
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -04001327 struct weston_surface *surface)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001328{
1329 struct wl_resource *resource;
Rob Bradford880ebc72013-07-22 17:31:38 +01001330 struct wl_display *display = keyboard->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001331 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +01001332 struct wl_list *focus_resource_list;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001333
Neil Roberts96d790e2013-09-19 17:32:00 +01001334 focus_resource_list = &keyboard->focus_resource_list;
1335
1336 if (!wl_list_empty(focus_resource_list) && keyboard->focus != surface) {
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001337 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +01001338 wl_resource_for_each(resource, focus_resource_list) {
1339 wl_keyboard_send_leave(resource, serial,
1340 keyboard->focus->resource);
1341 }
1342 move_resources(&keyboard->resource_list, focus_resource_list);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001343 }
1344
Neil Roberts96d790e2013-09-19 17:32:00 +01001345 if (find_resource_for_surface(&keyboard->resource_list, surface) &&
1346 keyboard->focus != surface) {
1347 struct wl_client *surface_client =
1348 wl_resource_get_client(surface->resource);
1349
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001350 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +01001351
1352 move_resources_for_client(focus_resource_list,
1353 &keyboard->resource_list,
1354 surface_client);
1355 send_enter_to_resource_list(focus_resource_list,
1356 keyboard,
1357 surface,
1358 serial);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001359 keyboard->focus_serial = serial;
Giulio Camuffo65a07f82013-12-06 12:46:27 +01001360 }
1361
1362 wl_list_remove(&keyboard->focus_resource_listener.link);
1363 wl_list_init(&keyboard->focus_resource_listener.link);
1364 if (surface && surface->resource)
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001365 wl_resource_add_destroy_listener(surface->resource,
1366 &keyboard->focus_resource_listener);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001367
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001368 keyboard->focus = surface;
1369 wl_signal_emit(&keyboard->focus_signal, keyboard);
1370}
1371
Giulio Camuffoa20ca812014-11-22 11:16:56 +02001372/* Users of this function must manually manage the keyboard focus */
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001373WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -04001374weston_keyboard_start_grab(struct weston_keyboard *keyboard,
1375 struct weston_keyboard_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001376{
1377 keyboard->grab = grab;
1378 grab->keyboard = keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001379}
1380
1381WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -04001382weston_keyboard_end_grab(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001383{
1384 keyboard->grab = &keyboard->default_grab;
1385}
1386
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02001387static void
1388weston_keyboard_cancel_grab(struct weston_keyboard *keyboard)
1389{
1390 keyboard->grab->interface->cancel(keyboard->grab);
1391}
1392
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001393WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001394weston_pointer_start_grab(struct weston_pointer *pointer,
1395 struct weston_pointer_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001396{
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001397 pointer->grab = grab;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001398 grab->pointer = pointer;
Kristian Høgsbergda751b82013-07-04 00:58:07 -04001399 pointer->grab->interface->focus(pointer->grab);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001400}
1401
1402WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001403weston_pointer_end_grab(struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001404{
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001405 pointer->grab = &pointer->default_grab;
Kristian Høgsbergda751b82013-07-04 00:58:07 -04001406 pointer->grab->interface->focus(pointer->grab);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001407}
1408
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02001409static void
1410weston_pointer_cancel_grab(struct weston_pointer *pointer)
1411{
1412 pointer->grab->interface->cancel(pointer->grab);
1413}
1414
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001415WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -04001416weston_touch_start_grab(struct weston_touch *touch, struct weston_touch_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001417{
1418 touch->grab = grab;
1419 grab->touch = touch;
1420}
1421
1422WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -04001423weston_touch_end_grab(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001424{
1425 touch->grab = &touch->default_grab;
1426}
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001427
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02001428static void
1429weston_touch_cancel_grab(struct weston_touch *touch)
1430{
1431 touch->grab->interface->cancel(touch->grab);
1432}
1433
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001434static void
1435weston_pointer_clamp_for_output(struct weston_pointer *pointer,
1436 struct weston_output *output,
1437 wl_fixed_t *fx, wl_fixed_t *fy)
1438{
1439 int x, y;
1440
1441 x = wl_fixed_to_int(*fx);
1442 y = wl_fixed_to_int(*fy);
1443
1444 if (x < output->x)
1445 *fx = wl_fixed_from_int(output->x);
1446 else if (x >= output->x + output->width)
1447 *fx = wl_fixed_from_int(output->x +
1448 output->width - 1);
1449 if (y < output->y)
1450 *fy = wl_fixed_from_int(output->y);
1451 else if (y >= output->y + output->height)
1452 *fy = wl_fixed_from_int(output->y +
1453 output->height - 1);
1454}
1455
Rob Bradford806d8c02013-06-25 18:56:41 +01001456WL_EXPORT void
1457weston_pointer_clamp(struct weston_pointer *pointer, wl_fixed_t *fx, wl_fixed_t *fy)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001458{
Rob Bradford806d8c02013-06-25 18:56:41 +01001459 struct weston_compositor *ec = pointer->seat->compositor;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001460 struct weston_output *output, *prev = NULL;
1461 int x, y, old_x, old_y, valid = 0;
1462
1463 x = wl_fixed_to_int(*fx);
1464 y = wl_fixed_to_int(*fy);
Rob Bradford806d8c02013-06-25 18:56:41 +01001465 old_x = wl_fixed_to_int(pointer->x);
1466 old_y = wl_fixed_to_int(pointer->y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001467
1468 wl_list_for_each(output, &ec->output_list, link) {
Rob Bradford66bd9f52013-06-25 18:56:42 +01001469 if (pointer->seat->output && pointer->seat->output != output)
1470 continue;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001471 if (pixman_region32_contains_point(&output->region,
1472 x, y, NULL))
1473 valid = 1;
1474 if (pixman_region32_contains_point(&output->region,
1475 old_x, old_y, NULL))
1476 prev = output;
1477 }
1478
Rob Bradford66bd9f52013-06-25 18:56:42 +01001479 if (!prev)
1480 prev = pointer->seat->output;
1481
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001482 if (prev && !valid)
1483 weston_pointer_clamp_for_output(pointer, prev, fx, fy);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001484}
1485
Jonas Ådahld2510102014-10-05 21:39:14 +02001486static void
1487weston_pointer_move_to(struct weston_pointer *pointer,
1488 wl_fixed_t x, wl_fixed_t y)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001489{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001490 int32_t ix, iy;
1491
Rob Bradford806d8c02013-06-25 18:56:41 +01001492 weston_pointer_clamp (pointer, &x, &y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001493
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001494 pointer->x = x;
1495 pointer->y = y;
1496
1497 ix = wl_fixed_to_int(x);
1498 iy = wl_fixed_to_int(y);
1499
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001500 if (pointer->sprite) {
Jason Ekstranda7af7042013-10-12 22:38:11 -05001501 weston_view_set_position(pointer->sprite,
1502 ix - pointer->hotspot_x,
1503 iy - pointer->hotspot_y);
1504 weston_view_schedule_repaint(pointer->sprite);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001505 }
Giulio Camuffo6fcb3782013-11-14 23:42:50 +01001506
Giulio Camuffo1959ab82013-11-14 23:42:52 +01001507 pointer->grab->interface->focus(pointer->grab);
Giulio Camuffo6fcb3782013-11-14 23:42:50 +01001508 wl_signal_emit(&pointer->motion_signal, pointer);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001509}
1510
Jonas Ådahld2510102014-10-05 21:39:14 +02001511WL_EXPORT void
Jonas Ådahld2510102014-10-05 21:39:14 +02001512weston_pointer_move(struct weston_pointer *pointer,
1513 struct weston_pointer_motion_event *event)
1514{
1515 wl_fixed_t x, y;
1516
1517 weston_pointer_motion_to_abs(pointer, event, &x, &y);
1518 weston_pointer_move_to(pointer, x, y);
1519}
1520
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001521/** Verify if the pointer is in a valid position and move it if it isn't.
1522 */
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001523static void
1524weston_pointer_handle_output_destroy(struct wl_listener *listener, void *data)
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001525{
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001526 struct weston_pointer *pointer;
1527 struct weston_compositor *ec;
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001528 struct weston_output *output, *closest = NULL;
1529 int x, y, distance, min = INT_MAX;
1530 wl_fixed_t fx, fy;
1531
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001532 pointer = container_of(listener, struct weston_pointer,
1533 output_destroy_listener);
1534 ec = pointer->seat->compositor;
1535
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001536 x = wl_fixed_to_int(pointer->x);
1537 y = wl_fixed_to_int(pointer->y);
1538
1539 wl_list_for_each(output, &ec->output_list, link) {
1540 if (pixman_region32_contains_point(&output->region,
1541 x, y, NULL))
1542 return;
1543
1544 /* Aproximante the distance from the pointer to the center of
1545 * the output. */
1546 distance = abs(output->x + output->width / 2 - x) +
1547 abs(output->y + output->height / 2 - y);
1548 if (distance < min) {
1549 min = distance;
1550 closest = output;
1551 }
1552 }
1553
1554 /* Nothing to do if there's no output left. */
1555 if (!closest)
1556 return;
1557
1558 fx = pointer->x;
1559 fy = pointer->y;
1560
1561 weston_pointer_clamp_for_output(pointer, closest, &fx, &fy);
Jonas Ådahld2510102014-10-05 21:39:14 +02001562 weston_pointer_move_to(pointer, fx, fy);
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001563}
1564
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001565WL_EXPORT void
1566notify_motion(struct weston_seat *seat,
Alexandros Frantzis84b31f82017-11-24 18:01:46 +02001567 const struct timespec *time,
Jonas Ådahld2510102014-10-05 21:39:14 +02001568 struct weston_pointer_motion_event *event)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001569{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001570 struct weston_compositor *ec = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001571 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001572
1573 weston_compositor_wake(ec);
Jonas Ådahld2510102014-10-05 21:39:14 +02001574 pointer->grab->interface->motion(pointer->grab, time, event);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001575}
1576
Daniel Stone96d47c02013-11-19 11:37:12 +01001577static void
1578run_modifier_bindings(struct weston_seat *seat, uint32_t old, uint32_t new)
1579{
1580 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001581 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Daniel Stone96d47c02013-11-19 11:37:12 +01001582 uint32_t diff;
1583 unsigned int i;
1584 struct {
1585 uint32_t xkb;
1586 enum weston_keyboard_modifier weston;
1587 } mods[] = {
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001588 { keyboard->xkb_info->ctrl_mod, MODIFIER_CTRL },
1589 { keyboard->xkb_info->alt_mod, MODIFIER_ALT },
1590 { keyboard->xkb_info->super_mod, MODIFIER_SUPER },
1591 { keyboard->xkb_info->shift_mod, MODIFIER_SHIFT },
Daniel Stone96d47c02013-11-19 11:37:12 +01001592 };
1593
1594 diff = new & ~old;
1595 for (i = 0; i < ARRAY_LENGTH(mods); i++) {
1596 if (diff & (1 << mods[i].xkb))
1597 weston_compositor_run_modifier_binding(compositor,
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001598 keyboard,
Daniel Stone96d47c02013-11-19 11:37:12 +01001599 mods[i].weston,
1600 WL_KEYBOARD_KEY_STATE_PRESSED);
1601 }
1602
1603 diff = old & ~new;
1604 for (i = 0; i < ARRAY_LENGTH(mods); i++) {
1605 if (diff & (1 << mods[i].xkb))
1606 weston_compositor_run_modifier_binding(compositor,
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001607 keyboard,
Daniel Stone96d47c02013-11-19 11:37:12 +01001608 mods[i].weston,
1609 WL_KEYBOARD_KEY_STATE_RELEASED);
1610 }
1611}
1612
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001613WL_EXPORT void
Alexandros Frantzis84b31f82017-11-24 18:01:46 +02001614notify_motion_absolute(struct weston_seat *seat, const struct timespec *time,
1615 double x, double y)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001616{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001617 struct weston_compositor *ec = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001618 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Jonas Ådahld2510102014-10-05 21:39:14 +02001619 struct weston_pointer_motion_event event = { 0 };
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001620
1621 weston_compositor_wake(ec);
Jonas Ådahld2510102014-10-05 21:39:14 +02001622
1623 event = (struct weston_pointer_motion_event) {
1624 .mask = WESTON_POINTER_MOTION_ABS,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001625 .x = x,
1626 .y = y,
Jonas Ådahld2510102014-10-05 21:39:14 +02001627 };
1628
1629 pointer->grab->interface->motion(pointer->grab, time, &event);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001630}
1631
Jonas Ådahl94e2e2d2014-10-18 18:42:19 +02001632static unsigned int
1633peek_next_activate_serial(struct weston_compositor *c)
1634{
1635 unsigned serial = c->activate_serial + 1;
1636
1637 return serial == 0 ? 1 : serial;
1638}
1639
1640static void
1641inc_activate_serial(struct weston_compositor *c)
1642{
1643 c->activate_serial = peek_next_activate_serial (c);
1644}
1645
1646WL_EXPORT void
1647weston_view_activate(struct weston_view *view,
1648 struct weston_seat *seat,
1649 uint32_t flags)
1650{
1651 struct weston_compositor *compositor = seat->compositor;
1652
1653 if (flags & WESTON_ACTIVATE_FLAG_CLICKED) {
1654 view->click_to_activate_serial =
1655 peek_next_activate_serial(compositor);
1656 }
1657
1658 weston_seat_set_keyboard_focus(seat, view->surface);
1659}
1660
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001661WL_EXPORT void
Alexandros Frantzis215bedc2017-11-16 18:20:55 +02001662notify_button(struct weston_seat *seat, const struct timespec *time,
1663 int32_t button, enum wl_pointer_button_state state)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001664{
1665 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001666 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001667
1668 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001669 weston_compositor_idle_inhibit(compositor);
1670 if (pointer->button_count == 0) {
1671 pointer->grab_button = button;
Alexandros Frantzis215bedc2017-11-16 18:20:55 +02001672 pointer->grab_time = *time;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001673 pointer->grab_x = pointer->x;
1674 pointer->grab_y = pointer->y;
1675 }
1676 pointer->button_count++;
1677 } else {
1678 weston_compositor_idle_release(compositor);
1679 pointer->button_count--;
1680 }
1681
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001682 weston_compositor_run_button_binding(compositor, pointer, time, button,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001683 state);
1684
1685 pointer->grab->interface->button(pointer->grab, time, button, state);
1686
1687 if (pointer->button_count == 1)
1688 pointer->grab_serial =
1689 wl_display_get_serial(compositor->wl_display);
1690}
1691
1692WL_EXPORT void
Alexandros Frantzis80321942017-11-16 18:20:56 +02001693notify_axis(struct weston_seat *seat, const struct timespec *time,
Peter Hutterer89b6a492016-01-18 15:58:17 +10001694 struct weston_pointer_axis_event *event)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001695{
1696 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001697 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001698
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001699 weston_compositor_wake(compositor);
1700
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001701 if (weston_compositor_run_axis_binding(compositor, pointer,
Peter Hutterer89b6a492016-01-18 15:58:17 +10001702 time, event))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001703 return;
1704
Peter Hutterer89b6a492016-01-18 15:58:17 +10001705 pointer->grab->interface->axis(pointer->grab, time, event);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001706}
1707
Peter Hutterer87743e92016-01-18 16:38:22 +10001708WL_EXPORT void
1709notify_axis_source(struct weston_seat *seat, uint32_t source)
1710{
1711 struct weston_compositor *compositor = seat->compositor;
1712 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1713
1714 weston_compositor_wake(compositor);
1715
1716 pointer->grab->interface->axis_source(pointer->grab, source);
1717}
1718
1719WL_EXPORT void
1720notify_pointer_frame(struct weston_seat *seat)
1721{
1722 struct weston_compositor *compositor = seat->compositor;
1723 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1724
1725 weston_compositor_wake(compositor);
1726
1727 pointer->grab->interface->frame(pointer->grab);
1728}
1729
Giulio Camuffo6ef444d2014-08-28 19:44:09 +03001730WL_EXPORT int
1731weston_keyboard_set_locks(struct weston_keyboard *keyboard,
1732 uint32_t mask, uint32_t value)
1733{
Giulio Camuffo6ef444d2014-08-28 19:44:09 +03001734 uint32_t serial;
1735 xkb_mod_mask_t mods_depressed, mods_latched, mods_locked, group;
1736 xkb_mod_mask_t num, caps;
1737
1738 /* We don't want the leds to go out of sync with the actual state
1739 * so if the backend has no way to change the leds don't try to
1740 * change the state */
1741 if (!keyboard->seat->led_update)
1742 return -1;
1743
1744 mods_depressed = xkb_state_serialize_mods(keyboard->xkb_state.state,
1745 XKB_STATE_DEPRESSED);
1746 mods_latched = xkb_state_serialize_mods(keyboard->xkb_state.state,
1747 XKB_STATE_LATCHED);
1748 mods_locked = xkb_state_serialize_mods(keyboard->xkb_state.state,
1749 XKB_STATE_LOCKED);
1750 group = xkb_state_serialize_group(keyboard->xkb_state.state,
1751 XKB_STATE_EFFECTIVE);
1752
1753 num = (1 << keyboard->xkb_info->mod2_mod);
1754 caps = (1 << keyboard->xkb_info->caps_mod);
1755 if (mask & WESTON_NUM_LOCK) {
1756 if (value & WESTON_NUM_LOCK)
1757 mods_locked |= num;
1758 else
1759 mods_locked &= ~num;
1760 }
1761 if (mask & WESTON_CAPS_LOCK) {
1762 if (value & WESTON_CAPS_LOCK)
1763 mods_locked |= caps;
1764 else
1765 mods_locked &= ~caps;
1766 }
1767
1768 xkb_state_update_mask(keyboard->xkb_state.state, mods_depressed,
1769 mods_latched, mods_locked, 0, 0, group);
1770
1771 serial = wl_display_next_serial(
1772 keyboard->seat->compositor->wl_display);
1773 notify_modifiers(keyboard->seat, serial);
1774
1775 return 0;
Giulio Camuffo6ef444d2014-08-28 19:44:09 +03001776}
1777
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001778WL_EXPORT void
1779notify_modifiers(struct weston_seat *seat, uint32_t serial)
1780{
Derek Foreman1281a362015-07-31 16:55:32 -05001781 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001782 struct weston_keyboard_grab *grab = keyboard->grab;
1783 uint32_t mods_depressed, mods_latched, mods_locked, group;
1784 uint32_t mods_lookup;
1785 enum weston_led leds = 0;
1786 int changed = 0;
1787
1788 /* Serialize and update our internal state, checking to see if it's
1789 * different to the previous state. */
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001790 mods_depressed = xkb_state_serialize_mods(keyboard->xkb_state.state,
Ran Benita2e1968f2014-08-19 23:59:51 +03001791 XKB_STATE_MODS_DEPRESSED);
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001792 mods_latched = xkb_state_serialize_mods(keyboard->xkb_state.state,
Ran Benita2e1968f2014-08-19 23:59:51 +03001793 XKB_STATE_MODS_LATCHED);
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001794 mods_locked = xkb_state_serialize_mods(keyboard->xkb_state.state,
Ran Benita2e1968f2014-08-19 23:59:51 +03001795 XKB_STATE_MODS_LOCKED);
1796 group = xkb_state_serialize_layout(keyboard->xkb_state.state,
1797 XKB_STATE_LAYOUT_EFFECTIVE);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001798
Derek Foreman244e99e2015-06-03 15:53:26 -05001799 if (mods_depressed != keyboard->modifiers.mods_depressed ||
1800 mods_latched != keyboard->modifiers.mods_latched ||
1801 mods_locked != keyboard->modifiers.mods_locked ||
1802 group != keyboard->modifiers.group)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001803 changed = 1;
1804
Derek Foreman244e99e2015-06-03 15:53:26 -05001805 run_modifier_bindings(seat, keyboard->modifiers.mods_depressed,
Daniel Stone96d47c02013-11-19 11:37:12 +01001806 mods_depressed);
1807
Derek Foreman244e99e2015-06-03 15:53:26 -05001808 keyboard->modifiers.mods_depressed = mods_depressed;
1809 keyboard->modifiers.mods_latched = mods_latched;
1810 keyboard->modifiers.mods_locked = mods_locked;
1811 keyboard->modifiers.group = group;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001812
1813 /* And update the modifier_state for bindings. */
1814 mods_lookup = mods_depressed | mods_latched;
1815 seat->modifier_state = 0;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001816 if (mods_lookup & (1 << keyboard->xkb_info->ctrl_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001817 seat->modifier_state |= MODIFIER_CTRL;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001818 if (mods_lookup & (1 << keyboard->xkb_info->alt_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001819 seat->modifier_state |= MODIFIER_ALT;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001820 if (mods_lookup & (1 << keyboard->xkb_info->super_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001821 seat->modifier_state |= MODIFIER_SUPER;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001822 if (mods_lookup & (1 << keyboard->xkb_info->shift_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001823 seat->modifier_state |= MODIFIER_SHIFT;
1824
1825 /* Finally, notify the compositor that LEDs have changed. */
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001826 if (xkb_state_led_index_is_active(keyboard->xkb_state.state,
1827 keyboard->xkb_info->num_led))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001828 leds |= LED_NUM_LOCK;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001829 if (xkb_state_led_index_is_active(keyboard->xkb_state.state,
1830 keyboard->xkb_info->caps_led))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001831 leds |= LED_CAPS_LOCK;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001832 if (xkb_state_led_index_is_active(keyboard->xkb_state.state,
1833 keyboard->xkb_info->scroll_led))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001834 leds |= LED_SCROLL_LOCK;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001835 if (leds != keyboard->xkb_state.leds && seat->led_update)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001836 seat->led_update(seat, leds);
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001837 keyboard->xkb_state.leds = leds;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001838
1839 if (changed) {
1840 grab->interface->modifiers(grab,
1841 serial,
1842 keyboard->modifiers.mods_depressed,
1843 keyboard->modifiers.mods_latched,
1844 keyboard->modifiers.mods_locked,
1845 keyboard->modifiers.group);
1846 }
1847}
1848
1849static void
1850update_modifier_state(struct weston_seat *seat, uint32_t serial, uint32_t key,
1851 enum wl_keyboard_key_state state)
1852{
Derek Foreman1281a362015-07-31 16:55:32 -05001853 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001854 enum xkb_key_direction direction;
1855
1856 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
1857 direction = XKB_KEY_DOWN;
1858 else
1859 direction = XKB_KEY_UP;
1860
1861 /* Offset the keycode by 8, as the evdev XKB rules reflect X's
1862 * broken keycode system, which starts at 8. */
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001863 xkb_state_update_key(keyboard->xkb_state.state, key + 8, direction);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001864
1865 notify_modifiers(seat, serial);
1866}
Rui Matos65196bc2013-10-10 19:44:19 +02001867
1868static void
1869send_keymap(struct wl_resource *resource, struct weston_xkb_info *xkb_info)
1870{
1871 wl_keyboard_send_keymap(resource,
1872 WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
1873 xkb_info->keymap_fd,
1874 xkb_info->keymap_size);
1875}
1876
1877static void
1878send_modifiers(struct wl_resource *resource, uint32_t serial, struct weston_keyboard *keyboard)
1879{
1880 wl_keyboard_send_modifiers(resource, serial,
1881 keyboard->modifiers.mods_depressed,
1882 keyboard->modifiers.mods_latched,
1883 keyboard->modifiers.mods_locked,
1884 keyboard->modifiers.group);
1885}
1886
1887static struct weston_xkb_info *
1888weston_xkb_info_create(struct xkb_keymap *keymap);
Rui Matos65196bc2013-10-10 19:44:19 +02001889
1890static void
1891update_keymap(struct weston_seat *seat)
1892{
Derek Foreman1281a362015-07-31 16:55:32 -05001893 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Rui Matos65196bc2013-10-10 19:44:19 +02001894 struct wl_resource *resource;
1895 struct weston_xkb_info *xkb_info;
1896 struct xkb_state *state;
1897 xkb_mod_mask_t latched_mods;
1898 xkb_mod_mask_t locked_mods;
1899
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001900 xkb_info = weston_xkb_info_create(keyboard->pending_keymap);
Rui Matos65196bc2013-10-10 19:44:19 +02001901
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001902 xkb_keymap_unref(keyboard->pending_keymap);
1903 keyboard->pending_keymap = NULL;
Rui Matos65196bc2013-10-10 19:44:19 +02001904
1905 if (!xkb_info) {
1906 weston_log("failed to create XKB info\n");
1907 return;
1908 }
1909
1910 state = xkb_state_new(xkb_info->keymap);
1911 if (!state) {
1912 weston_log("failed to initialise XKB state\n");
1913 weston_xkb_info_destroy(xkb_info);
1914 return;
1915 }
1916
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001917 latched_mods = xkb_state_serialize_mods(keyboard->xkb_state.state,
1918 XKB_STATE_MODS_LATCHED);
1919 locked_mods = xkb_state_serialize_mods(keyboard->xkb_state.state,
1920 XKB_STATE_MODS_LOCKED);
Rui Matos65196bc2013-10-10 19:44:19 +02001921 xkb_state_update_mask(state,
1922 0, /* depressed */
1923 latched_mods,
1924 locked_mods,
1925 0, 0, 0);
1926
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001927 weston_xkb_info_destroy(keyboard->xkb_info);
1928 keyboard->xkb_info = xkb_info;
Rui Matos65196bc2013-10-10 19:44:19 +02001929
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001930 xkb_state_unref(keyboard->xkb_state.state);
1931 keyboard->xkb_state.state = state;
Rui Matos65196bc2013-10-10 19:44:19 +02001932
Derek Foremanbc91e542015-06-03 15:53:27 -05001933 wl_resource_for_each(resource, &keyboard->resource_list)
Rui Matos65196bc2013-10-10 19:44:19 +02001934 send_keymap(resource, xkb_info);
Derek Foremanbc91e542015-06-03 15:53:27 -05001935 wl_resource_for_each(resource, &keyboard->focus_resource_list)
Rui Matos65196bc2013-10-10 19:44:19 +02001936 send_keymap(resource, xkb_info);
1937
1938 notify_modifiers(seat, wl_display_next_serial(seat->compositor->wl_display));
1939
1940 if (!latched_mods && !locked_mods)
1941 return;
1942
Derek Foremanbc91e542015-06-03 15:53:27 -05001943 wl_resource_for_each(resource, &keyboard->resource_list)
1944 send_modifiers(resource, wl_display_get_serial(seat->compositor->wl_display), keyboard);
1945 wl_resource_for_each(resource, &keyboard->focus_resource_list)
1946 send_modifiers(resource, wl_display_get_serial(seat->compositor->wl_display), keyboard);
Rui Matos65196bc2013-10-10 19:44:19 +02001947}
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001948
1949WL_EXPORT void
Alexandros Frantzis47e79c82017-11-16 18:20:57 +02001950notify_key(struct weston_seat *seat, const struct timespec *time, uint32_t key,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001951 enum wl_keyboard_key_state state,
1952 enum weston_key_state_update update_state)
1953{
1954 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001955 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001956 struct weston_keyboard_grab *grab = keyboard->grab;
Pekka Paalanen86b53962014-11-19 13:43:32 +02001957 uint32_t *k, *end;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001958
1959 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001960 weston_compositor_idle_inhibit(compositor);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001961 } else {
1962 weston_compositor_idle_release(compositor);
1963 }
1964
Pekka Paalanen86b53962014-11-19 13:43:32 +02001965 end = keyboard->keys.data + keyboard->keys.size;
1966 for (k = keyboard->keys.data; k < end; k++) {
1967 if (*k == key) {
1968 /* Ignore server-generated repeats. */
1969 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
1970 return;
1971 *k = *--end;
1972 }
1973 }
1974 keyboard->keys.size = (void *) end - keyboard->keys.data;
1975 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
1976 k = wl_array_add(&keyboard->keys, sizeof *k);
1977 *k = key;
1978 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001979
1980 if (grab == &keyboard->default_grab ||
1981 grab == &keyboard->input_method_grab) {
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001982 weston_compositor_run_key_binding(compositor, keyboard, time,
1983 key, state);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001984 grab = keyboard->grab;
1985 }
1986
1987 grab->interface->key(grab, time, key, state);
1988
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001989 if (keyboard->pending_keymap &&
Pekka Paalanen86b53962014-11-19 13:43:32 +02001990 keyboard->keys.size == 0)
Rui Matos65196bc2013-10-10 19:44:19 +02001991 update_keymap(seat);
1992
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001993 if (update_state == STATE_UPDATE_AUTOMATIC) {
1994 update_modifier_state(seat,
1995 wl_display_get_serial(compositor->wl_display),
1996 key,
1997 state);
1998 }
Giulio Camuffob6ddf6c2015-02-06 19:06:54 +02001999
Olivier Fourdandf84dbe2016-06-30 16:01:56 +02002000 keyboard->grab_serial = wl_display_get_serial(compositor->wl_display);
Giulio Camuffob6ddf6c2015-02-06 19:06:54 +02002001 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
Alexandros Frantzis47e79c82017-11-16 18:20:57 +02002002 keyboard->grab_time = *time;
Giulio Camuffob6ddf6c2015-02-06 19:06:54 +02002003 keyboard->grab_key = key;
2004 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002005}
2006
2007WL_EXPORT void
2008notify_pointer_focus(struct weston_seat *seat, struct weston_output *output,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02002009 double x, double y)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002010{
Derek Foreman1281a362015-07-31 16:55:32 -05002011 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
2012
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002013 if (output) {
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02002014 weston_pointer_move_to(pointer,
2015 wl_fixed_from_double(x),
2016 wl_fixed_from_double(y));
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002017 } else {
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04002018 /* FIXME: We should call weston_pointer_set_focus(seat,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002019 * NULL) here, but somehow that breaks re-entry... */
2020 }
2021}
2022
2023static void
2024destroy_device_saved_kbd_focus(struct wl_listener *listener, void *data)
2025{
2026 struct weston_seat *ws;
2027
2028 ws = container_of(listener, struct weston_seat,
2029 saved_kbd_focus_listener);
2030
2031 ws->saved_kbd_focus = NULL;
2032}
2033
2034WL_EXPORT void
2035notify_keyboard_focus_in(struct weston_seat *seat, struct wl_array *keys,
2036 enum weston_key_state_update update_state)
2037{
2038 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05002039 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -04002040 struct weston_surface *surface;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002041 uint32_t *k, serial;
2042
2043 serial = wl_display_next_serial(compositor->wl_display);
2044 wl_array_copy(&keyboard->keys, keys);
2045 wl_array_for_each(k, &keyboard->keys) {
2046 weston_compositor_idle_inhibit(compositor);
2047 if (update_state == STATE_UPDATE_AUTOMATIC)
2048 update_modifier_state(seat, serial, *k,
2049 WL_KEYBOARD_KEY_STATE_PRESSED);
2050 }
2051
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002052 surface = seat->saved_kbd_focus;
2053
2054 if (surface) {
2055 wl_list_remove(&seat->saved_kbd_focus_listener.link);
2056 weston_keyboard_set_focus(keyboard, surface);
2057 seat->saved_kbd_focus = NULL;
2058 }
2059}
2060
2061WL_EXPORT void
2062notify_keyboard_focus_out(struct weston_seat *seat)
2063{
2064 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05002065 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
2066 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002067 uint32_t *k, serial;
2068
2069 serial = wl_display_next_serial(compositor->wl_display);
2070 wl_array_for_each(k, &keyboard->keys) {
2071 weston_compositor_idle_release(compositor);
2072 update_modifier_state(seat, serial, *k,
2073 WL_KEYBOARD_KEY_STATE_RELEASED);
2074 }
2075
2076 seat->modifier_state = 0;
2077
2078 if (keyboard->focus) {
2079 seat->saved_kbd_focus = keyboard->focus;
2080 seat->saved_kbd_focus_listener.notify =
2081 destroy_device_saved_kbd_focus;
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05002082 wl_signal_add(&keyboard->focus->destroy_signal,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002083 &seat->saved_kbd_focus_listener);
2084 }
2085
2086 weston_keyboard_set_focus(keyboard, NULL);
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02002087 weston_keyboard_cancel_grab(keyboard);
Derek Foreman1281a362015-07-31 16:55:32 -05002088 if (pointer)
2089 weston_pointer_cancel_grab(pointer);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002090}
2091
Michael Fua2bb7912013-07-23 15:51:06 +08002092WL_EXPORT void
Derek Foreman4c93c082015-04-30 16:45:41 -05002093weston_touch_set_focus(struct weston_touch *touch, struct weston_view *view)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002094{
Neil Roberts96d790e2013-09-19 17:32:00 +01002095 struct wl_list *focus_resource_list;
2096
Derek Foreman4c93c082015-04-30 16:45:41 -05002097 focus_resource_list = &touch->focus_resource_list;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002098
Derek Foreman4c93c082015-04-30 16:45:41 -05002099 if (view && touch->focus &&
2100 touch->focus->surface == view->surface) {
2101 touch->focus = view;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002102 return;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002103 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002104
Derek Foreman4c93c082015-04-30 16:45:41 -05002105 wl_list_remove(&touch->focus_resource_listener.link);
2106 wl_list_init(&touch->focus_resource_listener.link);
2107 wl_list_remove(&touch->focus_view_listener.link);
2108 wl_list_init(&touch->focus_view_listener.link);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01002109
Neil Roberts96d790e2013-09-19 17:32:00 +01002110 if (!wl_list_empty(focus_resource_list)) {
Derek Foreman4c93c082015-04-30 16:45:41 -05002111 move_resources(&touch->resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01002112 focus_resource_list);
2113 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002114
Jason Ekstranda7af7042013-10-12 22:38:11 -05002115 if (view) {
Derek Foreman362656b2014-09-04 10:23:05 -05002116 struct wl_client *surface_client;
2117
2118 if (!view->surface->resource) {
Derek Foreman4c93c082015-04-30 16:45:41 -05002119 touch->focus = NULL;
Derek Foreman362656b2014-09-04 10:23:05 -05002120 return;
2121 }
2122
2123 surface_client = wl_resource_get_client(view->surface->resource);
Neil Roberts96d790e2013-09-19 17:32:00 +01002124 move_resources_for_client(focus_resource_list,
Derek Foreman4c93c082015-04-30 16:45:41 -05002125 &touch->resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01002126 surface_client);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01002127 wl_resource_add_destroy_listener(view->surface->resource,
Derek Foreman4c93c082015-04-30 16:45:41 -05002128 &touch->focus_resource_listener);
2129 wl_signal_add(&view->destroy_signal, &touch->focus_view_listener);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002130 }
Derek Foreman4c93c082015-04-30 16:45:41 -05002131 touch->focus = view;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002132}
2133
2134/**
2135 * notify_touch - emulates button touches and notifies surfaces accordingly.
2136 *
2137 * It assumes always the correct cycle sequence until it gets here: touch_down
2138 * → touch_update → ... → touch_update → touch_end. The driver is responsible
2139 * for sending along such order.
2140 *
2141 */
2142WL_EXPORT void
2143notify_touch(struct weston_seat *seat, uint32_t time, int touch_id,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02002144 double double_x, double double_y, int touch_type)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002145{
2146 struct weston_compositor *ec = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05002147 struct weston_touch *touch = weston_seat_get_touch(seat);
Kristian Høgsberge329f362013-05-06 22:19:57 -04002148 struct weston_touch_grab *grab = touch->grab;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002149 struct weston_view *ev;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002150 wl_fixed_t sx, sy;
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02002151 wl_fixed_t x = wl_fixed_from_double(double_x);
2152 wl_fixed_t y = wl_fixed_from_double(double_y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002153
2154 /* Update grab's global coordinates. */
Neil Roberts306fe082013-10-03 16:43:06 +01002155 if (touch_id == touch->grab_touch_id && touch_type != WL_TOUCH_UP) {
2156 touch->grab_x = x;
2157 touch->grab_y = y;
2158 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002159
2160 switch (touch_type) {
2161 case WL_TOUCH_DOWN:
2162 weston_compositor_idle_inhibit(ec);
2163
Jonas Ådahl9484b692013-12-02 22:05:03 +01002164 touch->num_tp++;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002165
Jason Ekstranda7af7042013-10-12 22:38:11 -05002166 /* the first finger down picks the view, and all further go
2167 * to that view for the remainder of the touch session i.e.
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002168 * until all touch points are up again. */
Jonas Ådahl9484b692013-12-02 22:05:03 +01002169 if (touch->num_tp == 1) {
Jason Ekstranda7af7042013-10-12 22:38:11 -05002170 ev = weston_compositor_pick_view(ec, x, y, &sx, &sy);
Derek Foreman4c93c082015-04-30 16:45:41 -05002171 weston_touch_set_focus(touch, ev);
Giulio Camuffo61ed7b62015-07-08 11:55:28 +03002172 } else if (!touch->focus) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002173 /* Unexpected condition: We have non-initial touch but
2174 * there is no focused surface.
2175 */
Chris Michael3f607d32015-10-07 11:59:49 -04002176 weston_log("touch event received with %d points down "
Jonas Ådahl9484b692013-12-02 22:05:03 +01002177 "but no surface focused\n", touch->num_tp);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002178 return;
2179 }
2180
Derek Foreman99a6a2d2015-07-15 13:00:43 -05002181 weston_compositor_run_touch_binding(ec, touch,
Kristian Høgsbergc8964012014-02-05 14:25:18 -08002182 time, touch_type);
2183
Giulio Camuffo61ed7b62015-07-08 11:55:28 +03002184 grab->interface->down(grab, time, touch_id, x, y);
Jonas Ådahl9484b692013-12-02 22:05:03 +01002185 if (touch->num_tp == 1) {
Rusty Lynchf1407ff2013-08-08 21:13:57 -07002186 touch->grab_serial =
2187 wl_display_get_serial(ec->wl_display);
Neil Roberts306fe082013-10-03 16:43:06 +01002188 touch->grab_touch_id = touch_id;
Rusty Lynchf1407ff2013-08-08 21:13:57 -07002189 touch->grab_time = time;
2190 touch->grab_x = x;
2191 touch->grab_y = y;
2192 }
2193
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002194 break;
2195 case WL_TOUCH_MOTION:
Jason Ekstranda7af7042013-10-12 22:38:11 -05002196 ev = touch->focus;
2197 if (!ev)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002198 break;
2199
Giulio Camuffo61ed7b62015-07-08 11:55:28 +03002200 grab->interface->motion(grab, time, touch_id, x, y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002201 break;
2202 case WL_TOUCH_UP:
Kristian Høgsberga30e29a2014-01-08 22:29:20 -08002203 if (touch->num_tp == 0) {
2204 /* This can happen if we start out with one or
2205 * more fingers on the touch screen, in which
2206 * case we didn't get the corresponding down
2207 * event. */
2208 weston_log("unmatched touch up event\n");
2209 break;
2210 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002211 weston_compositor_idle_release(ec);
Jonas Ådahl9484b692013-12-02 22:05:03 +01002212 touch->num_tp--;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002213
2214 grab->interface->up(grab, time, touch_id);
Jonas Ådahl9484b692013-12-02 22:05:03 +01002215 if (touch->num_tp == 0)
Derek Foreman4c93c082015-04-30 16:45:41 -05002216 weston_touch_set_focus(touch, NULL);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002217 break;
2218 }
2219}
2220
Jonas Ådahl1679f232014-04-12 09:39:51 +02002221WL_EXPORT void
2222notify_touch_frame(struct weston_seat *seat)
2223{
Derek Foreman1281a362015-07-31 16:55:32 -05002224 struct weston_touch *touch = weston_seat_get_touch(seat);
Jonas Ådahl1679f232014-04-12 09:39:51 +02002225 struct weston_touch_grab *grab = touch->grab;
2226
2227 grab->interface->frame(grab);
2228}
2229
Derek Foreman3cc004a2015-11-06 15:56:09 -06002230WL_EXPORT void
2231notify_touch_cancel(struct weston_seat *seat)
2232{
2233 struct weston_touch *touch = weston_seat_get_touch(seat);
2234 struct weston_touch_grab *grab = touch->grab;
2235
2236 grab->interface->cancel(grab);
2237}
2238
Pekka Paalanen8274d902014-08-06 19:36:51 +03002239static int
2240pointer_cursor_surface_get_label(struct weston_surface *surface,
2241 char *buf, size_t len)
2242{
2243 return snprintf(buf, len, "cursor");
2244}
2245
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002246static void
Quentin Glidic2edc3d52016-08-12 10:41:33 +02002247pointer_cursor_surface_committed(struct weston_surface *es,
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06002248 int32_t dx, int32_t dy)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002249{
Quentin Glidic2edc3d52016-08-12 10:41:33 +02002250 struct weston_pointer *pointer = es->committed_private;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002251 int x, y;
2252
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06002253 if (es->width == 0)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002254 return;
2255
Jason Ekstranda7af7042013-10-12 22:38:11 -05002256 assert(es == pointer->sprite->surface);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002257
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002258 pointer->hotspot_x -= dx;
2259 pointer->hotspot_y -= dy;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002260
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002261 x = wl_fixed_to_int(pointer->x) - pointer->hotspot_x;
2262 y = wl_fixed_to_int(pointer->y) - pointer->hotspot_y;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002263
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06002264 weston_view_set_position(pointer->sprite, x, y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002265
2266 empty_region(&es->pending.input);
Ander Conselvan de Oliveira23900f72014-01-31 16:07:51 +02002267 empty_region(&es->input);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002268
2269 if (!weston_surface_is_mapped(es)) {
Giulio Camuffo412e6a52014-07-09 22:12:56 +03002270 weston_layer_entry_insert(&es->compositor->cursor_layer.view_list,
2271 &pointer->sprite->layer_link);
Jason Ekstranda7af7042013-10-12 22:38:11 -05002272 weston_view_update_transform(pointer->sprite);
Armin Krezovićf8486c32016-06-30 06:04:28 +02002273 es->is_mapped = true;
2274 pointer->sprite->is_mapped = true;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002275 }
2276}
2277
2278static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002279pointer_set_cursor(struct wl_client *client, struct wl_resource *resource,
2280 uint32_t serial, struct wl_resource *surface_resource,
2281 int32_t x, int32_t y)
2282{
Jason Ekstrand44a38632013-06-14 10:08:00 -05002283 struct weston_pointer *pointer = wl_resource_get_user_data(resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002284 struct weston_surface *surface = NULL;
2285
2286 if (surface_resource)
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05002287 surface = wl_resource_get_user_data(surface_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002288
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002289 if (pointer->focus == NULL)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002290 return;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002291 /* pointer->focus->surface->resource can be NULL. Surfaces like the
Giulio Camuffo1fd4b012013-06-20 18:13:07 +02002292 black_surface used in shell.c for fullscreen don't have
2293 a resource, but can still have focus */
Jason Ekstranda7af7042013-10-12 22:38:11 -05002294 if (pointer->focus->surface->resource == NULL)
Giulio Camuffo1fd4b012013-06-20 18:13:07 +02002295 return;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002296 if (wl_resource_get_client(pointer->focus->surface->resource) != client)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002297 return;
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002298 if (pointer->focus_serial - serial > UINT32_MAX / 2)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002299 return;
2300
Derek Foreman4e53c532015-03-23 10:55:32 -05002301 if (!surface) {
2302 if (pointer->sprite)
2303 pointer_unmap_sprite(pointer);
2304 return;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002305 }
2306
Jonas Ådahlb4070242015-03-18 15:08:03 +08002307 if (pointer->sprite && pointer->sprite->surface == surface &&
2308 pointer->hotspot_x == x && pointer->hotspot_y == y)
2309 return;
2310
Derek Foreman4e53c532015-03-23 10:55:32 -05002311 if (!pointer->sprite || pointer->sprite->surface != surface) {
2312 if (weston_surface_set_role(surface, "wl_pointer-cursor",
2313 resource,
2314 WL_POINTER_ERROR_ROLE) < 0)
2315 return;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002316
Derek Foreman4e53c532015-03-23 10:55:32 -05002317 if (pointer->sprite)
2318 pointer_unmap_sprite(pointer);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002319
Derek Foreman4e53c532015-03-23 10:55:32 -05002320 wl_signal_add(&surface->destroy_signal,
2321 &pointer->sprite_destroy_listener);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002322
Quentin Glidic2edc3d52016-08-12 10:41:33 +02002323 surface->committed = pointer_cursor_surface_committed;
2324 surface->committed_private = pointer;
Derek Foreman4e53c532015-03-23 10:55:32 -05002325 weston_surface_set_label_func(surface,
2326 pointer_cursor_surface_get_label);
2327 pointer->sprite = weston_view_create(surface);
2328 }
2329
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002330 pointer->hotspot_x = x;
2331 pointer->hotspot_y = y;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002332
Jonas Ådahl16fe4dc2014-09-08 19:33:41 +02002333 if (surface->buffer_ref.buffer) {
Quentin Glidic2edc3d52016-08-12 10:41:33 +02002334 pointer_cursor_surface_committed(surface, 0, 0);
Jonas Ådahl16fe4dc2014-09-08 19:33:41 +02002335 weston_view_schedule_repaint(pointer->sprite);
2336 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002337}
2338
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002339static void
2340pointer_release(struct wl_client *client, struct wl_resource *resource)
2341{
2342 wl_resource_destroy(resource);
2343}
2344
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002345static const struct wl_pointer_interface pointer_interface = {
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002346 pointer_set_cursor,
2347 pointer_release
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002348};
2349
2350static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002351seat_get_pointer(struct wl_client *client, struct wl_resource *resource,
2352 uint32_t id)
2353{
Jason Ekstrand44a38632013-06-14 10:08:00 -05002354 struct weston_seat *seat = wl_resource_get_user_data(resource);
Derek Foreman1281a362015-07-31 16:55:32 -05002355 /* We use the pointer_state directly, which means we'll
2356 * give a wl_pointer if the seat has ever had one - even though
2357 * the spec explicitly states that this request only takes effect
2358 * if the seat has the pointer capability.
2359 *
2360 * This prevents a race between the compositor sending new
2361 * capabilities and the client trying to use the old ones.
2362 */
2363 struct weston_pointer *pointer = seat->pointer_state;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002364 struct wl_resource *cr;
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08002365 struct weston_pointer_client *pointer_client;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002366
Derek Foreman1281a362015-07-31 16:55:32 -05002367 if (!pointer)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002368 return;
2369
Jason Ekstranda85118c2013-06-27 20:17:02 -05002370 cr = wl_resource_create(client, &wl_pointer_interface,
2371 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07002372 if (cr == NULL) {
2373 wl_client_post_no_memory(client);
2374 return;
2375 }
2376
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08002377 pointer_client = weston_pointer_ensure_pointer_client(pointer, client);
2378 if (!pointer_client) {
2379 wl_client_post_no_memory(client);
2380 return;
2381 }
2382
2383 wl_list_insert(&pointer_client->pointer_resources,
2384 wl_resource_get_link(cr));
Derek Foreman1281a362015-07-31 16:55:32 -05002385 wl_resource_set_implementation(cr, &pointer_interface, pointer,
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08002386 unbind_pointer_client_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002387
Derek Foreman1281a362015-07-31 16:55:32 -05002388 if (pointer->focus && pointer->focus->surface->resource &&
2389 wl_resource_get_client(pointer->focus->surface->resource) == client) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002390 wl_fixed_t sx, sy;
2391
Derek Foreman1281a362015-07-31 16:55:32 -05002392 weston_view_from_global_fixed(pointer->focus,
2393 pointer->x,
2394 pointer->y,
Jason Ekstranda7af7042013-10-12 22:38:11 -05002395 &sx, &sy);
Neil Roberts96d790e2013-09-19 17:32:00 +01002396
Neil Roberts96d790e2013-09-19 17:32:00 +01002397 wl_pointer_send_enter(cr,
Derek Foreman1281a362015-07-31 16:55:32 -05002398 pointer->focus_serial,
2399 pointer->focus->surface->resource,
Neil Roberts96d790e2013-09-19 17:32:00 +01002400 sx, sy);
Peter Hutterer87743e92016-01-18 16:38:22 +10002401 pointer_send_frame(cr);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002402 }
2403}
2404
2405static void
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002406keyboard_release(struct wl_client *client, struct wl_resource *resource)
2407{
2408 wl_resource_destroy(resource);
2409}
2410
2411static const struct wl_keyboard_interface keyboard_interface = {
2412 keyboard_release
2413};
2414
Derek Foreman280e7dd2014-10-03 13:13:42 -05002415static bool
Neil Roberts96d790e2013-09-19 17:32:00 +01002416should_send_modifiers_to_client(struct weston_seat *seat,
2417 struct wl_client *client)
2418{
Derek Foreman1281a362015-07-31 16:55:32 -05002419 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
2420 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
2421
2422 if (keyboard &&
2423 keyboard->focus &&
2424 keyboard->focus->resource &&
2425 wl_resource_get_client(keyboard->focus->resource) == client)
Derek Foreman280e7dd2014-10-03 13:13:42 -05002426 return true;
Neil Roberts96d790e2013-09-19 17:32:00 +01002427
Derek Foreman1281a362015-07-31 16:55:32 -05002428 if (pointer &&
2429 pointer->focus &&
2430 pointer->focus->surface->resource &&
2431 wl_resource_get_client(pointer->focus->surface->resource) == client)
Derek Foreman280e7dd2014-10-03 13:13:42 -05002432 return true;
Neil Roberts96d790e2013-09-19 17:32:00 +01002433
Derek Foreman280e7dd2014-10-03 13:13:42 -05002434 return false;
Neil Roberts96d790e2013-09-19 17:32:00 +01002435}
2436
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002437static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002438seat_get_keyboard(struct wl_client *client, struct wl_resource *resource,
2439 uint32_t id)
2440{
Jason Ekstrand44a38632013-06-14 10:08:00 -05002441 struct weston_seat *seat = wl_resource_get_user_data(resource);
Derek Foreman1281a362015-07-31 16:55:32 -05002442 /* We use the keyboard_state directly, which means we'll
2443 * give a wl_keyboard if the seat has ever had one - even though
2444 * the spec explicitly states that this request only takes effect
2445 * if the seat has the keyboard capability.
2446 *
2447 * This prevents a race between the compositor sending new
2448 * capabilities and the client trying to use the old ones.
2449 */
2450 struct weston_keyboard *keyboard = seat->keyboard_state;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002451 struct wl_resource *cr;
2452
Derek Foreman345c9f32015-06-03 15:53:28 -05002453 if (!keyboard)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002454 return;
2455
Jason Ekstranda85118c2013-06-27 20:17:02 -05002456 cr = wl_resource_create(client, &wl_keyboard_interface,
2457 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07002458 if (cr == NULL) {
2459 wl_client_post_no_memory(client);
2460 return;
2461 }
2462
Neil Roberts96d790e2013-09-19 17:32:00 +01002463 /* May be moved to focused list later by either
2464 * weston_keyboard_set_focus or directly if this client is already
2465 * focused */
Derek Foreman345c9f32015-06-03 15:53:28 -05002466 wl_list_insert(&keyboard->resource_list, wl_resource_get_link(cr));
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002467 wl_resource_set_implementation(cr, &keyboard_interface,
2468 seat, unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002469
Jonny Lamb66a41a02014-08-12 14:58:25 +02002470 if (wl_resource_get_version(cr) >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) {
2471 wl_keyboard_send_repeat_info(cr,
2472 seat->compositor->kb_repeat_rate,
2473 seat->compositor->kb_repeat_delay);
2474 }
Jasper St. Pierred8c6aeb2014-08-04 13:43:24 -04002475
Derek Foreman185d1582017-06-28 11:17:23 -05002476 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
2477 keyboard->xkb_info->keymap_fd,
2478 keyboard->xkb_info->keymap_size);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002479
Neil Roberts96d790e2013-09-19 17:32:00 +01002480 if (should_send_modifiers_to_client(seat, client)) {
Derek Foreman345c9f32015-06-03 15:53:28 -05002481 send_modifiers_to_resource(keyboard,
Neil Roberts96d790e2013-09-19 17:32:00 +01002482 cr,
Derek Foreman345c9f32015-06-03 15:53:28 -05002483 keyboard->focus_serial);
Neil Roberts96d790e2013-09-19 17:32:00 +01002484 }
2485
Derek Foreman345c9f32015-06-03 15:53:28 -05002486 if (keyboard->focus && keyboard->focus->resource &&
2487 wl_resource_get_client(keyboard->focus->resource) == client) {
Neil Roberts96d790e2013-09-19 17:32:00 +01002488 struct weston_surface *surface =
Derek Foreman345c9f32015-06-03 15:53:28 -05002489 (struct weston_surface *)keyboard->focus;
Neil Roberts96d790e2013-09-19 17:32:00 +01002490
2491 wl_list_remove(wl_resource_get_link(cr));
Derek Foreman345c9f32015-06-03 15:53:28 -05002492 wl_list_insert(&keyboard->focus_resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01002493 wl_resource_get_link(cr));
2494 wl_keyboard_send_enter(cr,
Derek Foreman345c9f32015-06-03 15:53:28 -05002495 keyboard->focus_serial,
Neil Roberts96d790e2013-09-19 17:32:00 +01002496 surface->resource,
Derek Foreman345c9f32015-06-03 15:53:28 -05002497 &keyboard->keys);
Neil Roberts96d790e2013-09-19 17:32:00 +01002498
2499 /* If this is the first keyboard resource for this
2500 * client... */
Derek Foreman345c9f32015-06-03 15:53:28 -05002501 if (keyboard->focus_resource_list.prev ==
Neil Roberts96d790e2013-09-19 17:32:00 +01002502 wl_resource_get_link(cr))
2503 wl_data_device_set_keyboard_focus(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002504 }
2505}
2506
2507static void
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002508touch_release(struct wl_client *client, struct wl_resource *resource)
2509{
2510 wl_resource_destroy(resource);
2511}
2512
2513static const struct wl_touch_interface touch_interface = {
2514 touch_release
2515};
2516
2517static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002518seat_get_touch(struct wl_client *client, struct wl_resource *resource,
2519 uint32_t id)
2520{
Jason Ekstrand44a38632013-06-14 10:08:00 -05002521 struct weston_seat *seat = wl_resource_get_user_data(resource);
Derek Foreman1281a362015-07-31 16:55:32 -05002522 /* We use the touch_state directly, which means we'll
2523 * give a wl_touch if the seat has ever had one - even though
2524 * the spec explicitly states that this request only takes effect
2525 * if the seat has the touch capability.
2526 *
2527 * This prevents a race between the compositor sending new
2528 * capabilities and the client trying to use the old ones.
2529 */
2530 struct weston_touch *touch = seat->touch_state;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002531 struct wl_resource *cr;
2532
Derek Foreman1281a362015-07-31 16:55:32 -05002533 if (!touch)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002534 return;
2535
Jason Ekstranda85118c2013-06-27 20:17:02 -05002536 cr = wl_resource_create(client, &wl_touch_interface,
2537 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07002538 if (cr == NULL) {
2539 wl_client_post_no_memory(client);
2540 return;
2541 }
2542
Derek Foreman1281a362015-07-31 16:55:32 -05002543 if (touch->focus &&
2544 wl_resource_get_client(touch->focus->surface->resource) == client) {
Chokshi, Mituld6697142015-10-09 08:28:47 +00002545 wl_list_insert(&touch->focus_resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01002546 wl_resource_get_link(cr));
2547 } else {
Chokshi, Mituld6697142015-10-09 08:28:47 +00002548 wl_list_insert(&touch->resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01002549 wl_resource_get_link(cr));
2550 }
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002551 wl_resource_set_implementation(cr, &touch_interface,
2552 seat, unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002553}
2554
Quentin Glidicaab1d362016-03-13 17:49:08 +01002555static void
2556seat_release(struct wl_client *client, struct wl_resource *resource)
2557{
2558 wl_resource_destroy(resource);
2559}
2560
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002561static const struct wl_seat_interface seat_interface = {
2562 seat_get_pointer,
2563 seat_get_keyboard,
2564 seat_get_touch,
Quentin Glidicaab1d362016-03-13 17:49:08 +01002565 seat_release,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002566};
2567
2568static void
2569bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
2570{
Kristian Høgsberge3148752013-05-06 23:19:49 -04002571 struct weston_seat *seat = data;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002572 struct wl_resource *resource;
2573 enum wl_seat_capability caps = 0;
2574
Jason Ekstranda85118c2013-06-27 20:17:02 -05002575 resource = wl_resource_create(client,
Derek Foreman1909c102015-11-26 14:17:47 -06002576 &wl_seat_interface, version, id);
Jason Ekstrand44a38632013-06-14 10:08:00 -05002577 wl_list_insert(&seat->base_resource_list, wl_resource_get_link(resource));
Jason Ekstranda85118c2013-06-27 20:17:02 -05002578 wl_resource_set_implementation(resource, &seat_interface, data,
2579 unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002580
Derek Foreman1281a362015-07-31 16:55:32 -05002581 if (weston_seat_get_pointer(seat))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002582 caps |= WL_SEAT_CAPABILITY_POINTER;
Derek Foreman1281a362015-07-31 16:55:32 -05002583 if (weston_seat_get_keyboard(seat))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002584 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
Derek Foreman1281a362015-07-31 16:55:32 -05002585 if (weston_seat_get_touch(seat))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002586 caps |= WL_SEAT_CAPABILITY_TOUCH;
2587
2588 wl_seat_send_capabilities(resource, caps);
Jasper St. Pierre0013a292014-08-07 16:43:11 -04002589 if (version >= WL_SEAT_NAME_SINCE_VERSION)
Rob Bradforde445ae62013-05-31 18:09:51 +01002590 wl_seat_send_name(resource, seat->seat_name);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002591}
2592
Jonas Ådahl30d61d82014-10-22 21:21:17 +02002593static void
2594relative_pointer_destroy(struct wl_client *client,
2595 struct wl_resource *resource)
2596{
2597 wl_resource_destroy(resource);
2598}
2599
2600static const struct zwp_relative_pointer_v1_interface relative_pointer_interface = {
2601 relative_pointer_destroy
2602};
2603
2604static void
2605relative_pointer_manager_destroy(struct wl_client *client,
2606 struct wl_resource *resource)
2607{
2608 wl_resource_destroy(resource);
2609}
2610
2611static void
2612relative_pointer_manager_get_relative_pointer(struct wl_client *client,
2613 struct wl_resource *resource,
2614 uint32_t id,
2615 struct wl_resource *pointer_resource)
2616{
2617 struct weston_pointer *pointer =
2618 wl_resource_get_user_data(pointer_resource);
2619 struct weston_pointer_client *pointer_client;
2620 struct wl_resource *cr;
2621
2622 cr = wl_resource_create(client, &zwp_relative_pointer_v1_interface,
2623 wl_resource_get_version(resource), id);
2624 if (cr == NULL) {
2625 wl_client_post_no_memory(client);
2626 return;
2627 }
2628
2629 pointer_client = weston_pointer_ensure_pointer_client(pointer, client);
2630 if (!pointer_client) {
2631 wl_client_post_no_memory(client);
2632 return;
2633 }
2634
2635 wl_list_insert(&pointer_client->relative_pointer_resources,
2636 wl_resource_get_link(cr));
2637 wl_resource_set_implementation(cr, &relative_pointer_interface,
2638 pointer,
2639 unbind_pointer_client_resource);
2640}
2641
2642static const struct zwp_relative_pointer_manager_v1_interface relative_pointer_manager = {
2643 relative_pointer_manager_destroy,
2644 relative_pointer_manager_get_relative_pointer,
2645};
2646
2647static void
2648bind_relative_pointer_manager(struct wl_client *client, void *data,
2649 uint32_t version, uint32_t id)
2650{
2651 struct weston_compositor *compositor = data;
2652 struct wl_resource *resource;
2653
2654 resource = wl_resource_create(client,
2655 &zwp_relative_pointer_manager_v1_interface,
2656 1, id);
2657
2658 wl_resource_set_implementation(resource, &relative_pointer_manager,
2659 compositor,
2660 NULL);
2661}
2662
Giulio Camuffo0358af42016-06-02 21:48:08 +03002663WL_EXPORT int
2664weston_compositor_set_xkb_rule_names(struct weston_compositor *ec,
2665 struct xkb_rule_names *names)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002666{
2667 if (ec->xkb_context == NULL) {
2668 ec->xkb_context = xkb_context_new(0);
2669 if (ec->xkb_context == NULL) {
2670 weston_log("failed to create XKB context\n");
2671 return -1;
2672 }
2673 }
2674
2675 if (names)
2676 ec->xkb_names = *names;
2677 if (!ec->xkb_names.rules)
2678 ec->xkb_names.rules = strdup("evdev");
2679 if (!ec->xkb_names.model)
2680 ec->xkb_names.model = strdup("pc105");
2681 if (!ec->xkb_names.layout)
2682 ec->xkb_names.layout = strdup("us");
2683
2684 return 0;
2685}
2686
Stefan Schmidtfda26522013-09-17 10:54:09 +01002687static void
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002688weston_xkb_info_destroy(struct weston_xkb_info *xkb_info)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002689{
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002690 if (--xkb_info->ref_count > 0)
2691 return;
2692
Ran Benitac9c74152014-08-19 23:59:52 +03002693 xkb_keymap_unref(xkb_info->keymap);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002694
2695 if (xkb_info->keymap_area)
2696 munmap(xkb_info->keymap_area, xkb_info->keymap_size);
2697 if (xkb_info->keymap_fd >= 0)
2698 close(xkb_info->keymap_fd);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002699 free(xkb_info);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002700}
2701
2702void
2703weston_compositor_xkb_destroy(struct weston_compositor *ec)
2704{
2705 free((char *) ec->xkb_names.rules);
2706 free((char *) ec->xkb_names.model);
2707 free((char *) ec->xkb_names.layout);
2708 free((char *) ec->xkb_names.variant);
2709 free((char *) ec->xkb_names.options);
Stefan Schmidtfda26522013-09-17 10:54:09 +01002710
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002711 if (ec->xkb_info)
2712 weston_xkb_info_destroy(ec->xkb_info);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002713 xkb_context_unref(ec->xkb_context);
2714}
2715
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002716static struct weston_xkb_info *
2717weston_xkb_info_create(struct xkb_keymap *keymap)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002718{
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002719 struct weston_xkb_info *xkb_info = zalloc(sizeof *xkb_info);
2720 if (xkb_info == NULL)
2721 return NULL;
2722
Ran Benita2e1968f2014-08-19 23:59:51 +03002723 xkb_info->keymap = xkb_keymap_ref(keymap);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002724 xkb_info->ref_count = 1;
2725
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002726 char *keymap_str;
2727
Ran Benita2e1968f2014-08-19 23:59:51 +03002728 xkb_info->shift_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2729 XKB_MOD_NAME_SHIFT);
2730 xkb_info->caps_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2731 XKB_MOD_NAME_CAPS);
2732 xkb_info->ctrl_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2733 XKB_MOD_NAME_CTRL);
2734 xkb_info->alt_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2735 XKB_MOD_NAME_ALT);
2736 xkb_info->mod2_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2737 "Mod2");
2738 xkb_info->mod3_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2739 "Mod3");
2740 xkb_info->super_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2741 XKB_MOD_NAME_LOGO);
2742 xkb_info->mod5_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2743 "Mod5");
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002744
Ran Benita2e1968f2014-08-19 23:59:51 +03002745 xkb_info->num_led = xkb_keymap_led_get_index(xkb_info->keymap,
2746 XKB_LED_NAME_NUM);
2747 xkb_info->caps_led = xkb_keymap_led_get_index(xkb_info->keymap,
2748 XKB_LED_NAME_CAPS);
2749 xkb_info->scroll_led = xkb_keymap_led_get_index(xkb_info->keymap,
2750 XKB_LED_NAME_SCROLL);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002751
Ran Benita2e1968f2014-08-19 23:59:51 +03002752 keymap_str = xkb_keymap_get_as_string(xkb_info->keymap,
2753 XKB_KEYMAP_FORMAT_TEXT_V1);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002754 if (keymap_str == NULL) {
2755 weston_log("failed to get string version of keymap\n");
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002756 goto err_keymap;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002757 }
2758 xkb_info->keymap_size = strlen(keymap_str) + 1;
2759
2760 xkb_info->keymap_fd = os_create_anonymous_file(xkb_info->keymap_size);
2761 if (xkb_info->keymap_fd < 0) {
2762 weston_log("creating a keymap file for %lu bytes failed: %m\n",
2763 (unsigned long) xkb_info->keymap_size);
2764 goto err_keymap_str;
2765 }
2766
2767 xkb_info->keymap_area = mmap(NULL, xkb_info->keymap_size,
2768 PROT_READ | PROT_WRITE,
2769 MAP_SHARED, xkb_info->keymap_fd, 0);
2770 if (xkb_info->keymap_area == MAP_FAILED) {
2771 weston_log("failed to mmap() %lu bytes\n",
2772 (unsigned long) xkb_info->keymap_size);
2773 goto err_dev_zero;
2774 }
2775 strcpy(xkb_info->keymap_area, keymap_str);
2776 free(keymap_str);
2777
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002778 return xkb_info;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002779
2780err_dev_zero:
2781 close(xkb_info->keymap_fd);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002782err_keymap_str:
2783 free(keymap_str);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002784err_keymap:
Ran Benita2e1968f2014-08-19 23:59:51 +03002785 xkb_keymap_unref(xkb_info->keymap);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002786 free(xkb_info);
2787 return NULL;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002788}
2789
2790static int
2791weston_compositor_build_global_keymap(struct weston_compositor *ec)
2792{
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002793 struct xkb_keymap *keymap;
2794
2795 if (ec->xkb_info != NULL)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002796 return 0;
2797
Ran Benita2e1968f2014-08-19 23:59:51 +03002798 keymap = xkb_keymap_new_from_names(ec->xkb_context,
2799 &ec->xkb_names,
2800 0);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002801 if (keymap == NULL) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002802 weston_log("failed to compile global XKB keymap\n");
2803 weston_log(" tried rules %s, model %s, layout %s, variant %s, "
2804 "options %s\n",
2805 ec->xkb_names.rules, ec->xkb_names.model,
2806 ec->xkb_names.layout, ec->xkb_names.variant,
2807 ec->xkb_names.options);
2808 return -1;
2809 }
2810
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002811 ec->xkb_info = weston_xkb_info_create(keymap);
Rui Matos73d93952013-10-24 19:28:41 +02002812 xkb_keymap_unref(keymap);
Stefan Schmidtfda26522013-09-17 10:54:09 +01002813 if (ec->xkb_info == NULL)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002814 return -1;
2815
2816 return 0;
2817}
2818
Rui Matos65196bc2013-10-10 19:44:19 +02002819WL_EXPORT void
2820weston_seat_update_keymap(struct weston_seat *seat, struct xkb_keymap *keymap)
2821{
Derek Foreman1281a362015-07-31 16:55:32 -05002822 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
2823
2824 if (!keyboard || !keymap)
Rui Matos65196bc2013-10-10 19:44:19 +02002825 return;
2826
Derek Foreman1281a362015-07-31 16:55:32 -05002827 xkb_keymap_unref(keyboard->pending_keymap);
2828 keyboard->pending_keymap = xkb_keymap_ref(keymap);
Rui Matos65196bc2013-10-10 19:44:19 +02002829
Derek Foreman1281a362015-07-31 16:55:32 -05002830 if (keyboard->keys.size == 0)
Rui Matos65196bc2013-10-10 19:44:19 +02002831 update_keymap(seat);
Rui Matos65196bc2013-10-10 19:44:19 +02002832}
2833
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002834WL_EXPORT int
2835weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap)
2836{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002837 struct weston_keyboard *keyboard;
2838
Derek Foreman1281a362015-07-31 16:55:32 -05002839 if (seat->keyboard_state) {
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002840 seat->keyboard_device_count += 1;
2841 if (seat->keyboard_device_count == 1)
2842 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002843 return 0;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002844 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002845
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002846 keyboard = weston_keyboard_create();
2847 if (keyboard == NULL) {
2848 weston_log("failed to allocate weston keyboard struct\n");
2849 return -1;
2850 }
2851
Derek Foreman185d1582017-06-28 11:17:23 -05002852 if (keymap != NULL) {
2853 keyboard->xkb_info = weston_xkb_info_create(keymap);
2854 if (keyboard->xkb_info == NULL)
Ander Conselvan de Oliveira4d363cf2014-01-31 17:35:45 +02002855 goto err;
Derek Foreman185d1582017-06-28 11:17:23 -05002856 } else {
2857 if (weston_compositor_build_global_keymap(seat->compositor) < 0)
2858 goto err;
2859 keyboard->xkb_info = seat->compositor->xkb_info;
2860 keyboard->xkb_info->ref_count++;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002861 }
Derek Foreman185d1582017-06-28 11:17:23 -05002862
2863 keyboard->xkb_state.state = xkb_state_new(keyboard->xkb_info->keymap);
2864 if (keyboard->xkb_state.state == NULL) {
2865 weston_log("failed to initialise XKB state\n");
2866 goto err;
2867 }
2868
2869 keyboard->xkb_state.leds = 0;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002870
Derek Foreman1281a362015-07-31 16:55:32 -05002871 seat->keyboard_state = keyboard;
Ander Conselvan de Oliveira4d363cf2014-01-31 17:35:45 +02002872 seat->keyboard_device_count = 1;
2873 keyboard->seat = seat;
2874
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002875 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002876
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002877 return 0;
Ander Conselvan de Oliveira4d363cf2014-01-31 17:35:45 +02002878
2879err:
2880 if (keyboard->xkb_info)
2881 weston_xkb_info_destroy(keyboard->xkb_info);
2882 free(keyboard);
2883
2884 return -1;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002885}
2886
Jonas Ådahl91fed542013-12-03 09:14:27 +01002887static void
2888weston_keyboard_reset_state(struct weston_keyboard *keyboard)
2889{
2890 struct weston_seat *seat = keyboard->seat;
2891 struct xkb_state *state;
2892
Derek Foreman185d1582017-06-28 11:17:23 -05002893 state = xkb_state_new(keyboard->xkb_info->keymap);
2894 if (!state) {
2895 weston_log("failed to reset XKB state\n");
2896 return;
Jonas Ådahl91fed542013-12-03 09:14:27 +01002897 }
Derek Foreman185d1582017-06-28 11:17:23 -05002898 xkb_state_unref(keyboard->xkb_state.state);
2899 keyboard->xkb_state.state = state;
2900
2901 keyboard->xkb_state.leds = 0;
Jonas Ådahl91fed542013-12-03 09:14:27 +01002902
2903 seat->modifier_state = 0;
2904}
2905
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002906WL_EXPORT void
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002907weston_seat_release_keyboard(struct weston_seat *seat)
2908{
2909 seat->keyboard_device_count--;
Derek Foremand621df22014-11-19 11:04:12 -06002910 assert(seat->keyboard_device_count >= 0);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002911 if (seat->keyboard_device_count == 0) {
Derek Foreman1281a362015-07-31 16:55:32 -05002912 weston_keyboard_set_focus(seat->keyboard_state, NULL);
2913 weston_keyboard_cancel_grab(seat->keyboard_state);
2914 weston_keyboard_reset_state(seat->keyboard_state);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002915 seat_send_updated_caps(seat);
2916 }
2917}
2918
2919WL_EXPORT void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002920weston_seat_init_pointer(struct weston_seat *seat)
2921{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002922 struct weston_pointer *pointer;
2923
Derek Foreman1281a362015-07-31 16:55:32 -05002924 if (seat->pointer_state) {
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002925 seat->pointer_device_count += 1;
2926 if (seat->pointer_device_count == 1)
2927 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002928 return;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002929 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002930
Giulio Camuffocdb4d292013-11-14 23:42:53 +01002931 pointer = weston_pointer_create(seat);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002932 if (pointer == NULL)
2933 return;
2934
Derek Foreman1281a362015-07-31 16:55:32 -05002935 seat->pointer_state = pointer;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002936 seat->pointer_device_count = 1;
2937 pointer->seat = seat;
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002938
2939 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002940}
2941
2942WL_EXPORT void
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002943weston_seat_release_pointer(struct weston_seat *seat)
2944{
Derek Foreman1281a362015-07-31 16:55:32 -05002945 struct weston_pointer *pointer = seat->pointer_state;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002946
2947 seat->pointer_device_count--;
2948 if (seat->pointer_device_count == 0) {
Derek Foremanf9318d12015-05-11 15:40:11 -05002949 weston_pointer_clear_focus(pointer);
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02002950 weston_pointer_cancel_grab(pointer);
Jonas Ådahl630bae82013-10-17 23:04:06 +02002951
Jonas Ådahla4932742013-10-17 23:04:07 +02002952 if (pointer->sprite)
2953 pointer_unmap_sprite(pointer);
2954
Jonas Ådahl3e12e632013-12-02 22:05:05 +01002955 weston_pointer_reset_state(pointer);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002956 seat_send_updated_caps(seat);
Derek Foremanfd5ca512015-01-07 15:00:25 -06002957
2958 /* seat->pointer is intentionally not destroyed so that
2959 * a newly attached pointer on this seat will retain
2960 * the previous cursor co-ordinates.
2961 */
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002962 }
2963}
2964
2965WL_EXPORT void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002966weston_seat_init_touch(struct weston_seat *seat)
2967{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002968 struct weston_touch *touch;
2969
Derek Foreman1281a362015-07-31 16:55:32 -05002970 if (seat->touch_state) {
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002971 seat->touch_device_count += 1;
2972 if (seat->touch_device_count == 1)
2973 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002974 return;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002975 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002976
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002977 touch = weston_touch_create();
2978 if (touch == NULL)
2979 return;
2980
Derek Foreman1281a362015-07-31 16:55:32 -05002981 seat->touch_state = touch;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002982 seat->touch_device_count = 1;
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002983 touch->seat = seat;
2984
2985 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002986}
2987
2988WL_EXPORT void
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002989weston_seat_release_touch(struct weston_seat *seat)
2990{
2991 seat->touch_device_count--;
2992 if (seat->touch_device_count == 0) {
Derek Foreman1281a362015-07-31 16:55:32 -05002993 weston_touch_set_focus(seat->touch_state, NULL);
2994 weston_touch_cancel_grab(seat->touch_state);
2995 weston_touch_reset_state(seat->touch_state);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002996 seat_send_updated_caps(seat);
2997 }
2998}
2999
3000WL_EXPORT void
Rob Bradford9af5f9e2013-05-31 18:09:50 +01003001weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec,
3002 const char *seat_name)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003003{
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04003004 memset(seat, 0, sizeof *seat);
3005
Kristian Høgsberge3148752013-05-06 23:19:49 -04003006 seat->selection_data_source = NULL;
3007 wl_list_init(&seat->base_resource_list);
3008 wl_signal_init(&seat->selection_signal);
3009 wl_list_init(&seat->drag_resource_list);
Kristian Høgsberge3148752013-05-06 23:19:49 -04003010 wl_signal_init(&seat->destroy_signal);
Jason Ekstranda4ab5422014-04-02 19:53:45 -05003011 wl_signal_init(&seat->updated_caps_signal);
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04003012
Peter Hutterer87743e92016-01-18 16:38:22 +10003013 seat->global = wl_global_create(ec->wl_display, &wl_seat_interface, 5,
Kristian Høgsberg919cddb2013-07-08 19:03:57 -04003014 seat, bind_seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003015
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003016 seat->compositor = ec;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003017 seat->modifier_state = 0;
Rob Bradford9af5f9e2013-05-31 18:09:50 +01003018 seat->seat_name = strdup(seat_name);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003019
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003020 wl_list_insert(ec->seat_list.prev, &seat->link);
3021
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003022 clipboard_create(seat);
3023
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003024 wl_signal_emit(&ec->seat_created_signal, seat);
3025}
3026
3027WL_EXPORT void
3028weston_seat_release(struct weston_seat *seat)
3029{
3030 wl_list_remove(&seat->link);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003031
Jonas Ådahl1afb2382014-01-03 19:46:51 +01003032 if (seat->saved_kbd_focus)
3033 wl_list_remove(&seat->saved_kbd_focus_listener.link);
3034
Derek Foreman1281a362015-07-31 16:55:32 -05003035 if (seat->pointer_state)
3036 weston_pointer_destroy(seat->pointer_state);
3037 if (seat->keyboard_state)
3038 weston_keyboard_destroy(seat->keyboard_state);
3039 if (seat->touch_state)
3040 weston_touch_destroy(seat->touch_state);
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04003041
Rob Bradford9af5f9e2013-05-31 18:09:50 +01003042 free (seat->seat_name);
3043
Kristian Høgsberg919cddb2013-07-08 19:03:57 -04003044 wl_global_destroy(seat->global);
Kristian Høgsbergaaadc772013-07-08 16:20:31 -04003045
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003046 wl_signal_emit(&seat->destroy_signal, seat);
3047}
Derek Foreman1281a362015-07-31 16:55:32 -05003048
3049/** Get a seat's keyboard pointer
3050 *
3051 * \param seat The seat to query
3052 * \return The seat's keyboard pointer, or NULL if no keyboard is present
3053 *
3054 * The keyboard pointer for a seat isn't freed when all keyboards are removed,
3055 * so it should only be used when the seat's keyboard_device_count is greater
3056 * than zero. This function does that test and only returns a pointer
3057 * when a keyboard is present.
3058 */
3059WL_EXPORT struct weston_keyboard *
3060weston_seat_get_keyboard(struct weston_seat *seat)
3061{
3062 if (!seat)
3063 return NULL;
3064
3065 if (seat->keyboard_device_count)
3066 return seat->keyboard_state;
3067
3068 return NULL;
3069}
3070
3071/** Get a seat's pointer pointer
3072 *
3073 * \param seat The seat to query
3074 * \return The seat's pointer pointer, or NULL if no pointer device is present
3075 *
3076 * The pointer pointer for a seat isn't freed when all mice are removed,
3077 * so it should only be used when the seat's pointer_device_count is greater
3078 * than zero. This function does that test and only returns a pointer
3079 * when a pointing device is present.
3080 */
3081WL_EXPORT struct weston_pointer *
3082weston_seat_get_pointer(struct weston_seat *seat)
3083{
3084 if (!seat)
3085 return NULL;
3086
3087 if (seat->pointer_device_count)
3088 return seat->pointer_state;
3089
3090 return NULL;
3091}
3092
Jonas Ådahld3414f22016-07-22 17:56:31 +08003093static const struct zwp_locked_pointer_v1_interface locked_pointer_interface;
3094static const struct zwp_confined_pointer_v1_interface confined_pointer_interface;
3095
3096static enum pointer_constraint_type
3097pointer_constraint_get_type(struct weston_pointer_constraint *constraint)
3098{
3099 if (wl_resource_instance_of(constraint->resource,
3100 &zwp_locked_pointer_v1_interface,
3101 &locked_pointer_interface)) {
3102 return POINTER_CONSTRAINT_TYPE_LOCK;
3103 } else if (wl_resource_instance_of(constraint->resource,
3104 &zwp_confined_pointer_v1_interface,
3105 &confined_pointer_interface)) {
3106 return POINTER_CONSTRAINT_TYPE_CONFINE;
3107 }
3108
3109 abort();
3110 return 0;
3111}
3112
3113static void
3114pointer_constraint_notify_activated(struct weston_pointer_constraint *constraint)
3115{
3116 struct wl_resource *resource = constraint->resource;
3117
3118 switch (pointer_constraint_get_type(constraint)) {
3119 case POINTER_CONSTRAINT_TYPE_LOCK:
3120 zwp_locked_pointer_v1_send_locked(resource);
3121 break;
3122 case POINTER_CONSTRAINT_TYPE_CONFINE:
3123 zwp_confined_pointer_v1_send_confined(resource);
3124 break;
3125 }
3126}
3127
3128static void
3129pointer_constraint_notify_deactivated(struct weston_pointer_constraint *constraint)
3130{
3131 struct wl_resource *resource = constraint->resource;
3132
3133 switch (pointer_constraint_get_type(constraint)) {
3134 case POINTER_CONSTRAINT_TYPE_LOCK:
3135 zwp_locked_pointer_v1_send_unlocked(resource);
3136 break;
3137 case POINTER_CONSTRAINT_TYPE_CONFINE:
3138 zwp_confined_pointer_v1_send_unconfined(resource);
3139 break;
3140 }
3141}
3142
3143static struct weston_pointer_constraint *
3144get_pointer_constraint_for_pointer(struct weston_surface *surface,
3145 struct weston_pointer *pointer)
3146{
3147 struct weston_pointer_constraint *constraint;
3148
3149 wl_list_for_each(constraint, &surface->pointer_constraints, link) {
3150 if (constraint->pointer == pointer)
3151 return constraint;
3152 }
3153
3154 return NULL;
3155}
3156
Derek Foreman1281a362015-07-31 16:55:32 -05003157/** Get a seat's touch pointer
3158 *
3159 * \param seat The seat to query
3160 * \return The seat's touch pointer, or NULL if no touch device is present
3161 *
3162 * The touch pointer for a seat isn't freed when all touch devices are removed,
3163 * so it should only be used when the seat's touch_device_count is greater
3164 * than zero. This function does that test and only returns a pointer
3165 * when a touch device is present.
3166 */
3167WL_EXPORT struct weston_touch *
3168weston_seat_get_touch(struct weston_seat *seat)
3169{
3170 if (!seat)
3171 return NULL;
3172
3173 if (seat->touch_device_count)
3174 return seat->touch_state;
3175
3176 return NULL;
3177}
Bryce Harrington24f917e2016-06-29 19:04:07 -07003178
3179/** Sets the keyboard focus to the given surface
3180 *
3181 * \param seat The seat to query
3182 */
3183WL_EXPORT void
3184weston_seat_set_keyboard_focus(struct weston_seat *seat,
3185 struct weston_surface *surface)
3186{
3187 struct weston_compositor *compositor = seat->compositor;
3188 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Jonas Ådahlf7deb6a2016-07-22 17:50:26 +08003189 struct weston_surface_activation_data activation_data;
Bryce Harrington24f917e2016-06-29 19:04:07 -07003190
Jonas Ådahlef8e1c32016-03-15 20:28:51 +08003191 if (keyboard && keyboard->focus != surface) {
Bryce Harrington24f917e2016-06-29 19:04:07 -07003192 weston_keyboard_set_focus(keyboard, surface);
3193 wl_data_device_set_keyboard_focus(seat);
3194 }
3195
Jonas Ådahl94e2e2d2014-10-18 18:42:19 +02003196 inc_activate_serial(compositor);
Jonas Ådahlf7deb6a2016-07-22 17:50:26 +08003197
3198 activation_data = (struct weston_surface_activation_data) {
3199 .surface = surface,
3200 .seat = seat,
3201 };
3202 wl_signal_emit(&compositor->activate_signal, &activation_data);
Bryce Harrington24f917e2016-06-29 19:04:07 -07003203}
Jonas Ådahl30d61d82014-10-22 21:21:17 +02003204
Jonas Ådahld3414f22016-07-22 17:56:31 +08003205static void
3206enable_pointer_constraint(struct weston_pointer_constraint *constraint,
3207 struct weston_view *view)
3208{
3209 assert(constraint->view == NULL);
3210 constraint->view = view;
3211 pointer_constraint_notify_activated(constraint);
3212 weston_pointer_start_grab(constraint->pointer, &constraint->grab);
3213 wl_list_remove(&constraint->surface_destroy_listener.link);
3214 wl_list_init(&constraint->surface_destroy_listener.link);
3215}
3216
3217static bool
3218is_pointer_constraint_enabled(struct weston_pointer_constraint *constraint)
3219{
3220 return constraint->view != NULL;
3221}
3222
3223static void
3224weston_pointer_constraint_disable(struct weston_pointer_constraint *constraint)
3225{
3226 constraint->view = NULL;
3227 pointer_constraint_notify_deactivated(constraint);
3228 weston_pointer_end_grab(constraint->grab.pointer);
3229}
3230
3231void
3232weston_pointer_constraint_destroy(struct weston_pointer_constraint *constraint)
3233{
3234 if (is_pointer_constraint_enabled(constraint))
3235 weston_pointer_constraint_disable(constraint);
3236
3237 wl_list_remove(&constraint->pointer_destroy_listener.link);
3238 wl_list_remove(&constraint->surface_destroy_listener.link);
3239 wl_list_remove(&constraint->surface_commit_listener.link);
3240 wl_list_remove(&constraint->surface_activate_listener.link);
3241
3242 wl_resource_set_user_data(constraint->resource, NULL);
3243 pixman_region32_fini(&constraint->region);
3244 wl_list_remove(&constraint->link);
3245 free(constraint);
3246}
3247
3248static void
3249disable_pointer_constraint(struct weston_pointer_constraint *constraint)
3250{
3251 switch (constraint->lifetime) {
3252 case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT:
3253 weston_pointer_constraint_destroy(constraint);
3254 break;
3255 case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT:
3256 weston_pointer_constraint_disable(constraint);
3257 break;
3258 }
3259}
3260
3261static bool
3262is_within_constraint_region(struct weston_pointer_constraint *constraint,
3263 wl_fixed_t sx, wl_fixed_t sy)
3264{
3265 struct weston_surface *surface = constraint->surface;
3266 pixman_region32_t constraint_region;
3267 bool result;
3268
3269 pixman_region32_init(&constraint_region);
3270 pixman_region32_intersect(&constraint_region,
3271 &surface->input,
3272 &constraint->region);
3273 result = pixman_region32_contains_point(&constraint_region,
3274 wl_fixed_to_int(sx),
3275 wl_fixed_to_int(sy),
3276 NULL);
3277 pixman_region32_fini(&constraint_region);
3278
3279 return result;
3280}
3281
3282static void
3283maybe_enable_pointer_constraint(struct weston_pointer_constraint *constraint)
3284{
3285 struct weston_surface *surface = constraint->surface;
3286 struct weston_view *vit;
3287 struct weston_view *view = NULL;
3288 struct weston_pointer *pointer = constraint->pointer;
3289 struct weston_keyboard *keyboard;
3290 struct weston_seat *seat = pointer->seat;
3291 int32_t x, y;
3292
3293 /* Postpone if no view of the surface was most recently clicked. */
3294 wl_list_for_each(vit, &surface->views, surface_link) {
3295 if (vit->click_to_activate_serial ==
3296 surface->compositor->activate_serial) {
3297 view = vit;
3298 }
3299 }
3300 if (view == NULL)
3301 return;
3302
3303 /* Postpone if surface doesn't have keyboard focus. */
3304 keyboard = weston_seat_get_keyboard(seat);
3305 if (!keyboard || keyboard->focus != surface)
3306 return;
3307
3308 /* Postpone constraint if the pointer is not within the
3309 * constraint region.
3310 */
3311 weston_view_from_global(view,
3312 wl_fixed_to_int(pointer->x),
3313 wl_fixed_to_int(pointer->y),
3314 &x, &y);
3315 if (!is_within_constraint_region(constraint,
3316 wl_fixed_from_int(x),
3317 wl_fixed_from_int(y)))
3318 return;
3319
3320 enable_pointer_constraint(constraint, view);
3321}
3322
3323static void
3324locked_pointer_grab_pointer_focus(struct weston_pointer_grab *grab)
3325{
3326}
3327
3328static void
3329locked_pointer_grab_pointer_motion(struct weston_pointer_grab *grab,
Alexandros Frantzis84b31f82017-11-24 18:01:46 +02003330 const struct timespec *time,
Jonas Ådahld3414f22016-07-22 17:56:31 +08003331 struct weston_pointer_motion_event *event)
3332{
Quentin Glidiccde13452016-08-12 10:41:32 +02003333 pointer_send_relative_motion(grab->pointer, time, event);
Jonas Ådahld3414f22016-07-22 17:56:31 +08003334}
3335
3336static void
3337locked_pointer_grab_pointer_button(struct weston_pointer_grab *grab,
Alexandros Frantzis215bedc2017-11-16 18:20:55 +02003338 const struct timespec *time,
Jonas Ådahld3414f22016-07-22 17:56:31 +08003339 uint32_t button,
3340 uint32_t state_w)
3341{
3342 weston_pointer_send_button(grab->pointer, time, button, state_w);
3343}
3344
3345static void
3346locked_pointer_grab_pointer_axis(struct weston_pointer_grab *grab,
Alexandros Frantzis80321942017-11-16 18:20:56 +02003347 const struct timespec *time,
Jonas Ådahld3414f22016-07-22 17:56:31 +08003348 struct weston_pointer_axis_event *event)
3349{
3350 weston_pointer_send_axis(grab->pointer, time, event);
3351}
3352
3353static void
3354locked_pointer_grab_pointer_axis_source(struct weston_pointer_grab *grab,
3355 uint32_t source)
3356{
3357 weston_pointer_send_axis_source(grab->pointer, source);
3358}
3359
3360static void
3361locked_pointer_grab_pointer_frame(struct weston_pointer_grab *grab)
3362{
3363 weston_pointer_send_frame(grab->pointer);
3364}
3365
3366static void
3367locked_pointer_grab_pointer_cancel(struct weston_pointer_grab *grab)
3368{
3369 struct weston_pointer_constraint *constraint =
3370 container_of(grab, struct weston_pointer_constraint, grab);
3371
3372 disable_pointer_constraint(constraint);
3373}
3374
3375static const struct weston_pointer_grab_interface
3376 locked_pointer_grab_interface = {
3377 locked_pointer_grab_pointer_focus,
3378 locked_pointer_grab_pointer_motion,
3379 locked_pointer_grab_pointer_button,
3380 locked_pointer_grab_pointer_axis,
3381 locked_pointer_grab_pointer_axis_source,
3382 locked_pointer_grab_pointer_frame,
3383 locked_pointer_grab_pointer_cancel,
3384};
3385
3386static void
3387pointer_constraint_constrain_resource_destroyed(struct wl_resource *resource)
3388{
3389 struct weston_pointer_constraint *constraint =
3390 wl_resource_get_user_data(resource);
3391
3392 if (!constraint)
3393 return;
3394
3395 weston_pointer_constraint_destroy(constraint);
3396}
3397
3398static void
3399pointer_constraint_surface_activate(struct wl_listener *listener, void *data)
3400{
3401 struct weston_surface_activation_data *activation = data;
3402 struct weston_pointer *pointer;
3403 struct weston_surface *focus = activation->surface;
3404 struct weston_pointer_constraint *constraint =
3405 container_of(listener, struct weston_pointer_constraint,
3406 surface_activate_listener);
3407 bool is_constraint_surface;
3408
3409 pointer = weston_seat_get_pointer(activation->seat);
3410 if (!pointer)
3411 return;
3412
3413 is_constraint_surface =
3414 get_pointer_constraint_for_pointer(focus, pointer) == constraint;
3415
3416 if (is_constraint_surface &&
3417 !is_pointer_constraint_enabled(constraint))
3418 maybe_enable_pointer_constraint(constraint);
3419 else if (!is_constraint_surface &&
3420 is_pointer_constraint_enabled(constraint))
3421 disable_pointer_constraint(constraint);
3422}
3423
3424static void
3425pointer_constraint_pointer_destroyed(struct wl_listener *listener, void *data)
3426{
3427 struct weston_pointer_constraint *constraint =
3428 container_of(listener, struct weston_pointer_constraint,
3429 pointer_destroy_listener);
3430
3431 weston_pointer_constraint_destroy(constraint);
3432}
3433
3434static void
3435pointer_constraint_surface_destroyed(struct wl_listener *listener, void *data)
3436{
3437 struct weston_pointer_constraint *constraint =
3438 container_of(listener, struct weston_pointer_constraint,
3439 surface_destroy_listener);
3440
3441 weston_pointer_constraint_destroy(constraint);
3442}
3443
3444static void
3445pointer_constraint_surface_committed(struct wl_listener *listener, void *data)
3446{
3447 struct weston_pointer_constraint *constraint =
3448 container_of(listener, struct weston_pointer_constraint,
3449 surface_commit_listener);
3450
3451 if (constraint->region_is_pending) {
3452 constraint->region_is_pending = false;
3453 pixman_region32_copy(&constraint->region,
3454 &constraint->region_pending);
3455 pixman_region32_fini(&constraint->region_pending);
3456 pixman_region32_init(&constraint->region_pending);
3457 }
3458
3459 if (constraint->hint_is_pending) {
3460 constraint->hint_is_pending = false;
3461
3462 constraint->hint_is_pending = true;
3463 constraint->hint_x = constraint->hint_x_pending;
3464 constraint->hint_y = constraint->hint_y_pending;
3465 }
3466
3467 if (pointer_constraint_get_type(constraint) ==
3468 POINTER_CONSTRAINT_TYPE_CONFINE &&
3469 is_pointer_constraint_enabled(constraint))
3470 maybe_warp_confined_pointer(constraint);
3471}
3472
3473static struct weston_pointer_constraint *
3474weston_pointer_constraint_create(struct weston_surface *surface,
3475 struct weston_pointer *pointer,
3476 struct weston_region *region,
3477 enum zwp_pointer_constraints_v1_lifetime lifetime,
3478 struct wl_resource *cr,
3479 const struct weston_pointer_grab_interface *grab_interface)
3480{
3481 struct weston_pointer_constraint *constraint;
3482
3483 constraint = zalloc(sizeof *constraint);
3484 if (!constraint)
3485 return NULL;
3486
3487 constraint->lifetime = lifetime;
3488 pixman_region32_init(&constraint->region);
3489 pixman_region32_init(&constraint->region_pending);
3490 wl_list_insert(&surface->pointer_constraints, &constraint->link);
3491 constraint->surface = surface;
3492 constraint->pointer = pointer;
3493 constraint->resource = cr;
3494 constraint->grab.interface = grab_interface;
3495 if (region) {
3496 pixman_region32_copy(&constraint->region,
3497 &region->region);
3498 } else {
3499 pixman_region32_fini(&constraint->region);
3500 region_init_infinite(&constraint->region);
3501 }
3502
3503 constraint->surface_activate_listener.notify =
3504 pointer_constraint_surface_activate;
3505 constraint->surface_destroy_listener.notify =
3506 pointer_constraint_surface_destroyed;
3507 constraint->surface_commit_listener.notify =
3508 pointer_constraint_surface_committed;
3509 constraint->pointer_destroy_listener.notify =
3510 pointer_constraint_pointer_destroyed;
3511
3512 wl_signal_add(&surface->compositor->activate_signal,
3513 &constraint->surface_activate_listener);
3514 wl_signal_add(&pointer->destroy_signal,
3515 &constraint->pointer_destroy_listener);
3516 wl_signal_add(&surface->destroy_signal,
3517 &constraint->surface_destroy_listener);
3518 wl_signal_add(&surface->commit_signal,
3519 &constraint->surface_commit_listener);
3520
3521 return constraint;
3522}
3523
3524static void
3525init_pointer_constraint(struct wl_resource *pointer_constraints_resource,
3526 uint32_t id,
3527 struct weston_surface *surface,
3528 struct weston_pointer *pointer,
3529 struct weston_region *region,
3530 enum zwp_pointer_constraints_v1_lifetime lifetime,
3531 const struct wl_interface *interface,
3532 const void *implementation,
3533 const struct weston_pointer_grab_interface *grab_interface)
3534{
3535 struct wl_client *client =
3536 wl_resource_get_client(pointer_constraints_resource);
3537 struct wl_resource *cr;
3538 struct weston_pointer_constraint *constraint;
3539
3540 if (get_pointer_constraint_for_pointer(surface, pointer)) {
3541 wl_resource_post_error(pointer_constraints_resource,
3542 ZWP_POINTER_CONSTRAINTS_V1_ERROR_ALREADY_CONSTRAINED,
3543 "the pointer has a lock/confine request on this surface");
3544 return;
3545 }
3546
3547 cr = wl_resource_create(client, interface,
3548 wl_resource_get_version(pointer_constraints_resource),
3549 id);
3550 if (cr == NULL) {
3551 wl_client_post_no_memory(client);
3552 return;
3553 }
3554
3555 constraint = weston_pointer_constraint_create(surface, pointer,
3556 region, lifetime,
3557 cr, grab_interface);
3558 if (constraint == NULL) {
3559 wl_client_post_no_memory(client);
3560 return;
3561 }
3562
3563 wl_resource_set_implementation(cr, implementation, constraint,
3564 pointer_constraint_constrain_resource_destroyed);
3565
3566 maybe_enable_pointer_constraint(constraint);
3567}
3568
3569static void
3570pointer_constraints_destroy(struct wl_client *client,
3571 struct wl_resource *resource)
3572{
3573 wl_resource_destroy(resource);
3574}
3575
3576static void
3577locked_pointer_destroy(struct wl_client *client,
3578 struct wl_resource *resource)
3579{
3580 struct weston_pointer_constraint *constraint =
3581 wl_resource_get_user_data(resource);
3582 wl_fixed_t x, y;
3583
3584 if (constraint && constraint->view && constraint->hint_is_pending &&
3585 is_within_constraint_region(constraint,
3586 constraint->hint_x,
3587 constraint->hint_y)) {
3588 weston_view_to_global_fixed(constraint->view,
3589 constraint->hint_x,
3590 constraint->hint_y,
3591 &x, &y);
3592 weston_pointer_move_to(constraint->pointer, x, y);
3593 }
3594 wl_resource_destroy(resource);
3595}
3596
3597static void
3598locked_pointer_set_cursor_position_hint(struct wl_client *client,
3599 struct wl_resource *resource,
3600 wl_fixed_t surface_x,
3601 wl_fixed_t surface_y)
3602{
3603 struct weston_pointer_constraint *constraint =
3604 wl_resource_get_user_data(resource);
3605
3606 /* Ignore a set cursor hint that was sent after the lock was cancelled.
3607 */
3608 if (!constraint ||
3609 !constraint->resource ||
3610 constraint->resource != resource)
3611 return;
3612
3613 constraint->hint_is_pending = true;
3614 constraint->hint_x_pending = surface_x;
3615 constraint->hint_y_pending = surface_y;
3616}
3617
3618static void
3619locked_pointer_set_region(struct wl_client *client,
3620 struct wl_resource *resource,
3621 struct wl_resource *region_resource)
3622{
3623 struct weston_pointer_constraint *constraint =
3624 wl_resource_get_user_data(resource);
3625 struct weston_region *region = region_resource ?
3626 wl_resource_get_user_data(region_resource) : NULL;
3627
3628 if (!constraint)
3629 return;
3630
3631 if (region) {
3632 pixman_region32_copy(&constraint->region_pending,
3633 &region->region);
3634 } else {
3635 pixman_region32_fini(&constraint->region_pending);
3636 region_init_infinite(&constraint->region_pending);
3637 }
3638 constraint->region_is_pending = true;
3639}
3640
3641
3642static const struct zwp_locked_pointer_v1_interface locked_pointer_interface = {
3643 locked_pointer_destroy,
3644 locked_pointer_set_cursor_position_hint,
3645 locked_pointer_set_region,
3646};
3647
3648static void
3649pointer_constraints_lock_pointer(struct wl_client *client,
3650 struct wl_resource *resource,
3651 uint32_t id,
3652 struct wl_resource *surface_resource,
3653 struct wl_resource *pointer_resource,
3654 struct wl_resource *region_resource,
3655 uint32_t lifetime)
3656{
3657 struct weston_surface *surface =
3658 wl_resource_get_user_data(surface_resource);
3659 struct weston_pointer *pointer = wl_resource_get_user_data(pointer_resource);
3660 struct weston_region *region = region_resource ?
3661 wl_resource_get_user_data(region_resource) : NULL;
3662
3663 init_pointer_constraint(resource, id, surface, pointer, region, lifetime,
3664 &zwp_locked_pointer_v1_interface,
3665 &locked_pointer_interface,
3666 &locked_pointer_grab_interface);
3667}
3668
3669static void
3670confined_pointer_grab_pointer_focus(struct weston_pointer_grab *grab)
3671{
3672}
3673
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08003674static double
3675vec2d_cross_product(struct vec2d a, struct vec2d b)
3676{
3677 return a.x * b.y - a.y * b.x;
3678}
3679
3680static struct vec2d
3681vec2d_add(struct vec2d a, struct vec2d b)
3682{
3683 return (struct vec2d) {
3684 .x = a.x + b.x,
3685 .y = a.y + b.y,
3686 };
3687}
3688
3689static struct vec2d
3690vec2d_subtract(struct vec2d a, struct vec2d b)
3691{
3692 return (struct vec2d) {
3693 .x = a.x - b.x,
3694 .y = a.y - b.y,
3695 };
3696}
3697
3698static struct vec2d
3699vec2d_multiply_constant(double c, struct vec2d a)
3700{
3701 return (struct vec2d) {
3702 .x = c * a.x,
3703 .y = c * a.y,
3704 };
3705}
3706
3707static bool
3708lines_intersect(struct line *line1, struct line *line2,
3709 struct vec2d *intersection)
3710{
3711 struct vec2d p = line1->a;
3712 struct vec2d r = vec2d_subtract(line1->b, line1->a);
3713 struct vec2d q = line2->a;
3714 struct vec2d s = vec2d_subtract(line2->b, line2->a);
3715 double rxs;
3716 double sxr;
3717 double t;
3718 double u;
3719
3720 /*
3721 * The line (p, r) and (q, s) intersects where
3722 *
3723 * p + t r = q + u s
3724 *
3725 * Calculate t:
3726 *
3727 * (p + t r) × s = (q + u s) × s
3728 * p × s + t (r × s) = q × s + u (s × s)
3729 * p × s + t (r × s) = q × s
3730 * t (r × s) = q × s - p × s
3731 * t (r × s) = (q - p) × s
3732 * t = ((q - p) × s) / (r × s)
3733 *
3734 * Using the same method, for u we get:
3735 *
3736 * u = ((p - q) × r) / (s × r)
3737 */
3738
3739 rxs = vec2d_cross_product(r, s);
3740 sxr = vec2d_cross_product(s, r);
3741
3742 /* If r × s = 0 then the lines are either parallel or collinear. */
3743 if (fabs(rxs) < DBL_MIN)
3744 return false;
3745
3746 t = vec2d_cross_product(vec2d_subtract(q, p), s) / rxs;
3747 u = vec2d_cross_product(vec2d_subtract(p, q), r) / sxr;
3748
3749 /* The lines only intersect if 0 ≤ t ≤ 1 and 0 ≤ u ≤ 1. */
3750 if (t < 0.0 || t > 1.0 || u < 0.0 || u > 1.0)
3751 return false;
3752
3753 *intersection = vec2d_add(p, vec2d_multiply_constant(t, r));
3754 return true;
3755}
3756
3757static struct border *
3758add_border(struct wl_array *array,
3759 double x1, double y1,
3760 double x2, double y2,
3761 enum motion_direction blocking_dir)
3762{
3763 struct border *border = wl_array_add(array, sizeof *border);
3764
3765 *border = (struct border) {
3766 .line = (struct line) {
3767 .a = (struct vec2d) {
3768 .x = x1,
3769 .y = y1,
3770 },
3771 .b = (struct vec2d) {
3772 .x = x2,
3773 .y = y2,
3774 },
3775 },
3776 .blocking_dir = blocking_dir,
3777 };
3778
3779 return border;
3780}
3781
3782static int
3783compare_lines_x(const void *a, const void *b)
3784{
3785 const struct border *border_a = a;
3786 const struct border *border_b = b;
3787
3788
3789 if (border_a->line.a.x == border_b->line.a.x)
3790 return border_a->line.b.x < border_b->line.b.x;
3791 else
3792 return border_a->line.a.x > border_b->line.a.x;
3793}
3794
3795static void
3796add_non_overlapping_edges(pixman_box32_t *boxes,
3797 int band_above_start,
3798 int band_below_start,
3799 int band_below_end,
3800 struct wl_array *borders)
3801{
3802 int i;
3803 struct wl_array band_merge;
3804 struct border *border;
3805 struct border *prev_border;
3806 struct border *new_border;
3807
3808 wl_array_init(&band_merge);
3809
3810 /* Add bottom band of previous row, and top band of current row, and
3811 * sort them so lower left x coordinate comes first. If there are two
3812 * borders with the same left x coordinate, the wider one comes first.
3813 */
3814 for (i = band_above_start; i < band_below_start; i++) {
3815 pixman_box32_t *box = &boxes[i];
3816 add_border(&band_merge, box->x1, box->y2, box->x2, box->y2,
3817 MOTION_DIRECTION_POSITIVE_Y);
3818 }
3819 for (i = band_below_start; i < band_below_end; i++) {
3820 pixman_box32_t *box= &boxes[i];
3821 add_border(&band_merge, box->x1, box->y1, box->x2, box->y1,
3822 MOTION_DIRECTION_NEGATIVE_Y);
3823 }
3824 qsort(band_merge.data,
3825 band_merge.size / sizeof *border,
3826 sizeof *border,
3827 compare_lines_x);
3828
3829 /* Combine the two combined bands so that any overlapping border is
3830 * eliminated. */
3831 prev_border = NULL;
3832 wl_array_for_each(border, &band_merge) {
3833 assert(border->line.a.y == border->line.b.y);
3834 assert(!prev_border ||
3835 prev_border->line.a.y == border->line.a.y);
3836 assert(!prev_border ||
3837 (prev_border->line.a.x != border->line.a.x ||
3838 prev_border->line.b.x != border->line.b.x));
3839 assert(!prev_border ||
3840 prev_border->line.a.x <= border->line.a.x);
3841
3842 if (prev_border &&
3843 prev_border->line.a.x == border->line.a.x) {
3844 /*
3845 * ------------ +
3846 * ------- =
3847 * [ ]-----
3848 */
3849 prev_border->line.a.x = border->line.b.x;
3850 } else if (prev_border &&
3851 prev_border->line.b.x == border->line.b.x) {
3852 /*
3853 * ------------ +
3854 * ------ =
3855 * ------[ ]
3856 */
3857 prev_border->line.b.x = border->line.a.x;
3858 } else if (prev_border &&
3859 prev_border->line.b.x == border->line.a.x) {
3860 /*
3861 * -------- +
3862 * ------ =
3863 * --------------
3864 */
3865 prev_border->line.b.x = border->line.b.x;
3866 } else if (prev_border &&
3867 prev_border->line.b.x >= border->line.a.x) {
3868 /*
3869 * --------------- +
3870 * ------ =
3871 * -----[ ]----
3872 */
3873 new_border = add_border(borders,
3874 border->line.b.x,
3875 border->line.b.y,
3876 prev_border->line.b.x,
3877 prev_border->line.b.y,
3878 prev_border->blocking_dir);
3879 prev_border->line.b.x = border->line.a.x;
3880 prev_border = new_border;
3881 } else {
3882 assert(!prev_border ||
3883 prev_border->line.b.x < border->line.a.x);
3884 /*
3885 * First border or non-overlapping.
3886 *
3887 * ----- +
3888 * ----- =
3889 * ----- -----
3890 */
3891 new_border = wl_array_add(borders, sizeof *border);
3892 *new_border = *border;
3893 prev_border = new_border;
3894 }
3895 }
3896
3897 wl_array_release(&band_merge);
3898}
3899
3900static void
3901add_band_bottom_edges(pixman_box32_t *boxes,
3902 int band_start,
3903 int band_end,
3904 struct wl_array *borders)
3905{
3906 int i;
3907
3908 for (i = band_start; i < band_end; i++) {
3909 add_border(borders,
3910 boxes[i].x1, boxes[i].y2,
3911 boxes[i].x2, boxes[i].y2,
3912 MOTION_DIRECTION_POSITIVE_Y);
3913 }
3914}
3915
3916static void
3917region_to_outline(pixman_region32_t *region, struct wl_array *borders)
3918{
3919 pixman_box32_t *boxes;
3920 int num_boxes;
3921 int i;
3922 int top_most, bottom_most;
3923 int current_roof;
3924 int prev_top;
3925 int band_start, prev_band_start;
3926
3927 /*
3928 * Remove any overlapping lines from the set of rectangles. Note that
3929 * pixman regions are grouped as rows of rectangles, where rectangles
3930 * in one row never touch or overlap and are all of the same height.
3931 *
3932 * -------- --- -------- ---
3933 * | | | | | | | |
3934 * ----------====---- --- ----------- ----- ---
3935 * | | => | |
3936 * ----==========--------- ----- ----------
3937 * | | | |
3938 * ------------------- -------------------
3939 *
3940 */
3941
3942 boxes = pixman_region32_rectangles(region, &num_boxes);
3943 prev_top = 0;
3944 top_most = boxes[0].y1;
3945 current_roof = top_most;
3946 bottom_most = boxes[num_boxes - 1].y2;
3947 band_start = 0;
3948 prev_band_start = 0;
3949 for (i = 0; i < num_boxes; i++) {
3950 /* Detect if there is a vertical empty space, and add the lower
3951 * level of the previous band if so was the case. */
3952 if (i > 0 &&
3953 boxes[i].y1 != prev_top &&
3954 boxes[i].y1 != boxes[i - 1].y2) {
3955 current_roof = boxes[i].y1;
3956 add_band_bottom_edges(boxes,
3957 band_start,
3958 i,
3959 borders);
3960 }
3961
3962 /* Special case adding the last band, since it won't be handled
3963 * by the band change detection below. */
3964 if (boxes[i].y1 != current_roof && i == num_boxes - 1) {
3965 if (boxes[i].y1 != prev_top) {
3966 /* The last band is a single box, so we don't
3967 * have a prev_band_start to tell us when the
3968 * previous band started. */
3969 add_non_overlapping_edges(boxes,
3970 band_start,
3971 i,
3972 i + 1,
3973 borders);
3974 } else {
3975 add_non_overlapping_edges(boxes,
3976 prev_band_start,
3977 band_start,
3978 i + 1,
3979 borders);
3980 }
3981 }
3982
3983 /* Detect when passing a band and combine the top border of the
3984 * just passed band with the bottom band of the previous band.
3985 */
3986 if (boxes[i].y1 != top_most && boxes[i].y1 != prev_top) {
3987 /* Combine the two passed bands. */
3988 if (prev_top != current_roof) {
3989 add_non_overlapping_edges(boxes,
3990 prev_band_start,
3991 band_start,
3992 i,
3993 borders);
3994 }
3995
3996 prev_band_start = band_start;
3997 band_start = i;
3998 }
3999
4000 /* Add the top border if the box is part of the current roof. */
4001 if (boxes[i].y1 == current_roof) {
4002 add_border(borders,
4003 boxes[i].x1, boxes[i].y1,
4004 boxes[i].x2, boxes[i].y1,
4005 MOTION_DIRECTION_NEGATIVE_Y);
4006 }
4007
4008 /* Add the bottom border of the last band. */
4009 if (boxes[i].y2 == bottom_most) {
4010 add_border(borders,
4011 boxes[i].x1, boxes[i].y2,
4012 boxes[i].x2, boxes[i].y2,
4013 MOTION_DIRECTION_POSITIVE_Y);
4014 }
4015
4016 /* Always add the left border. */
4017 add_border(borders,
4018 boxes[i].x1, boxes[i].y1,
4019 boxes[i].x1, boxes[i].y2,
4020 MOTION_DIRECTION_NEGATIVE_X);
4021
4022 /* Always add the right border. */
4023 add_border(borders,
4024 boxes[i].x2, boxes[i].y1,
4025 boxes[i].x2, boxes[i].y2,
4026 MOTION_DIRECTION_POSITIVE_X);
4027
4028 prev_top = boxes[i].y1;
4029 }
4030}
4031
4032static bool
4033is_border_horizontal (struct border *border)
4034{
4035 return border->line.a.y == border->line.b.y;
4036}
4037
4038static bool
4039is_border_blocking_directions(struct border *border,
4040 uint32_t directions)
4041{
4042 /* Don't block parallel motions. */
4043 if (is_border_horizontal(border)) {
4044 if ((directions & (MOTION_DIRECTION_POSITIVE_Y |
4045 MOTION_DIRECTION_NEGATIVE_Y)) == 0)
4046 return false;
4047 } else {
4048 if ((directions & (MOTION_DIRECTION_POSITIVE_X |
4049 MOTION_DIRECTION_NEGATIVE_X)) == 0)
4050 return false;
4051 }
4052
4053 return (~border->blocking_dir & directions) != directions;
4054}
4055
4056static struct border *
4057get_closest_border(struct wl_array *borders,
4058 struct line *motion,
4059 uint32_t directions)
4060{
4061 struct border *border;
4062 struct vec2d intersection;
4063 struct vec2d delta;
4064 double distance_2;
4065 struct border *closest_border = NULL;
4066 double closest_distance_2 = DBL_MAX;
4067
4068 wl_array_for_each(border, borders) {
4069 if (!is_border_blocking_directions(border, directions))
4070 continue;
4071
4072 if (!lines_intersect(&border->line, motion, &intersection))
4073 continue;
4074
4075 delta = vec2d_subtract(intersection, motion->a);
4076 distance_2 = delta.x*delta.x + delta.y*delta.y;
4077 if (distance_2 < closest_distance_2) {
4078 closest_border = border;
4079 closest_distance_2 = distance_2;
4080 }
4081 }
4082
4083 return closest_border;
4084}
4085
4086static void
4087clamp_to_border(struct border *border,
4088 struct line *motion,
4089 uint32_t *motion_dir)
4090{
4091 /*
4092 * When clamping either rightward or downward motions, the motion needs
4093 * to be clamped so that the destination coordinate does not end up on
4094 * the border (see weston_pointer_clamp_event_to_region). Do this by
4095 * clamping such motions to the border minus the smallest possible
4096 * wl_fixed_t value.
4097 */
4098 if (is_border_horizontal(border)) {
4099 if (*motion_dir & MOTION_DIRECTION_POSITIVE_Y)
4100 motion->b.y = border->line.a.y - wl_fixed_to_double(1);
4101 else
4102 motion->b.y = border->line.a.y;
4103 *motion_dir &= ~(MOTION_DIRECTION_POSITIVE_Y |
4104 MOTION_DIRECTION_NEGATIVE_Y);
4105 } else {
4106 if (*motion_dir & MOTION_DIRECTION_POSITIVE_X)
4107 motion->b.x = border->line.a.x - wl_fixed_to_double(1);
4108 else
4109 motion->b.x = border->line.a.x;
4110 *motion_dir &= ~(MOTION_DIRECTION_POSITIVE_X |
4111 MOTION_DIRECTION_NEGATIVE_X);
4112 }
4113}
4114
4115static uint32_t
4116get_motion_directions(struct line *motion)
4117{
4118 uint32_t directions = 0;
4119
4120 if (motion->a.x < motion->b.x)
4121 directions |= MOTION_DIRECTION_POSITIVE_X;
4122 else if (motion->a.x > motion->b.x)
4123 directions |= MOTION_DIRECTION_NEGATIVE_X;
4124 if (motion->a.y < motion->b.y)
4125 directions |= MOTION_DIRECTION_POSITIVE_Y;
4126 else if (motion->a.y > motion->b.y)
4127 directions |= MOTION_DIRECTION_NEGATIVE_Y;
4128
4129 return directions;
4130}
4131
Jonas Ådahld3414f22016-07-22 17:56:31 +08004132static void
4133weston_pointer_clamp_event_to_region(struct weston_pointer *pointer,
4134 struct weston_pointer_motion_event *event,
4135 pixman_region32_t *region,
4136 wl_fixed_t *clamped_x,
4137 wl_fixed_t *clamped_y)
4138{
4139 wl_fixed_t x, y;
4140 wl_fixed_t sx, sy;
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004141 wl_fixed_t old_sx = pointer->sx;
4142 wl_fixed_t old_sy = pointer->sy;
4143 struct wl_array borders;
4144 struct line motion;
4145 struct border *closest_border;
4146 float new_x_f, new_y_f;
4147 uint32_t directions;
Jonas Ådahld3414f22016-07-22 17:56:31 +08004148
4149 weston_pointer_motion_to_abs(pointer, event, &x, &y);
4150 weston_view_from_global_fixed(pointer->focus, x, y, &sx, &sy);
4151
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004152 wl_array_init(&borders);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004153
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004154 /*
4155 * Generate borders given the confine region we are to use. The borders
4156 * are defined to be the outer region of the allowed area. This means
4157 * top/left borders are "within" the allowed area, while bottom/right
4158 * borders are outside. This needs to be considered when clamping
4159 * confined motion vectors.
4160 */
4161 region_to_outline(region, &borders);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004162
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004163 motion = (struct line) {
4164 .a = (struct vec2d) {
4165 .x = wl_fixed_to_double(old_sx),
4166 .y = wl_fixed_to_double(old_sy),
4167 },
4168 .b = (struct vec2d) {
4169 .x = wl_fixed_to_double(sx),
4170 .y = wl_fixed_to_double(sy),
4171 },
4172 };
4173 directions = get_motion_directions(&motion);
4174
4175 while (directions) {
4176 closest_border = get_closest_border(&borders,
4177 &motion,
4178 directions);
4179 if (closest_border)
4180 clamp_to_border(closest_border, &motion, &directions);
4181 else
4182 break;
4183 }
4184
4185 weston_view_to_global_float(pointer->focus,
4186 (float) motion.b.x, (float) motion.b.y,
4187 &new_x_f, &new_y_f);
4188 *clamped_x = wl_fixed_from_double(new_x_f);
4189 *clamped_y = wl_fixed_from_double(new_y_f);
4190
4191 wl_array_release(&borders);
4192}
4193
4194static double
4195point_to_border_distance_2(struct border *border, double x, double y)
4196{
4197 double orig_x, orig_y;
4198 double dx, dy;
4199
4200 if (is_border_horizontal(border)) {
4201 if (x < border->line.a.x)
4202 orig_x = border->line.a.x;
4203 else if (x > border->line.b.x)
4204 orig_x = border->line.b.x;
4205 else
4206 orig_x = x;
4207 orig_y = border->line.a.y;
4208 } else {
4209 if (y < border->line.a.y)
4210 orig_y = border->line.a.y;
4211 else if (y > border->line.b.y)
4212 orig_y = border->line.b.y;
4213 else
4214 orig_y = y;
4215 orig_x = border->line.a.x;
4216 }
4217
4218
4219 dx = fabs(orig_x - x);
4220 dy = fabs(orig_y - y);
4221 return dx*dx + dy*dy;
4222}
4223
4224static void
4225warp_to_behind_border(struct border *border, wl_fixed_t *sx, wl_fixed_t *sy)
4226{
4227 switch (border->blocking_dir) {
4228 case MOTION_DIRECTION_POSITIVE_X:
4229 case MOTION_DIRECTION_NEGATIVE_X:
4230 if (border->blocking_dir == MOTION_DIRECTION_POSITIVE_X)
4231 *sx = wl_fixed_from_double(border->line.a.x) - 1;
4232 else
4233 *sx = wl_fixed_from_double(border->line.a.x) + 1;
4234 if (*sy < wl_fixed_from_double(border->line.a.y))
4235 *sy = wl_fixed_from_double(border->line.a.y) + 1;
4236 else if (*sy > wl_fixed_from_double(border->line.b.y))
4237 *sy = wl_fixed_from_double(border->line.b.y) - 1;
4238 break;
4239 case MOTION_DIRECTION_POSITIVE_Y:
4240 case MOTION_DIRECTION_NEGATIVE_Y:
4241 if (border->blocking_dir == MOTION_DIRECTION_POSITIVE_Y)
4242 *sy = wl_fixed_from_double(border->line.a.y) - 1;
4243 else
4244 *sy = wl_fixed_from_double(border->line.a.y) + 1;
4245 if (*sx < wl_fixed_from_double(border->line.a.x))
4246 *sx = wl_fixed_from_double(border->line.a.x) + 1;
4247 else if (*sx > wl_fixed_from_double(border->line.b.x))
4248 *sx = wl_fixed_from_double(border->line.b.x) - 1;
4249 break;
4250 }
Jonas Ådahld3414f22016-07-22 17:56:31 +08004251}
4252
4253static void
4254maybe_warp_confined_pointer(struct weston_pointer_constraint *constraint)
4255{
4256 wl_fixed_t x;
4257 wl_fixed_t y;
4258 wl_fixed_t sx;
4259 wl_fixed_t sy;
4260
4261 weston_view_from_global_fixed(constraint->view,
4262 constraint->pointer->x,
4263 constraint->pointer->y,
4264 &sx,
4265 &sy);
4266
4267 if (!is_within_constraint_region(constraint, sx, sy)) {
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004268 double xf = wl_fixed_to_double(sx);
4269 double yf = wl_fixed_to_double(sy);
4270 pixman_region32_t confine_region;
4271 struct wl_array borders;
4272 struct border *border;
4273 double closest_distance_2 = DBL_MAX;
4274 struct border *closest_border = NULL;
Jonas Ådahld3414f22016-07-22 17:56:31 +08004275
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004276 wl_array_init(&borders);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004277
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004278 pixman_region32_init(&confine_region);
4279 pixman_region32_intersect(&confine_region,
4280 &constraint->view->surface->input,
4281 &constraint->region);
4282 region_to_outline(&confine_region, &borders);
4283 pixman_region32_fini(&confine_region);
4284
4285 wl_array_for_each(border, &borders) {
4286 double distance_2;
4287
4288 distance_2 = point_to_border_distance_2(border, xf, yf);
4289 if (distance_2 < closest_distance_2) {
4290 closest_border = border;
4291 closest_distance_2 = distance_2;
4292 }
4293 }
4294 assert(closest_border);
4295
4296 warp_to_behind_border(closest_border, &sx, &sy);
4297
4298 wl_array_release(&borders);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004299
4300 weston_view_to_global_fixed(constraint->view, sx, sy, &x, &y);
4301 weston_pointer_move_to(constraint->pointer, x, y);
4302 }
4303}
4304
4305static void
4306confined_pointer_grab_pointer_motion(struct weston_pointer_grab *grab,
Alexandros Frantzis84b31f82017-11-24 18:01:46 +02004307 const struct timespec *time,
Jonas Ådahld3414f22016-07-22 17:56:31 +08004308 struct weston_pointer_motion_event *event)
4309{
4310 struct weston_pointer_constraint *constraint =
4311 container_of(grab, struct weston_pointer_constraint, grab);
4312 struct weston_pointer *pointer = grab->pointer;
4313 struct weston_surface *surface;
4314 wl_fixed_t x, y;
4315 wl_fixed_t old_sx = pointer->sx;
4316 wl_fixed_t old_sy = pointer->sy;
4317 pixman_region32_t confine_region;
4318
4319 assert(pointer->focus);
4320 assert(pointer->focus->surface == constraint->surface);
4321
4322 surface = pointer->focus->surface;
4323
4324 pixman_region32_init(&confine_region);
4325 pixman_region32_intersect(&confine_region,
4326 &surface->input,
4327 &constraint->region);
4328 weston_pointer_clamp_event_to_region(pointer, event,
4329 &confine_region, &x, &y);
4330 weston_pointer_move_to(pointer, x, y);
4331 pixman_region32_fini(&confine_region);
4332
4333 weston_view_from_global_fixed(pointer->focus, x, y,
4334 &pointer->sx, &pointer->sy);
4335
4336 if (old_sx != pointer->sx || old_sy != pointer->sy) {
Quentin Glidiccde13452016-08-12 10:41:32 +02004337 pointer_send_motion(pointer, time,
4338 pointer->sx, pointer->sy);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004339 }
4340
Quentin Glidiccde13452016-08-12 10:41:32 +02004341 pointer_send_relative_motion(pointer, time, event);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004342}
4343
4344static void
4345confined_pointer_grab_pointer_button(struct weston_pointer_grab *grab,
Alexandros Frantzis215bedc2017-11-16 18:20:55 +02004346 const struct timespec *time,
Jonas Ådahld3414f22016-07-22 17:56:31 +08004347 uint32_t button,
4348 uint32_t state_w)
4349{
4350 weston_pointer_send_button(grab->pointer, time, button, state_w);
4351}
4352
4353static void
4354confined_pointer_grab_pointer_axis(struct weston_pointer_grab *grab,
Alexandros Frantzis80321942017-11-16 18:20:56 +02004355 const struct timespec *time,
Jonas Ådahld3414f22016-07-22 17:56:31 +08004356 struct weston_pointer_axis_event *event)
4357{
4358 weston_pointer_send_axis(grab->pointer, time, event);
4359}
4360
4361static void
4362confined_pointer_grab_pointer_axis_source(struct weston_pointer_grab *grab,
4363 uint32_t source)
4364{
4365 weston_pointer_send_axis_source(grab->pointer, source);
4366}
4367
4368static void
4369confined_pointer_grab_pointer_frame(struct weston_pointer_grab *grab)
4370{
4371 weston_pointer_send_frame(grab->pointer);
4372}
4373
4374static void
4375confined_pointer_grab_pointer_cancel(struct weston_pointer_grab *grab)
4376{
4377 struct weston_pointer_constraint *constraint =
4378 container_of(grab, struct weston_pointer_constraint, grab);
4379
4380 disable_pointer_constraint(constraint);
4381
4382 /* If this is a persistent constraint, re-add the surface destroy signal
4383 * listener only if we are currently not destroying the surface. */
4384 switch (constraint->lifetime) {
4385 case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT:
4386 if (constraint->surface->resource)
4387 wl_signal_add(&constraint->surface->destroy_signal,
4388 &constraint->surface_destroy_listener);
4389 break;
4390 case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT:
4391 break;
4392 }
4393}
4394
4395static const struct weston_pointer_grab_interface
4396 confined_pointer_grab_interface = {
4397 confined_pointer_grab_pointer_focus,
4398 confined_pointer_grab_pointer_motion,
4399 confined_pointer_grab_pointer_button,
4400 confined_pointer_grab_pointer_axis,
4401 confined_pointer_grab_pointer_axis_source,
4402 confined_pointer_grab_pointer_frame,
4403 confined_pointer_grab_pointer_cancel,
4404};
4405
4406static void
4407confined_pointer_destroy(struct wl_client *client,
4408 struct wl_resource *resource)
4409{
4410 wl_resource_destroy(resource);
4411}
4412
4413static void
4414confined_pointer_set_region(struct wl_client *client,
4415 struct wl_resource *resource,
4416 struct wl_resource *region_resource)
4417{
4418 struct weston_pointer_constraint *constraint =
4419 wl_resource_get_user_data(resource);
4420 struct weston_region *region = region_resource ?
4421 wl_resource_get_user_data(region_resource) : NULL;
4422
4423 if (!constraint)
4424 return;
4425
4426 if (region) {
4427 pixman_region32_copy(&constraint->region_pending,
4428 &region->region);
4429 } else {
4430 pixman_region32_fini(&constraint->region_pending);
4431 region_init_infinite(&constraint->region_pending);
4432 }
4433 constraint->region_is_pending = true;
4434}
4435
4436static const struct zwp_confined_pointer_v1_interface confined_pointer_interface = {
4437 confined_pointer_destroy,
4438 confined_pointer_set_region,
4439};
4440
4441static void
4442pointer_constraints_confine_pointer(struct wl_client *client,
4443 struct wl_resource *resource,
4444 uint32_t id,
4445 struct wl_resource *surface_resource,
4446 struct wl_resource *pointer_resource,
4447 struct wl_resource *region_resource,
4448 uint32_t lifetime)
4449{
4450 struct weston_surface *surface =
4451 wl_resource_get_user_data(surface_resource);
4452 struct weston_pointer *pointer = wl_resource_get_user_data(pointer_resource);
4453 struct weston_region *region = region_resource ?
4454 wl_resource_get_user_data(region_resource) : NULL;
4455
4456 init_pointer_constraint(resource, id, surface, pointer, region, lifetime,
4457 &zwp_confined_pointer_v1_interface,
4458 &confined_pointer_interface,
4459 &confined_pointer_grab_interface);
4460}
4461
4462static const struct zwp_pointer_constraints_v1_interface pointer_constraints_interface = {
4463 pointer_constraints_destroy,
4464 pointer_constraints_lock_pointer,
4465 pointer_constraints_confine_pointer,
4466};
4467
4468static void
4469bind_pointer_constraints(struct wl_client *client, void *data,
4470 uint32_t version, uint32_t id)
4471{
4472 struct wl_resource *resource;
4473
4474 resource = wl_resource_create(client,
4475 &zwp_pointer_constraints_v1_interface,
4476 1, id);
4477
4478 wl_resource_set_implementation(resource, &pointer_constraints_interface,
4479 NULL, NULL);
4480}
4481
Jonas Ådahl30d61d82014-10-22 21:21:17 +02004482int
4483weston_input_init(struct weston_compositor *compositor)
4484{
4485 if (!wl_global_create(compositor->wl_display,
4486 &zwp_relative_pointer_manager_v1_interface, 1,
4487 compositor, bind_relative_pointer_manager))
4488 return -1;
4489
Jonas Ådahld3414f22016-07-22 17:56:31 +08004490 if (!wl_global_create(compositor->wl_display,
4491 &zwp_pointer_constraints_v1_interface, 1,
4492 NULL, bind_pointer_constraints))
4493 return -1;
4494
Jonas Ådahl30d61d82014-10-22 21:21:17 +02004495 return 0;
4496}