blob: 96cded47cd7fa5889f5bab5ae29efde32c10f849 [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
Alexandros Frantzis9448deb2017-11-16 18:20:58 +0200673weston_touch_send_down(struct weston_touch *touch, const struct timespec *time,
Quentin Glidiccde13452016-08-12 10:41:32 +0200674 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;
Alexandros Frantzis9448deb2017-11-16 18:20:58 +0200681 uint32_t msecs;
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300682
Quentin Glidiccde13452016-08-12 10:41:32 +0200683 if (!weston_touch_has_focus_resource(touch))
Bryce Harrington2c40d1d2016-02-02 10:18:48 -0800684 return;
685
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300686 weston_view_from_global_fixed(touch->focus, x, y, &sx, &sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400687
Neil Roberts96d790e2013-09-19 17:32:00 +0100688 resource_list = &touch->focus_resource_list;
Quentin Glidiccde13452016-08-12 10:41:32 +0200689 serial = wl_display_next_serial(display);
Alexandros Frantzis9448deb2017-11-16 18:20:58 +0200690 msecs = timespec_to_msec(time);
Quentin Glidiccde13452016-08-12 10:41:32 +0200691 wl_resource_for_each(resource, resource_list)
Alexandros Frantzis9448deb2017-11-16 18:20:58 +0200692 wl_touch_send_down(resource, serial, msecs,
Quentin Glidiccde13452016-08-12 10:41:32 +0200693 touch->focus->surface->resource,
694 touch_id, sx, sy);
695}
Neil Roberts96d790e2013-09-19 17:32:00 +0100696
Quentin Glidiccde13452016-08-12 10:41:32 +0200697static void
Alexandros Frantzis9448deb2017-11-16 18:20:58 +0200698default_grab_touch_down(struct weston_touch_grab *grab,
699 const struct timespec *time, int touch_id,
700 wl_fixed_t x, wl_fixed_t y)
Quentin Glidiccde13452016-08-12 10:41:32 +0200701{
702 weston_touch_send_down(grab->touch, time, touch_id, x, y);
703}
704
705/** Send wl_touch.up events to focused resources.
706 *
707 * \param touch The touch where the up events originates from.
708 * \param time The timestamp of the event
709 * \param touch_id The touch_id value of the event
710 *
711 * For every resource that is currently in focus, send a wl_touch.up event
712 * with the passed parameters. The focused resources are the wl_touch
713 * resources of the client which currently has the surface with touch focus.
714 */
715WL_EXPORT void
Alexandros Frantzis27a51b82017-11-16 18:20:59 +0200716weston_touch_send_up(struct weston_touch *touch, const struct timespec *time,
717 int touch_id)
Quentin Glidiccde13452016-08-12 10:41:32 +0200718{
719 struct wl_display *display = touch->seat->compositor->wl_display;
720 uint32_t serial;
721 struct wl_resource *resource;
722 struct wl_list *resource_list;
Alexandros Frantzis27a51b82017-11-16 18:20:59 +0200723 uint32_t msecs;
Quentin Glidiccde13452016-08-12 10:41:32 +0200724
725 if (!weston_touch_has_focus_resource(touch))
726 return;
727
728 resource_list = &touch->focus_resource_list;
729 serial = wl_display_next_serial(display);
Alexandros Frantzis27a51b82017-11-16 18:20:59 +0200730 msecs = timespec_to_msec(time);
Quentin Glidiccde13452016-08-12 10:41:32 +0200731 wl_resource_for_each(resource, resource_list)
Alexandros Frantzis27a51b82017-11-16 18:20:59 +0200732 wl_touch_send_up(resource, serial, msecs, touch_id);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400733}
734
Kristian Høgsberge329f362013-05-06 22:19:57 -0400735static void
736default_grab_touch_up(struct weston_touch_grab *grab,
Alexandros Frantzis27a51b82017-11-16 18:20:59 +0200737 const struct timespec *time, int touch_id)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400738{
Quentin Glidiccde13452016-08-12 10:41:32 +0200739 weston_touch_send_up(grab->touch, time, touch_id);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400740}
741
Quentin Glidiccde13452016-08-12 10:41:32 +0200742/** Send wl_touch.motion events to focused resources.
743 *
744 * \param touch The touch where the motion events originates from.
745 * \param time The timestamp of the event
746 * \param touch_id The touch_id value of the event
747 * \param x The x value of the event
748 * \param y The y value of the event
749 *
750 * For every resource that is currently in focus, send a wl_touch.motion event
751 * with the passed parameters. The focused resources are the wl_touch
752 * resources of the client which currently has the surface with touch focus.
753 */
754WL_EXPORT void
Alexandros Frantzis7d2abcf2017-11-16 18:21:00 +0200755weston_touch_send_motion(struct weston_touch *touch,
756 const struct timespec *time, int touch_id,
757 wl_fixed_t x, wl_fixed_t y)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400758{
Neil Roberts96d790e2013-09-19 17:32:00 +0100759 struct wl_resource *resource;
760 struct wl_list *resource_list;
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300761 wl_fixed_t sx, sy;
Alexandros Frantzis7d2abcf2017-11-16 18:21:00 +0200762 uint32_t msecs;
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300763
Quentin Glidiccde13452016-08-12 10:41:32 +0200764 if (!weston_touch_has_focus_resource(touch))
765 return;
766
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300767 weston_view_from_global_fixed(touch->focus, x, y, &sx, &sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400768
Neil Roberts96d790e2013-09-19 17:32:00 +0100769 resource_list = &touch->focus_resource_list;
Alexandros Frantzis7d2abcf2017-11-16 18:21:00 +0200770 msecs = timespec_to_msec(time);
Neil Roberts96d790e2013-09-19 17:32:00 +0100771 wl_resource_for_each(resource, resource_list) {
Alexandros Frantzis7d2abcf2017-11-16 18:21:00 +0200772 wl_touch_send_motion(resource, msecs,
Kristian Høgsberge329f362013-05-06 22:19:57 -0400773 touch_id, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400774 }
775}
776
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200777static void
Alexandros Frantzis7d2abcf2017-11-16 18:21:00 +0200778default_grab_touch_motion(struct weston_touch_grab *grab,
779 const struct timespec *time, int touch_id,
780 wl_fixed_t x, wl_fixed_t y)
Quentin Glidiccde13452016-08-12 10:41:32 +0200781{
782 weston_touch_send_motion(grab->touch, time, touch_id, x, y);
783}
784
785
786/** Send wl_touch.frame events to focused resources.
787 *
788 * \param touch The touch where the frame events originates from.
789 *
790 * For every resource that is currently in focus, send a wl_touch.frame event.
791 * The focused resources are the wl_touch resources of the client which
792 * currently has the surface with touch focus.
793 */
794WL_EXPORT void
795weston_touch_send_frame(struct weston_touch *touch)
Jonas Ådahl1679f232014-04-12 09:39:51 +0200796{
797 struct wl_resource *resource;
798
Quentin Glidiccde13452016-08-12 10:41:32 +0200799 if (!weston_touch_has_focus_resource(touch))
800 return;
801
802 wl_resource_for_each(resource, &touch->focus_resource_list)
Jonas Ådahl1679f232014-04-12 09:39:51 +0200803 wl_touch_send_frame(resource);
804}
805
806static void
Quentin Glidiccde13452016-08-12 10:41:32 +0200807default_grab_touch_frame(struct weston_touch_grab *grab)
808{
809 weston_touch_send_frame(grab->touch);
810}
811
812static void
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200813default_grab_touch_cancel(struct weston_touch_grab *grab)
814{
815}
816
Kristian Høgsberge329f362013-05-06 22:19:57 -0400817static const struct weston_touch_grab_interface default_touch_grab_interface = {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400818 default_grab_touch_down,
819 default_grab_touch_up,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200820 default_grab_touch_motion,
Jonas Ådahl1679f232014-04-12 09:39:51 +0200821 default_grab_touch_frame,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200822 default_grab_touch_cancel,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400823};
824
Quentin Glidiccde13452016-08-12 10:41:32 +0200825/** Check if the keyboard has focused resources.
826 *
827 * \param keyboard The keyboard to check for focused resources.
828 * \return Whether or not this keyboard has focused resources
829 */
830WL_EXPORT bool
831weston_keyboard_has_focus_resource(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400832{
Quentin Glidiccde13452016-08-12 10:41:32 +0200833 if (!keyboard->focus)
834 return false;
835
836 if (wl_list_empty(&keyboard->focus_resource_list))
837 return false;
838
839 return true;
840}
841
842/** Send wl_keyboard.key events to focused resources.
843 *
844 * \param keyboard The keyboard where the key events originates from.
845 * \param time The timestamp of the event
846 * \param key The key value of the event
847 * \param state The state enum value of the event
848 *
849 * For every resource that is currently in focus, send a wl_keyboard.key event
850 * with the passed parameters. The focused resources are the wl_keyboard
851 * resources of the client which currently has the surface with keyboard focus.
852 */
853WL_EXPORT void
854weston_keyboard_send_key(struct weston_keyboard *keyboard,
Alexandros Frantzis47e79c82017-11-16 18:20:57 +0200855 const struct timespec *time, uint32_t key,
Quentin Glidiccde13452016-08-12 10:41:32 +0200856 enum wl_keyboard_key_state state)
857{
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400858 struct wl_resource *resource;
Rob Bradford880ebc72013-07-22 17:31:38 +0100859 struct wl_display *display = keyboard->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400860 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +0100861 struct wl_list *resource_list;
Alexandros Frantzis47e79c82017-11-16 18:20:57 +0200862 uint32_t msecs;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400863
Quentin Glidiccde13452016-08-12 10:41:32 +0200864 if (!weston_keyboard_has_focus_resource(keyboard))
865 return;
866
Neil Roberts96d790e2013-09-19 17:32:00 +0100867 resource_list = &keyboard->focus_resource_list;
Quentin Glidiccde13452016-08-12 10:41:32 +0200868 serial = wl_display_next_serial(display);
Alexandros Frantzis47e79c82017-11-16 18:20:57 +0200869 msecs = timespec_to_msec(time);
Quentin Glidiccde13452016-08-12 10:41:32 +0200870 wl_resource_for_each(resource, resource_list)
Alexandros Frantzis47e79c82017-11-16 18:20:57 +0200871 wl_keyboard_send_key(resource, serial, msecs, key, state);
Quentin Glidiccde13452016-08-12 10:41:32 +0200872};
873
874static void
875default_grab_keyboard_key(struct weston_keyboard_grab *grab,
Alexandros Frantzis47e79c82017-11-16 18:20:57 +0200876 const struct timespec *time, uint32_t key,
877 uint32_t state)
Quentin Glidiccde13452016-08-12 10:41:32 +0200878{
879 weston_keyboard_send_key(grab->keyboard, time, key, state);
Neil Roberts96d790e2013-09-19 17:32:00 +0100880}
881
882static void
883send_modifiers_to_resource(struct weston_keyboard *keyboard,
884 struct wl_resource *resource,
885 uint32_t serial)
886{
887 wl_keyboard_send_modifiers(resource,
888 serial,
889 keyboard->modifiers.mods_depressed,
890 keyboard->modifiers.mods_latched,
891 keyboard->modifiers.mods_locked,
892 keyboard->modifiers.group);
893}
894
895static void
896send_modifiers_to_client_in_list(struct wl_client *client,
897 struct wl_list *list,
898 uint32_t serial,
899 struct weston_keyboard *keyboard)
900{
901 struct wl_resource *resource;
902
903 wl_resource_for_each(resource, list) {
904 if (wl_resource_get_client(resource) == client)
905 send_modifiers_to_resource(keyboard,
906 resource,
907 serial);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400908 }
909}
910
Jonas Ådahl2cbf2932015-07-22 12:05:38 +0800911static struct weston_pointer_client *
912find_pointer_client_for_surface(struct weston_pointer *pointer,
913 struct weston_surface *surface)
914{
915 struct wl_client *client;
916
917 if (!surface)
918 return NULL;
919
920 if (!surface->resource)
921 return NULL;
922
923 client = wl_resource_get_client(surface->resource);
924 return weston_pointer_get_pointer_client(pointer, client);
925}
926
927static struct weston_pointer_client *
928find_pointer_client_for_view(struct weston_pointer *pointer, struct weston_view *view)
929{
930 if (!view)
931 return NULL;
932
933 return find_pointer_client_for_surface(pointer, view->surface);
934}
935
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400936static struct wl_resource *
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400937find_resource_for_surface(struct wl_list *list, struct weston_surface *surface)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400938{
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400939 if (!surface)
940 return NULL;
941
Jason Ekstrand44a38632013-06-14 10:08:00 -0500942 if (!surface->resource)
943 return NULL;
Stefan Schmidtfda26522013-09-17 10:54:09 +0100944
Jason Ekstrand44a38632013-06-14 10:08:00 -0500945 return wl_resource_find_for_client(list, wl_resource_get_client(surface->resource));
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400946}
947
Quentin Glidiccde13452016-08-12 10:41:32 +0200948/** Send wl_keyboard.modifiers events to focused resources and pointer
949 * focused resources.
950 *
951 * \param keyboard The keyboard where the modifiers events originates from.
952 * \param serial The serial of the event
953 * \param mods_depressed The mods_depressed value of the event
954 * \param mods_latched The mods_latched value of the event
955 * \param mods_locked The mods_locked value of the event
956 * \param group The group value of the event
957 *
958 * For every resource that is currently in focus, send a wl_keyboard.modifiers
959 * event with the passed parameters. The focused resources are the wl_keyboard
960 * resources of the client which currently has the surface with keyboard focus.
961 * This also sends wl_keyboard.modifiers events to the wl_keyboard resources of
962 * the client having pointer focus (if different from the keyboard focus client).
963 */
964WL_EXPORT void
965weston_keyboard_send_modifiers(struct weston_keyboard *keyboard,
966 uint32_t serial, uint32_t mods_depressed,
967 uint32_t mods_latched,
968 uint32_t mods_locked, uint32_t group)
969{
970 struct weston_pointer *pointer =
971 weston_seat_get_pointer(keyboard->seat);
972
973 if (weston_keyboard_has_focus_resource(keyboard)) {
974 struct wl_list *resource_list;
975 struct wl_resource *resource;
976
977 resource_list = &keyboard->focus_resource_list;
978 wl_resource_for_each(resource, resource_list) {
979 wl_keyboard_send_modifiers(resource, serial,
980 mods_depressed, mods_latched,
981 mods_locked, group);
982 }
983 }
984
985 if (pointer && pointer->focus && pointer->focus->surface->resource &&
986 pointer->focus->surface != keyboard->focus) {
987 struct wl_client *pointer_client =
988 wl_resource_get_client(pointer->focus->surface->resource);
989
990 send_modifiers_to_client_in_list(pointer_client,
991 &keyboard->resource_list,
992 serial,
993 keyboard);
994 }
995}
996
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400997static void
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700998default_grab_keyboard_modifiers(struct weston_keyboard_grab *grab,
999 uint32_t serial, uint32_t mods_depressed,
1000 uint32_t mods_latched,
1001 uint32_t mods_locked, uint32_t group)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001002{
Quentin Glidiccde13452016-08-12 10:41:32 +02001003 weston_keyboard_send_modifiers(grab->keyboard, serial, mods_depressed,
1004 mods_latched, mods_locked, group);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001005}
1006
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02001007static void
1008default_grab_keyboard_cancel(struct weston_keyboard_grab *grab)
1009{
1010}
1011
Kristian Høgsberg29139d42013-04-18 15:25:39 -04001012static const struct weston_keyboard_grab_interface
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001013 default_keyboard_grab_interface = {
Kristian Høgsbergb27901c2013-10-28 15:32:02 -07001014 default_grab_keyboard_key,
1015 default_grab_keyboard_modifiers,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02001016 default_grab_keyboard_cancel,
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001017};
1018
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001019static void
1020pointer_unmap_sprite(struct weston_pointer *pointer)
1021{
Pekka Paalanenc557ff72014-11-12 16:42:52 +02001022 struct weston_surface *surface = pointer->sprite->surface;
1023
1024 if (weston_surface_is_mapped(surface))
1025 weston_surface_unmap(surface);
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001026
1027 wl_list_remove(&pointer->sprite_destroy_listener.link);
Quentin Glidic2edc3d52016-08-12 10:41:33 +02001028 surface->committed = NULL;
1029 surface->committed_private = NULL;
Pekka Paalanen8274d902014-08-06 19:36:51 +03001030 weston_surface_set_label_func(surface, NULL);
Jason Ekstranda7af7042013-10-12 22:38:11 -05001031 weston_view_destroy(pointer->sprite);
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001032 pointer->sprite = NULL;
1033}
1034
1035static void
1036pointer_handle_sprite_destroy(struct wl_listener *listener, void *data)
1037{
1038 struct weston_pointer *pointer =
1039 container_of(listener, struct weston_pointer,
1040 sprite_destroy_listener);
1041
1042 pointer->sprite = NULL;
1043}
1044
Jonas Ådahl3e12e632013-12-02 22:05:05 +01001045static void
1046weston_pointer_reset_state(struct weston_pointer *pointer)
1047{
1048 pointer->button_count = 0;
1049}
1050
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001051static void
1052weston_pointer_handle_output_destroy(struct wl_listener *listener, void *data);
1053
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001054WL_EXPORT struct weston_pointer *
Giulio Camuffocdb4d292013-11-14 23:42:53 +01001055weston_pointer_create(struct weston_seat *seat)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001056{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001057 struct weston_pointer *pointer;
1058
Peter Huttererf3d62272013-08-08 11:57:05 +10001059 pointer = zalloc(sizeof *pointer);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001060 if (pointer == NULL)
1061 return NULL;
1062
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001063 wl_list_init(&pointer->pointer_clients);
Giulio Camuffocdb4d292013-11-14 23:42:53 +01001064 weston_pointer_set_default_grab(pointer,
1065 seat->compositor->default_pointer_grab);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001066 wl_list_init(&pointer->focus_resource_listener.link);
1067 pointer->focus_resource_listener.notify = pointer_focus_resource_destroyed;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001068 pointer->default_grab.pointer = pointer;
1069 pointer->grab = &pointer->default_grab;
Giulio Camuffo6fcb3782013-11-14 23:42:50 +01001070 wl_signal_init(&pointer->motion_signal);
Emilio Pozuelo Monfortaa7a4762013-11-19 11:37:15 +01001071 wl_signal_init(&pointer->focus_signal);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001072 wl_list_init(&pointer->focus_view_listener.link);
Jonas Ådahl3eb4ddd2016-07-22 17:52:58 +08001073 wl_signal_init(&pointer->destroy_signal);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001074
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001075 pointer->sprite_destroy_listener.notify = pointer_handle_sprite_destroy;
1076
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001077 /* FIXME: Pick better co-ords. */
1078 pointer->x = wl_fixed_from_int(100);
1079 pointer->y = wl_fixed_from_int(100);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001080
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001081 pointer->output_destroy_listener.notify =
1082 weston_pointer_handle_output_destroy;
1083 wl_signal_add(&seat->compositor->output_destroyed_signal,
1084 &pointer->output_destroy_listener);
1085
Derek Foremanf9318d12015-05-11 15:40:11 -05001086 pointer->sx = wl_fixed_from_int(-1000000);
1087 pointer->sy = wl_fixed_from_int(-1000000);
1088
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001089 return pointer;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001090}
1091
1092WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001093weston_pointer_destroy(struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001094{
Jonas Ådahl3eb4ddd2016-07-22 17:52:58 +08001095 wl_signal_emit(&pointer->destroy_signal, pointer);
1096
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001097 if (pointer->sprite)
1098 pointer_unmap_sprite(pointer);
1099
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001100 /* XXX: What about pointer->resource_list? */
Neil Roberts96d790e2013-09-19 17:32:00 +01001101
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001102 wl_list_remove(&pointer->focus_resource_listener.link);
1103 wl_list_remove(&pointer->focus_view_listener.link);
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001104 wl_list_remove(&pointer->output_destroy_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001105 free(pointer);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001106}
1107
Giulio Camuffocdb4d292013-11-14 23:42:53 +01001108void
1109weston_pointer_set_default_grab(struct weston_pointer *pointer,
1110 const struct weston_pointer_grab_interface *interface)
1111{
1112 if (interface)
1113 pointer->default_grab.interface = interface;
1114 else
1115 pointer->default_grab.interface =
1116 &default_pointer_grab_interface;
1117}
1118
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001119WL_EXPORT struct weston_keyboard *
1120weston_keyboard_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001121{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001122 struct weston_keyboard *keyboard;
1123
Peter Huttererf3d62272013-08-08 11:57:05 +10001124 keyboard = zalloc(sizeof *keyboard);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001125 if (keyboard == NULL)
Neil Roberts96d790e2013-09-19 17:32:00 +01001126 return NULL;
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001127
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001128 wl_list_init(&keyboard->resource_list);
Neil Roberts96d790e2013-09-19 17:32:00 +01001129 wl_list_init(&keyboard->focus_resource_list);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001130 wl_list_init(&keyboard->focus_resource_listener.link);
1131 keyboard->focus_resource_listener.notify = keyboard_focus_resource_destroyed;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001132 wl_array_init(&keyboard->keys);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001133 keyboard->default_grab.interface = &default_keyboard_grab_interface;
1134 keyboard->default_grab.keyboard = keyboard;
1135 keyboard->grab = &keyboard->default_grab;
1136 wl_signal_init(&keyboard->focus_signal);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001137
1138 return keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001139}
1140
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001141static void
1142weston_xkb_info_destroy(struct weston_xkb_info *xkb_info);
1143
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001144WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001145weston_keyboard_destroy(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001146{
Alexandros Frantzis7a314d62018-01-26 18:47:56 +02001147 struct wl_resource *resource;
1148
1149 wl_resource_for_each(resource, &keyboard->resource_list) {
1150 wl_resource_set_user_data(resource, NULL);
1151 }
1152
1153 wl_resource_for_each(resource, &keyboard->focus_resource_list) {
1154 wl_resource_set_user_data(resource, NULL);
1155 }
1156
1157 wl_list_remove(&keyboard->resource_list);
1158 wl_list_remove(&keyboard->focus_resource_list);
Neil Roberts96d790e2013-09-19 17:32:00 +01001159
Derek Foreman185d1582017-06-28 11:17:23 -05001160 xkb_state_unref(keyboard->xkb_state.state);
1161 if (keyboard->xkb_info)
1162 weston_xkb_info_destroy(keyboard->xkb_info);
1163 xkb_keymap_unref(keyboard->pending_keymap);
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001164
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001165 wl_array_release(&keyboard->keys);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001166 wl_list_remove(&keyboard->focus_resource_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001167 free(keyboard);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001168}
1169
Jonas Ådahlcbfa7f72013-12-02 22:05:04 +01001170static void
1171weston_touch_reset_state(struct weston_touch *touch)
1172{
1173 touch->num_tp = 0;
1174}
1175
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001176WL_EXPORT struct weston_touch *
1177weston_touch_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001178{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001179 struct weston_touch *touch;
1180
Peter Huttererf3d62272013-08-08 11:57:05 +10001181 touch = zalloc(sizeof *touch);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001182 if (touch == NULL)
1183 return NULL;
1184
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001185 wl_list_init(&touch->resource_list);
Neil Roberts96d790e2013-09-19 17:32:00 +01001186 wl_list_init(&touch->focus_resource_list);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001187 wl_list_init(&touch->focus_view_listener.link);
1188 touch->focus_view_listener.notify = touch_focus_view_destroyed;
1189 wl_list_init(&touch->focus_resource_listener.link);
1190 touch->focus_resource_listener.notify = touch_focus_resource_destroyed;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001191 touch->default_grab.interface = &default_touch_grab_interface;
1192 touch->default_grab.touch = touch;
1193 touch->grab = &touch->default_grab;
1194 wl_signal_init(&touch->focus_signal);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001195
1196 return touch;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001197}
1198
1199WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001200weston_touch_destroy(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001201{
Alexandros Frantzisb0b598c2018-01-26 18:47:57 +02001202 struct wl_resource *resource;
Neil Roberts96d790e2013-09-19 17:32:00 +01001203
Alexandros Frantzisb0b598c2018-01-26 18:47:57 +02001204 wl_resource_for_each(resource, &touch->resource_list) {
1205 wl_resource_set_user_data(resource, NULL);
1206 }
1207
1208 wl_resource_for_each(resource, &touch->focus_resource_list) {
1209 wl_resource_set_user_data(resource, NULL);
1210 }
1211
1212 wl_list_remove(&touch->resource_list);
1213 wl_list_remove(&touch->focus_resource_list);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001214 wl_list_remove(&touch->focus_view_listener.link);
1215 wl_list_remove(&touch->focus_resource_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001216 free(touch);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001217}
1218
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001219static void
Kristian Høgsberge3148752013-05-06 23:19:49 -04001220seat_send_updated_caps(struct weston_seat *seat)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001221{
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001222 enum wl_seat_capability caps = 0;
Rob Bradford6e737f52013-09-06 17:48:19 +01001223 struct wl_resource *resource;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001224
Jonas Ådahld6e1c342013-10-17 23:04:05 +02001225 if (seat->pointer_device_count > 0)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001226 caps |= WL_SEAT_CAPABILITY_POINTER;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02001227 if (seat->keyboard_device_count > 0)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001228 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02001229 if (seat->touch_device_count > 0)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001230 caps |= WL_SEAT_CAPABILITY_TOUCH;
1231
Rob Bradford6e737f52013-09-06 17:48:19 +01001232 wl_resource_for_each(resource, &seat->base_resource_list) {
1233 wl_seat_send_capabilities(resource, caps);
Jason Ekstrand44a38632013-06-14 10:08:00 -05001234 }
Jason Ekstranda4ab5422014-04-02 19:53:45 -05001235 wl_signal_emit(&seat->updated_caps_signal, seat);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001236}
1237
Derek Foremanf9318d12015-05-11 15:40:11 -05001238
1239/** Clear the pointer focus
1240 *
1241 * \param pointer the pointer to clear focus for.
1242 *
1243 * This can be used to unset pointer focus and set the co-ordinates to the
1244 * arbitrary values we use for the no focus case.
1245 *
1246 * There's no requirement to use this function. For example, passing the
1247 * results of a weston_compositor_pick_view() directly to
1248 * weston_pointer_set_focus() will do the right thing when no view is found.
1249 */
1250WL_EXPORT void
1251weston_pointer_clear_focus(struct weston_pointer *pointer)
1252{
1253 weston_pointer_set_focus(pointer, NULL,
1254 wl_fixed_from_int(-1000000),
1255 wl_fixed_from_int(-1000000));
1256}
1257
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001258WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001259weston_pointer_set_focus(struct weston_pointer *pointer,
Jason Ekstranda7af7042013-10-12 22:38:11 -05001260 struct weston_view *view,
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001261 wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001262{
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001263 struct weston_pointer_client *pointer_client;
Derek Foreman1281a362015-07-31 16:55:32 -05001264 struct weston_keyboard *kbd = weston_seat_get_keyboard(pointer->seat);
Neil Roberts96d790e2013-09-19 17:32:00 +01001265 struct wl_resource *resource;
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001266 struct wl_resource *surface_resource;
Rob Bradford880ebc72013-07-22 17:31:38 +01001267 struct wl_display *display = pointer->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001268 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +01001269 struct wl_list *focus_resource_list;
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -08001270 int refocus = 0;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001271
1272 if ((!pointer->focus && view) ||
1273 (pointer->focus && !view) ||
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -08001274 (pointer->focus && pointer->focus->surface != view->surface) ||
1275 pointer->sx != sx || pointer->sy != sy)
1276 refocus = 1;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001277
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001278 if (pointer->focus_client && refocus) {
1279 focus_resource_list = &pointer->focus_client->pointer_resources;
1280 if (!wl_list_empty(focus_resource_list)) {
1281 serial = wl_display_next_serial(display);
1282 surface_resource = pointer->focus->surface->resource;
1283 wl_resource_for_each(resource, focus_resource_list) {
1284 wl_pointer_send_leave(resource, serial,
1285 surface_resource);
Peter Hutterer87743e92016-01-18 16:38:22 +10001286 pointer_send_frame(resource);
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001287 }
Neil Roberts96d790e2013-09-19 17:32:00 +01001288 }
1289
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001290 pointer->focus_client = NULL;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001291 }
1292
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001293 pointer_client = find_pointer_client_for_view(pointer, view);
1294 if (pointer_client && refocus) {
1295 struct wl_client *surface_client = pointer_client->client;
Neil Roberts96d790e2013-09-19 17:32:00 +01001296
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001297 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +01001298
Jason Ekstranda7af7042013-10-12 22:38:11 -05001299 if (kbd && kbd->focus != view->surface)
Kristian Høgsbergcb406f12013-10-09 10:54:03 -07001300 send_modifiers_to_client_in_list(surface_client,
1301 &kbd->resource_list,
1302 serial,
1303 kbd);
1304
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001305 pointer->focus_client = pointer_client;
Neil Roberts96d790e2013-09-19 17:32:00 +01001306
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001307 focus_resource_list = &pointer->focus_client->pointer_resources;
Neil Roberts96d790e2013-09-19 17:32:00 +01001308 wl_resource_for_each(resource, focus_resource_list) {
1309 wl_pointer_send_enter(resource,
1310 serial,
Jason Ekstranda7af7042013-10-12 22:38:11 -05001311 view->surface->resource,
Neil Roberts96d790e2013-09-19 17:32:00 +01001312 sx, sy);
Peter Hutterer87743e92016-01-18 16:38:22 +10001313 pointer_send_frame(resource);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001314 }
Neil Roberts96d790e2013-09-19 17:32:00 +01001315
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001316 pointer->focus_serial = serial;
1317 }
1318
Giulio Camuffo65a07f82013-12-06 12:46:27 +01001319 wl_list_remove(&pointer->focus_view_listener.link);
1320 wl_list_init(&pointer->focus_view_listener.link);
1321 wl_list_remove(&pointer->focus_resource_listener.link);
1322 wl_list_init(&pointer->focus_resource_listener.link);
Emilio Pozuelo Monfortaa7a4762013-11-19 11:37:15 +01001323 if (view)
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001324 wl_signal_add(&view->destroy_signal, &pointer->focus_view_listener);
Giulio Camuffo65a07f82013-12-06 12:46:27 +01001325 if (view && view->surface->resource)
1326 wl_resource_add_destroy_listener(view->surface->resource,
1327 &pointer->focus_resource_listener);
1328
1329 pointer->focus = view;
1330 pointer->focus_view_listener.notify = pointer_focus_view_destroyed;
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -08001331 pointer->sx = sx;
1332 pointer->sy = sy;
1333
Derek Foremanf9318d12015-05-11 15:40:11 -05001334 assert(view || sx == wl_fixed_from_int(-1000000));
1335 assert(view || sy == wl_fixed_from_int(-1000000));
1336
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001337 wl_signal_emit(&pointer->focus_signal, pointer);
1338}
1339
Neil Roberts96d790e2013-09-19 17:32:00 +01001340static void
1341send_enter_to_resource_list(struct wl_list *list,
1342 struct weston_keyboard *keyboard,
1343 struct weston_surface *surface,
1344 uint32_t serial)
1345{
1346 struct wl_resource *resource;
1347
1348 wl_resource_for_each(resource, list) {
1349 send_modifiers_to_resource(keyboard, resource, serial);
1350 wl_keyboard_send_enter(resource, serial,
1351 surface->resource,
1352 &keyboard->keys);
1353 }
1354}
1355
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001356WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -04001357weston_keyboard_set_focus(struct weston_keyboard *keyboard,
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -04001358 struct weston_surface *surface)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001359{
Quentin Glidic85d55542017-07-21 14:02:40 +02001360 struct weston_seat *seat = keyboard->seat;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001361 struct wl_resource *resource;
Rob Bradford880ebc72013-07-22 17:31:38 +01001362 struct wl_display *display = keyboard->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001363 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +01001364 struct wl_list *focus_resource_list;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001365
Neil Roberts96d790e2013-09-19 17:32:00 +01001366 focus_resource_list = &keyboard->focus_resource_list;
1367
1368 if (!wl_list_empty(focus_resource_list) && keyboard->focus != surface) {
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001369 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +01001370 wl_resource_for_each(resource, focus_resource_list) {
1371 wl_keyboard_send_leave(resource, serial,
1372 keyboard->focus->resource);
1373 }
1374 move_resources(&keyboard->resource_list, focus_resource_list);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001375 }
1376
Neil Roberts96d790e2013-09-19 17:32:00 +01001377 if (find_resource_for_surface(&keyboard->resource_list, surface) &&
1378 keyboard->focus != surface) {
1379 struct wl_client *surface_client =
1380 wl_resource_get_client(surface->resource);
1381
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001382 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +01001383
1384 move_resources_for_client(focus_resource_list,
1385 &keyboard->resource_list,
1386 surface_client);
1387 send_enter_to_resource_list(focus_resource_list,
1388 keyboard,
1389 surface,
1390 serial);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001391 keyboard->focus_serial = serial;
Giulio Camuffo65a07f82013-12-06 12:46:27 +01001392 }
1393
Quentin Glidic85d55542017-07-21 14:02:40 +02001394 if (seat->saved_kbd_focus) {
1395 wl_list_remove(&seat->saved_kbd_focus_listener.link);
1396 seat->saved_kbd_focus = NULL;
1397 }
1398
Giulio Camuffo65a07f82013-12-06 12:46:27 +01001399 wl_list_remove(&keyboard->focus_resource_listener.link);
1400 wl_list_init(&keyboard->focus_resource_listener.link);
1401 if (surface && surface->resource)
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001402 wl_resource_add_destroy_listener(surface->resource,
1403 &keyboard->focus_resource_listener);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001404
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001405 keyboard->focus = surface;
1406 wl_signal_emit(&keyboard->focus_signal, keyboard);
1407}
1408
Giulio Camuffoa20ca812014-11-22 11:16:56 +02001409/* Users of this function must manually manage the keyboard focus */
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001410WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -04001411weston_keyboard_start_grab(struct weston_keyboard *keyboard,
1412 struct weston_keyboard_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001413{
1414 keyboard->grab = grab;
1415 grab->keyboard = keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001416}
1417
1418WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -04001419weston_keyboard_end_grab(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001420{
1421 keyboard->grab = &keyboard->default_grab;
1422}
1423
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02001424static void
1425weston_keyboard_cancel_grab(struct weston_keyboard *keyboard)
1426{
1427 keyboard->grab->interface->cancel(keyboard->grab);
1428}
1429
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001430WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001431weston_pointer_start_grab(struct weston_pointer *pointer,
1432 struct weston_pointer_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001433{
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001434 pointer->grab = grab;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001435 grab->pointer = pointer;
Kristian Høgsbergda751b82013-07-04 00:58:07 -04001436 pointer->grab->interface->focus(pointer->grab);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001437}
1438
1439WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001440weston_pointer_end_grab(struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001441{
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001442 pointer->grab = &pointer->default_grab;
Kristian Høgsbergda751b82013-07-04 00:58:07 -04001443 pointer->grab->interface->focus(pointer->grab);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001444}
1445
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02001446static void
1447weston_pointer_cancel_grab(struct weston_pointer *pointer)
1448{
1449 pointer->grab->interface->cancel(pointer->grab);
1450}
1451
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001452WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -04001453weston_touch_start_grab(struct weston_touch *touch, struct weston_touch_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001454{
1455 touch->grab = grab;
1456 grab->touch = touch;
1457}
1458
1459WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -04001460weston_touch_end_grab(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001461{
1462 touch->grab = &touch->default_grab;
1463}
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001464
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02001465static void
1466weston_touch_cancel_grab(struct weston_touch *touch)
1467{
1468 touch->grab->interface->cancel(touch->grab);
1469}
1470
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001471static void
1472weston_pointer_clamp_for_output(struct weston_pointer *pointer,
1473 struct weston_output *output,
1474 wl_fixed_t *fx, wl_fixed_t *fy)
1475{
1476 int x, y;
1477
1478 x = wl_fixed_to_int(*fx);
1479 y = wl_fixed_to_int(*fy);
1480
1481 if (x < output->x)
1482 *fx = wl_fixed_from_int(output->x);
1483 else if (x >= output->x + output->width)
1484 *fx = wl_fixed_from_int(output->x +
1485 output->width - 1);
1486 if (y < output->y)
1487 *fy = wl_fixed_from_int(output->y);
1488 else if (y >= output->y + output->height)
1489 *fy = wl_fixed_from_int(output->y +
1490 output->height - 1);
1491}
1492
Rob Bradford806d8c02013-06-25 18:56:41 +01001493WL_EXPORT void
1494weston_pointer_clamp(struct weston_pointer *pointer, wl_fixed_t *fx, wl_fixed_t *fy)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001495{
Rob Bradford806d8c02013-06-25 18:56:41 +01001496 struct weston_compositor *ec = pointer->seat->compositor;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001497 struct weston_output *output, *prev = NULL;
1498 int x, y, old_x, old_y, valid = 0;
1499
1500 x = wl_fixed_to_int(*fx);
1501 y = wl_fixed_to_int(*fy);
Rob Bradford806d8c02013-06-25 18:56:41 +01001502 old_x = wl_fixed_to_int(pointer->x);
1503 old_y = wl_fixed_to_int(pointer->y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001504
1505 wl_list_for_each(output, &ec->output_list, link) {
Rob Bradford66bd9f52013-06-25 18:56:42 +01001506 if (pointer->seat->output && pointer->seat->output != output)
1507 continue;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001508 if (pixman_region32_contains_point(&output->region,
1509 x, y, NULL))
1510 valid = 1;
1511 if (pixman_region32_contains_point(&output->region,
1512 old_x, old_y, NULL))
1513 prev = output;
1514 }
1515
Rob Bradford66bd9f52013-06-25 18:56:42 +01001516 if (!prev)
1517 prev = pointer->seat->output;
1518
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001519 if (prev && !valid)
1520 weston_pointer_clamp_for_output(pointer, prev, fx, fy);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001521}
1522
Jonas Ådahld2510102014-10-05 21:39:14 +02001523static void
1524weston_pointer_move_to(struct weston_pointer *pointer,
1525 wl_fixed_t x, wl_fixed_t y)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001526{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001527 int32_t ix, iy;
1528
Rob Bradford806d8c02013-06-25 18:56:41 +01001529 weston_pointer_clamp (pointer, &x, &y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001530
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001531 pointer->x = x;
1532 pointer->y = y;
1533
1534 ix = wl_fixed_to_int(x);
1535 iy = wl_fixed_to_int(y);
1536
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001537 if (pointer->sprite) {
Jason Ekstranda7af7042013-10-12 22:38:11 -05001538 weston_view_set_position(pointer->sprite,
1539 ix - pointer->hotspot_x,
1540 iy - pointer->hotspot_y);
1541 weston_view_schedule_repaint(pointer->sprite);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001542 }
Giulio Camuffo6fcb3782013-11-14 23:42:50 +01001543
Giulio Camuffo1959ab82013-11-14 23:42:52 +01001544 pointer->grab->interface->focus(pointer->grab);
Giulio Camuffo6fcb3782013-11-14 23:42:50 +01001545 wl_signal_emit(&pointer->motion_signal, pointer);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001546}
1547
Jonas Ådahld2510102014-10-05 21:39:14 +02001548WL_EXPORT void
Jonas Ådahld2510102014-10-05 21:39:14 +02001549weston_pointer_move(struct weston_pointer *pointer,
1550 struct weston_pointer_motion_event *event)
1551{
1552 wl_fixed_t x, y;
1553
1554 weston_pointer_motion_to_abs(pointer, event, &x, &y);
1555 weston_pointer_move_to(pointer, x, y);
1556}
1557
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001558/** Verify if the pointer is in a valid position and move it if it isn't.
1559 */
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001560static void
1561weston_pointer_handle_output_destroy(struct wl_listener *listener, void *data)
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001562{
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001563 struct weston_pointer *pointer;
1564 struct weston_compositor *ec;
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001565 struct weston_output *output, *closest = NULL;
1566 int x, y, distance, min = INT_MAX;
1567 wl_fixed_t fx, fy;
1568
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001569 pointer = container_of(listener, struct weston_pointer,
1570 output_destroy_listener);
1571 ec = pointer->seat->compositor;
1572
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001573 x = wl_fixed_to_int(pointer->x);
1574 y = wl_fixed_to_int(pointer->y);
1575
1576 wl_list_for_each(output, &ec->output_list, link) {
1577 if (pixman_region32_contains_point(&output->region,
1578 x, y, NULL))
1579 return;
1580
1581 /* Aproximante the distance from the pointer to the center of
1582 * the output. */
1583 distance = abs(output->x + output->width / 2 - x) +
1584 abs(output->y + output->height / 2 - y);
1585 if (distance < min) {
1586 min = distance;
1587 closest = output;
1588 }
1589 }
1590
1591 /* Nothing to do if there's no output left. */
1592 if (!closest)
1593 return;
1594
1595 fx = pointer->x;
1596 fy = pointer->y;
1597
1598 weston_pointer_clamp_for_output(pointer, closest, &fx, &fy);
Jonas Ådahld2510102014-10-05 21:39:14 +02001599 weston_pointer_move_to(pointer, fx, fy);
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001600}
1601
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001602WL_EXPORT void
1603notify_motion(struct weston_seat *seat,
Alexandros Frantzis84b31f82017-11-24 18:01:46 +02001604 const struct timespec *time,
Jonas Ådahld2510102014-10-05 21:39:14 +02001605 struct weston_pointer_motion_event *event)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001606{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001607 struct weston_compositor *ec = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001608 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001609
1610 weston_compositor_wake(ec);
Jonas Ådahld2510102014-10-05 21:39:14 +02001611 pointer->grab->interface->motion(pointer->grab, time, event);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001612}
1613
Daniel Stone96d47c02013-11-19 11:37:12 +01001614static void
1615run_modifier_bindings(struct weston_seat *seat, uint32_t old, uint32_t new)
1616{
1617 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001618 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Daniel Stone96d47c02013-11-19 11:37:12 +01001619 uint32_t diff;
1620 unsigned int i;
1621 struct {
1622 uint32_t xkb;
1623 enum weston_keyboard_modifier weston;
1624 } mods[] = {
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001625 { keyboard->xkb_info->ctrl_mod, MODIFIER_CTRL },
1626 { keyboard->xkb_info->alt_mod, MODIFIER_ALT },
1627 { keyboard->xkb_info->super_mod, MODIFIER_SUPER },
1628 { keyboard->xkb_info->shift_mod, MODIFIER_SHIFT },
Daniel Stone96d47c02013-11-19 11:37:12 +01001629 };
1630
1631 diff = new & ~old;
1632 for (i = 0; i < ARRAY_LENGTH(mods); i++) {
1633 if (diff & (1 << mods[i].xkb))
1634 weston_compositor_run_modifier_binding(compositor,
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001635 keyboard,
Daniel Stone96d47c02013-11-19 11:37:12 +01001636 mods[i].weston,
1637 WL_KEYBOARD_KEY_STATE_PRESSED);
1638 }
1639
1640 diff = old & ~new;
1641 for (i = 0; i < ARRAY_LENGTH(mods); i++) {
1642 if (diff & (1 << mods[i].xkb))
1643 weston_compositor_run_modifier_binding(compositor,
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001644 keyboard,
Daniel Stone96d47c02013-11-19 11:37:12 +01001645 mods[i].weston,
1646 WL_KEYBOARD_KEY_STATE_RELEASED);
1647 }
1648}
1649
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001650WL_EXPORT void
Alexandros Frantzis84b31f82017-11-24 18:01:46 +02001651notify_motion_absolute(struct weston_seat *seat, const struct timespec *time,
1652 double x, double y)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001653{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001654 struct weston_compositor *ec = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001655 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Jonas Ådahld2510102014-10-05 21:39:14 +02001656 struct weston_pointer_motion_event event = { 0 };
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001657
1658 weston_compositor_wake(ec);
Jonas Ådahld2510102014-10-05 21:39:14 +02001659
1660 event = (struct weston_pointer_motion_event) {
1661 .mask = WESTON_POINTER_MOTION_ABS,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001662 .x = x,
1663 .y = y,
Jonas Ådahld2510102014-10-05 21:39:14 +02001664 };
1665
1666 pointer->grab->interface->motion(pointer->grab, time, &event);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001667}
1668
Jonas Ådahl94e2e2d2014-10-18 18:42:19 +02001669static unsigned int
1670peek_next_activate_serial(struct weston_compositor *c)
1671{
1672 unsigned serial = c->activate_serial + 1;
1673
1674 return serial == 0 ? 1 : serial;
1675}
1676
1677static void
1678inc_activate_serial(struct weston_compositor *c)
1679{
1680 c->activate_serial = peek_next_activate_serial (c);
1681}
1682
1683WL_EXPORT void
1684weston_view_activate(struct weston_view *view,
1685 struct weston_seat *seat,
1686 uint32_t flags)
1687{
1688 struct weston_compositor *compositor = seat->compositor;
1689
1690 if (flags & WESTON_ACTIVATE_FLAG_CLICKED) {
1691 view->click_to_activate_serial =
1692 peek_next_activate_serial(compositor);
1693 }
1694
1695 weston_seat_set_keyboard_focus(seat, view->surface);
1696}
1697
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001698WL_EXPORT void
Alexandros Frantzis215bedc2017-11-16 18:20:55 +02001699notify_button(struct weston_seat *seat, const struct timespec *time,
1700 int32_t button, enum wl_pointer_button_state state)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001701{
1702 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001703 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001704
1705 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001706 weston_compositor_idle_inhibit(compositor);
1707 if (pointer->button_count == 0) {
1708 pointer->grab_button = button;
Alexandros Frantzis215bedc2017-11-16 18:20:55 +02001709 pointer->grab_time = *time;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001710 pointer->grab_x = pointer->x;
1711 pointer->grab_y = pointer->y;
1712 }
1713 pointer->button_count++;
1714 } else {
1715 weston_compositor_idle_release(compositor);
1716 pointer->button_count--;
1717 }
1718
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001719 weston_compositor_run_button_binding(compositor, pointer, time, button,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001720 state);
1721
1722 pointer->grab->interface->button(pointer->grab, time, button, state);
1723
1724 if (pointer->button_count == 1)
1725 pointer->grab_serial =
1726 wl_display_get_serial(compositor->wl_display);
1727}
1728
1729WL_EXPORT void
Alexandros Frantzis80321942017-11-16 18:20:56 +02001730notify_axis(struct weston_seat *seat, const struct timespec *time,
Peter Hutterer89b6a492016-01-18 15:58:17 +10001731 struct weston_pointer_axis_event *event)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001732{
1733 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001734 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001735
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001736 weston_compositor_wake(compositor);
1737
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001738 if (weston_compositor_run_axis_binding(compositor, pointer,
Peter Hutterer89b6a492016-01-18 15:58:17 +10001739 time, event))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001740 return;
1741
Peter Hutterer89b6a492016-01-18 15:58:17 +10001742 pointer->grab->interface->axis(pointer->grab, time, event);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001743}
1744
Peter Hutterer87743e92016-01-18 16:38:22 +10001745WL_EXPORT void
1746notify_axis_source(struct weston_seat *seat, uint32_t source)
1747{
1748 struct weston_compositor *compositor = seat->compositor;
1749 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1750
1751 weston_compositor_wake(compositor);
1752
1753 pointer->grab->interface->axis_source(pointer->grab, source);
1754}
1755
1756WL_EXPORT void
1757notify_pointer_frame(struct weston_seat *seat)
1758{
1759 struct weston_compositor *compositor = seat->compositor;
1760 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1761
1762 weston_compositor_wake(compositor);
1763
1764 pointer->grab->interface->frame(pointer->grab);
1765}
1766
Giulio Camuffo6ef444d2014-08-28 19:44:09 +03001767WL_EXPORT int
1768weston_keyboard_set_locks(struct weston_keyboard *keyboard,
1769 uint32_t mask, uint32_t value)
1770{
Giulio Camuffo6ef444d2014-08-28 19:44:09 +03001771 uint32_t serial;
1772 xkb_mod_mask_t mods_depressed, mods_latched, mods_locked, group;
1773 xkb_mod_mask_t num, caps;
1774
1775 /* We don't want the leds to go out of sync with the actual state
1776 * so if the backend has no way to change the leds don't try to
1777 * change the state */
1778 if (!keyboard->seat->led_update)
1779 return -1;
1780
1781 mods_depressed = xkb_state_serialize_mods(keyboard->xkb_state.state,
1782 XKB_STATE_DEPRESSED);
1783 mods_latched = xkb_state_serialize_mods(keyboard->xkb_state.state,
1784 XKB_STATE_LATCHED);
1785 mods_locked = xkb_state_serialize_mods(keyboard->xkb_state.state,
1786 XKB_STATE_LOCKED);
1787 group = xkb_state_serialize_group(keyboard->xkb_state.state,
1788 XKB_STATE_EFFECTIVE);
1789
1790 num = (1 << keyboard->xkb_info->mod2_mod);
1791 caps = (1 << keyboard->xkb_info->caps_mod);
1792 if (mask & WESTON_NUM_LOCK) {
1793 if (value & WESTON_NUM_LOCK)
1794 mods_locked |= num;
1795 else
1796 mods_locked &= ~num;
1797 }
1798 if (mask & WESTON_CAPS_LOCK) {
1799 if (value & WESTON_CAPS_LOCK)
1800 mods_locked |= caps;
1801 else
1802 mods_locked &= ~caps;
1803 }
1804
1805 xkb_state_update_mask(keyboard->xkb_state.state, mods_depressed,
1806 mods_latched, mods_locked, 0, 0, group);
1807
1808 serial = wl_display_next_serial(
1809 keyboard->seat->compositor->wl_display);
1810 notify_modifiers(keyboard->seat, serial);
1811
1812 return 0;
Giulio Camuffo6ef444d2014-08-28 19:44:09 +03001813}
1814
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001815WL_EXPORT void
1816notify_modifiers(struct weston_seat *seat, uint32_t serial)
1817{
Derek Foreman1281a362015-07-31 16:55:32 -05001818 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001819 struct weston_keyboard_grab *grab = keyboard->grab;
1820 uint32_t mods_depressed, mods_latched, mods_locked, group;
1821 uint32_t mods_lookup;
1822 enum weston_led leds = 0;
1823 int changed = 0;
1824
1825 /* Serialize and update our internal state, checking to see if it's
1826 * different to the previous state. */
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001827 mods_depressed = xkb_state_serialize_mods(keyboard->xkb_state.state,
Ran Benita2e1968f2014-08-19 23:59:51 +03001828 XKB_STATE_MODS_DEPRESSED);
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001829 mods_latched = xkb_state_serialize_mods(keyboard->xkb_state.state,
Ran Benita2e1968f2014-08-19 23:59:51 +03001830 XKB_STATE_MODS_LATCHED);
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001831 mods_locked = xkb_state_serialize_mods(keyboard->xkb_state.state,
Ran Benita2e1968f2014-08-19 23:59:51 +03001832 XKB_STATE_MODS_LOCKED);
1833 group = xkb_state_serialize_layout(keyboard->xkb_state.state,
1834 XKB_STATE_LAYOUT_EFFECTIVE);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001835
Derek Foreman244e99e2015-06-03 15:53:26 -05001836 if (mods_depressed != keyboard->modifiers.mods_depressed ||
1837 mods_latched != keyboard->modifiers.mods_latched ||
1838 mods_locked != keyboard->modifiers.mods_locked ||
1839 group != keyboard->modifiers.group)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001840 changed = 1;
1841
Derek Foreman244e99e2015-06-03 15:53:26 -05001842 run_modifier_bindings(seat, keyboard->modifiers.mods_depressed,
Daniel Stone96d47c02013-11-19 11:37:12 +01001843 mods_depressed);
1844
Derek Foreman244e99e2015-06-03 15:53:26 -05001845 keyboard->modifiers.mods_depressed = mods_depressed;
1846 keyboard->modifiers.mods_latched = mods_latched;
1847 keyboard->modifiers.mods_locked = mods_locked;
1848 keyboard->modifiers.group = group;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001849
1850 /* And update the modifier_state for bindings. */
1851 mods_lookup = mods_depressed | mods_latched;
1852 seat->modifier_state = 0;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001853 if (mods_lookup & (1 << keyboard->xkb_info->ctrl_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001854 seat->modifier_state |= MODIFIER_CTRL;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001855 if (mods_lookup & (1 << keyboard->xkb_info->alt_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001856 seat->modifier_state |= MODIFIER_ALT;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001857 if (mods_lookup & (1 << keyboard->xkb_info->super_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001858 seat->modifier_state |= MODIFIER_SUPER;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001859 if (mods_lookup & (1 << keyboard->xkb_info->shift_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001860 seat->modifier_state |= MODIFIER_SHIFT;
1861
1862 /* Finally, notify the compositor that LEDs have changed. */
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001863 if (xkb_state_led_index_is_active(keyboard->xkb_state.state,
1864 keyboard->xkb_info->num_led))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001865 leds |= LED_NUM_LOCK;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001866 if (xkb_state_led_index_is_active(keyboard->xkb_state.state,
1867 keyboard->xkb_info->caps_led))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001868 leds |= LED_CAPS_LOCK;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001869 if (xkb_state_led_index_is_active(keyboard->xkb_state.state,
1870 keyboard->xkb_info->scroll_led))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001871 leds |= LED_SCROLL_LOCK;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001872 if (leds != keyboard->xkb_state.leds && seat->led_update)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001873 seat->led_update(seat, leds);
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001874 keyboard->xkb_state.leds = leds;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001875
1876 if (changed) {
1877 grab->interface->modifiers(grab,
1878 serial,
1879 keyboard->modifiers.mods_depressed,
1880 keyboard->modifiers.mods_latched,
1881 keyboard->modifiers.mods_locked,
1882 keyboard->modifiers.group);
1883 }
1884}
1885
1886static void
1887update_modifier_state(struct weston_seat *seat, uint32_t serial, uint32_t key,
1888 enum wl_keyboard_key_state state)
1889{
Derek Foreman1281a362015-07-31 16:55:32 -05001890 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001891 enum xkb_key_direction direction;
1892
1893 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
1894 direction = XKB_KEY_DOWN;
1895 else
1896 direction = XKB_KEY_UP;
1897
1898 /* Offset the keycode by 8, as the evdev XKB rules reflect X's
1899 * broken keycode system, which starts at 8. */
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001900 xkb_state_update_key(keyboard->xkb_state.state, key + 8, direction);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001901
1902 notify_modifiers(seat, serial);
1903}
Rui Matos65196bc2013-10-10 19:44:19 +02001904
1905static void
1906send_keymap(struct wl_resource *resource, struct weston_xkb_info *xkb_info)
1907{
1908 wl_keyboard_send_keymap(resource,
1909 WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
1910 xkb_info->keymap_fd,
1911 xkb_info->keymap_size);
1912}
1913
1914static void
1915send_modifiers(struct wl_resource *resource, uint32_t serial, struct weston_keyboard *keyboard)
1916{
1917 wl_keyboard_send_modifiers(resource, serial,
1918 keyboard->modifiers.mods_depressed,
1919 keyboard->modifiers.mods_latched,
1920 keyboard->modifiers.mods_locked,
1921 keyboard->modifiers.group);
1922}
1923
1924static struct weston_xkb_info *
1925weston_xkb_info_create(struct xkb_keymap *keymap);
Rui Matos65196bc2013-10-10 19:44:19 +02001926
1927static void
1928update_keymap(struct weston_seat *seat)
1929{
Derek Foreman1281a362015-07-31 16:55:32 -05001930 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Rui Matos65196bc2013-10-10 19:44:19 +02001931 struct wl_resource *resource;
1932 struct weston_xkb_info *xkb_info;
1933 struct xkb_state *state;
1934 xkb_mod_mask_t latched_mods;
1935 xkb_mod_mask_t locked_mods;
1936
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001937 xkb_info = weston_xkb_info_create(keyboard->pending_keymap);
Rui Matos65196bc2013-10-10 19:44:19 +02001938
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001939 xkb_keymap_unref(keyboard->pending_keymap);
1940 keyboard->pending_keymap = NULL;
Rui Matos65196bc2013-10-10 19:44:19 +02001941
1942 if (!xkb_info) {
1943 weston_log("failed to create XKB info\n");
1944 return;
1945 }
1946
1947 state = xkb_state_new(xkb_info->keymap);
1948 if (!state) {
1949 weston_log("failed to initialise XKB state\n");
1950 weston_xkb_info_destroy(xkb_info);
1951 return;
1952 }
1953
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001954 latched_mods = xkb_state_serialize_mods(keyboard->xkb_state.state,
1955 XKB_STATE_MODS_LATCHED);
1956 locked_mods = xkb_state_serialize_mods(keyboard->xkb_state.state,
1957 XKB_STATE_MODS_LOCKED);
Rui Matos65196bc2013-10-10 19:44:19 +02001958 xkb_state_update_mask(state,
1959 0, /* depressed */
1960 latched_mods,
1961 locked_mods,
1962 0, 0, 0);
1963
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001964 weston_xkb_info_destroy(keyboard->xkb_info);
1965 keyboard->xkb_info = xkb_info;
Rui Matos65196bc2013-10-10 19:44:19 +02001966
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001967 xkb_state_unref(keyboard->xkb_state.state);
1968 keyboard->xkb_state.state = state;
Rui Matos65196bc2013-10-10 19:44:19 +02001969
Derek Foremanbc91e542015-06-03 15:53:27 -05001970 wl_resource_for_each(resource, &keyboard->resource_list)
Rui Matos65196bc2013-10-10 19:44:19 +02001971 send_keymap(resource, xkb_info);
Derek Foremanbc91e542015-06-03 15:53:27 -05001972 wl_resource_for_each(resource, &keyboard->focus_resource_list)
Rui Matos65196bc2013-10-10 19:44:19 +02001973 send_keymap(resource, xkb_info);
1974
1975 notify_modifiers(seat, wl_display_next_serial(seat->compositor->wl_display));
1976
1977 if (!latched_mods && !locked_mods)
1978 return;
1979
Derek Foremanbc91e542015-06-03 15:53:27 -05001980 wl_resource_for_each(resource, &keyboard->resource_list)
1981 send_modifiers(resource, wl_display_get_serial(seat->compositor->wl_display), keyboard);
1982 wl_resource_for_each(resource, &keyboard->focus_resource_list)
1983 send_modifiers(resource, wl_display_get_serial(seat->compositor->wl_display), keyboard);
Rui Matos65196bc2013-10-10 19:44:19 +02001984}
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001985
1986WL_EXPORT void
Alexandros Frantzis47e79c82017-11-16 18:20:57 +02001987notify_key(struct weston_seat *seat, const struct timespec *time, uint32_t key,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001988 enum wl_keyboard_key_state state,
1989 enum weston_key_state_update update_state)
1990{
1991 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001992 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001993 struct weston_keyboard_grab *grab = keyboard->grab;
Pekka Paalanen86b53962014-11-19 13:43:32 +02001994 uint32_t *k, *end;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001995
1996 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001997 weston_compositor_idle_inhibit(compositor);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001998 } else {
1999 weston_compositor_idle_release(compositor);
2000 }
2001
Pekka Paalanen86b53962014-11-19 13:43:32 +02002002 end = keyboard->keys.data + keyboard->keys.size;
2003 for (k = keyboard->keys.data; k < end; k++) {
2004 if (*k == key) {
2005 /* Ignore server-generated repeats. */
2006 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
2007 return;
2008 *k = *--end;
2009 }
2010 }
2011 keyboard->keys.size = (void *) end - keyboard->keys.data;
2012 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
2013 k = wl_array_add(&keyboard->keys, sizeof *k);
2014 *k = key;
2015 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002016
2017 if (grab == &keyboard->default_grab ||
2018 grab == &keyboard->input_method_grab) {
Derek Foreman99a6a2d2015-07-15 13:00:43 -05002019 weston_compositor_run_key_binding(compositor, keyboard, time,
2020 key, state);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002021 grab = keyboard->grab;
2022 }
2023
2024 grab->interface->key(grab, time, key, state);
2025
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002026 if (keyboard->pending_keymap &&
Pekka Paalanen86b53962014-11-19 13:43:32 +02002027 keyboard->keys.size == 0)
Rui Matos65196bc2013-10-10 19:44:19 +02002028 update_keymap(seat);
2029
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002030 if (update_state == STATE_UPDATE_AUTOMATIC) {
2031 update_modifier_state(seat,
2032 wl_display_get_serial(compositor->wl_display),
2033 key,
2034 state);
2035 }
Giulio Camuffob6ddf6c2015-02-06 19:06:54 +02002036
Olivier Fourdandf84dbe2016-06-30 16:01:56 +02002037 keyboard->grab_serial = wl_display_get_serial(compositor->wl_display);
Giulio Camuffob6ddf6c2015-02-06 19:06:54 +02002038 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
Alexandros Frantzis47e79c82017-11-16 18:20:57 +02002039 keyboard->grab_time = *time;
Giulio Camuffob6ddf6c2015-02-06 19:06:54 +02002040 keyboard->grab_key = key;
2041 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002042}
2043
2044WL_EXPORT void
2045notify_pointer_focus(struct weston_seat *seat, struct weston_output *output,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02002046 double x, double y)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002047{
Derek Foreman1281a362015-07-31 16:55:32 -05002048 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
2049
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002050 if (output) {
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02002051 weston_pointer_move_to(pointer,
2052 wl_fixed_from_double(x),
2053 wl_fixed_from_double(y));
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002054 } else {
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04002055 /* FIXME: We should call weston_pointer_set_focus(seat,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002056 * NULL) here, but somehow that breaks re-entry... */
2057 }
2058}
2059
2060static void
2061destroy_device_saved_kbd_focus(struct wl_listener *listener, void *data)
2062{
2063 struct weston_seat *ws;
2064
2065 ws = container_of(listener, struct weston_seat,
2066 saved_kbd_focus_listener);
2067
2068 ws->saved_kbd_focus = NULL;
2069}
2070
2071WL_EXPORT void
2072notify_keyboard_focus_in(struct weston_seat *seat, struct wl_array *keys,
2073 enum weston_key_state_update update_state)
2074{
2075 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05002076 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -04002077 struct weston_surface *surface;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002078 uint32_t *k, serial;
2079
2080 serial = wl_display_next_serial(compositor->wl_display);
2081 wl_array_copy(&keyboard->keys, keys);
2082 wl_array_for_each(k, &keyboard->keys) {
2083 weston_compositor_idle_inhibit(compositor);
2084 if (update_state == STATE_UPDATE_AUTOMATIC)
2085 update_modifier_state(seat, serial, *k,
2086 WL_KEYBOARD_KEY_STATE_PRESSED);
2087 }
2088
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002089 surface = seat->saved_kbd_focus;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002090 if (surface) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002091 weston_keyboard_set_focus(keyboard, surface);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002092 }
2093}
2094
2095WL_EXPORT void
2096notify_keyboard_focus_out(struct weston_seat *seat)
2097{
2098 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05002099 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
2100 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Quentin Glidic85d55542017-07-21 14:02:40 +02002101 struct weston_surface *focus = keyboard->focus;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002102 uint32_t *k, serial;
2103
2104 serial = wl_display_next_serial(compositor->wl_display);
2105 wl_array_for_each(k, &keyboard->keys) {
2106 weston_compositor_idle_release(compositor);
2107 update_modifier_state(seat, serial, *k,
2108 WL_KEYBOARD_KEY_STATE_RELEASED);
2109 }
2110
2111 seat->modifier_state = 0;
2112
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002113 weston_keyboard_set_focus(keyboard, NULL);
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02002114 weston_keyboard_cancel_grab(keyboard);
Derek Foreman1281a362015-07-31 16:55:32 -05002115 if (pointer)
2116 weston_pointer_cancel_grab(pointer);
Quentin Glidic85d55542017-07-21 14:02:40 +02002117
2118 if (focus) {
2119 seat->saved_kbd_focus = focus;
2120 seat->saved_kbd_focus_listener.notify =
2121 destroy_device_saved_kbd_focus;
2122 wl_signal_add(&focus->destroy_signal,
2123 &seat->saved_kbd_focus_listener);
2124 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002125}
2126
Michael Fua2bb7912013-07-23 15:51:06 +08002127WL_EXPORT void
Derek Foreman4c93c082015-04-30 16:45:41 -05002128weston_touch_set_focus(struct weston_touch *touch, struct weston_view *view)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002129{
Neil Roberts96d790e2013-09-19 17:32:00 +01002130 struct wl_list *focus_resource_list;
2131
Derek Foreman4c93c082015-04-30 16:45:41 -05002132 focus_resource_list = &touch->focus_resource_list;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002133
Derek Foreman4c93c082015-04-30 16:45:41 -05002134 if (view && touch->focus &&
2135 touch->focus->surface == view->surface) {
2136 touch->focus = view;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002137 return;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002138 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002139
Derek Foreman4c93c082015-04-30 16:45:41 -05002140 wl_list_remove(&touch->focus_resource_listener.link);
2141 wl_list_init(&touch->focus_resource_listener.link);
2142 wl_list_remove(&touch->focus_view_listener.link);
2143 wl_list_init(&touch->focus_view_listener.link);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01002144
Neil Roberts96d790e2013-09-19 17:32:00 +01002145 if (!wl_list_empty(focus_resource_list)) {
Derek Foreman4c93c082015-04-30 16:45:41 -05002146 move_resources(&touch->resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01002147 focus_resource_list);
2148 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002149
Jason Ekstranda7af7042013-10-12 22:38:11 -05002150 if (view) {
Derek Foreman362656b2014-09-04 10:23:05 -05002151 struct wl_client *surface_client;
2152
2153 if (!view->surface->resource) {
Derek Foreman4c93c082015-04-30 16:45:41 -05002154 touch->focus = NULL;
Derek Foreman362656b2014-09-04 10:23:05 -05002155 return;
2156 }
2157
2158 surface_client = wl_resource_get_client(view->surface->resource);
Neil Roberts96d790e2013-09-19 17:32:00 +01002159 move_resources_for_client(focus_resource_list,
Derek Foreman4c93c082015-04-30 16:45:41 -05002160 &touch->resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01002161 surface_client);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01002162 wl_resource_add_destroy_listener(view->surface->resource,
Derek Foreman4c93c082015-04-30 16:45:41 -05002163 &touch->focus_resource_listener);
2164 wl_signal_add(&view->destroy_signal, &touch->focus_view_listener);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002165 }
Derek Foreman4c93c082015-04-30 16:45:41 -05002166 touch->focus = view;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002167}
2168
2169/**
2170 * notify_touch - emulates button touches and notifies surfaces accordingly.
2171 *
2172 * It assumes always the correct cycle sequence until it gets here: touch_down
2173 * → touch_update → ... → touch_update → touch_end. The driver is responsible
2174 * for sending along such order.
2175 *
2176 */
2177WL_EXPORT void
Alexandros Frantzis9448deb2017-11-16 18:20:58 +02002178notify_touch(struct weston_seat *seat, const struct timespec *time,
2179 int touch_id, double double_x, double double_y, int touch_type)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002180{
2181 struct weston_compositor *ec = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05002182 struct weston_touch *touch = weston_seat_get_touch(seat);
Kristian Høgsberge329f362013-05-06 22:19:57 -04002183 struct weston_touch_grab *grab = touch->grab;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002184 struct weston_view *ev;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002185 wl_fixed_t sx, sy;
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02002186 wl_fixed_t x = wl_fixed_from_double(double_x);
2187 wl_fixed_t y = wl_fixed_from_double(double_y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002188
2189 /* Update grab's global coordinates. */
Neil Roberts306fe082013-10-03 16:43:06 +01002190 if (touch_id == touch->grab_touch_id && touch_type != WL_TOUCH_UP) {
2191 touch->grab_x = x;
2192 touch->grab_y = y;
2193 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002194
2195 switch (touch_type) {
2196 case WL_TOUCH_DOWN:
2197 weston_compositor_idle_inhibit(ec);
2198
Jonas Ådahl9484b692013-12-02 22:05:03 +01002199 touch->num_tp++;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002200
Jason Ekstranda7af7042013-10-12 22:38:11 -05002201 /* the first finger down picks the view, and all further go
2202 * to that view for the remainder of the touch session i.e.
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002203 * until all touch points are up again. */
Jonas Ådahl9484b692013-12-02 22:05:03 +01002204 if (touch->num_tp == 1) {
Jason Ekstranda7af7042013-10-12 22:38:11 -05002205 ev = weston_compositor_pick_view(ec, x, y, &sx, &sy);
Derek Foreman4c93c082015-04-30 16:45:41 -05002206 weston_touch_set_focus(touch, ev);
Giulio Camuffo61ed7b62015-07-08 11:55:28 +03002207 } else if (!touch->focus) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002208 /* Unexpected condition: We have non-initial touch but
2209 * there is no focused surface.
2210 */
Chris Michael3f607d32015-10-07 11:59:49 -04002211 weston_log("touch event received with %d points down "
Jonas Ådahl9484b692013-12-02 22:05:03 +01002212 "but no surface focused\n", touch->num_tp);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002213 return;
2214 }
2215
Derek Foreman99a6a2d2015-07-15 13:00:43 -05002216 weston_compositor_run_touch_binding(ec, touch,
Kristian Høgsbergc8964012014-02-05 14:25:18 -08002217 time, touch_type);
2218
Giulio Camuffo61ed7b62015-07-08 11:55:28 +03002219 grab->interface->down(grab, time, touch_id, x, y);
Jonas Ådahl9484b692013-12-02 22:05:03 +01002220 if (touch->num_tp == 1) {
Rusty Lynchf1407ff2013-08-08 21:13:57 -07002221 touch->grab_serial =
2222 wl_display_get_serial(ec->wl_display);
Neil Roberts306fe082013-10-03 16:43:06 +01002223 touch->grab_touch_id = touch_id;
Alexandros Frantzis9448deb2017-11-16 18:20:58 +02002224 touch->grab_time = *time;
Rusty Lynchf1407ff2013-08-08 21:13:57 -07002225 touch->grab_x = x;
2226 touch->grab_y = y;
2227 }
2228
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002229 break;
2230 case WL_TOUCH_MOTION:
Jason Ekstranda7af7042013-10-12 22:38:11 -05002231 ev = touch->focus;
2232 if (!ev)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002233 break;
2234
Alexandros Frantzis7d2abcf2017-11-16 18:21:00 +02002235 grab->interface->motion(grab, time, touch_id, x, y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002236 break;
2237 case WL_TOUCH_UP:
Kristian Høgsberga30e29a2014-01-08 22:29:20 -08002238 if (touch->num_tp == 0) {
2239 /* This can happen if we start out with one or
2240 * more fingers on the touch screen, in which
2241 * case we didn't get the corresponding down
2242 * event. */
2243 weston_log("unmatched touch up event\n");
2244 break;
2245 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002246 weston_compositor_idle_release(ec);
Jonas Ådahl9484b692013-12-02 22:05:03 +01002247 touch->num_tp--;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002248
Alexandros Frantzis27a51b82017-11-16 18:20:59 +02002249 grab->interface->up(grab, time, touch_id);
Jonas Ådahl9484b692013-12-02 22:05:03 +01002250 if (touch->num_tp == 0)
Derek Foreman4c93c082015-04-30 16:45:41 -05002251 weston_touch_set_focus(touch, NULL);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002252 break;
2253 }
2254}
2255
Jonas Ådahl1679f232014-04-12 09:39:51 +02002256WL_EXPORT void
2257notify_touch_frame(struct weston_seat *seat)
2258{
Derek Foreman1281a362015-07-31 16:55:32 -05002259 struct weston_touch *touch = weston_seat_get_touch(seat);
Jonas Ådahl1679f232014-04-12 09:39:51 +02002260 struct weston_touch_grab *grab = touch->grab;
2261
2262 grab->interface->frame(grab);
2263}
2264
Derek Foreman3cc004a2015-11-06 15:56:09 -06002265WL_EXPORT void
2266notify_touch_cancel(struct weston_seat *seat)
2267{
2268 struct weston_touch *touch = weston_seat_get_touch(seat);
2269 struct weston_touch_grab *grab = touch->grab;
2270
2271 grab->interface->cancel(grab);
2272}
2273
Pekka Paalanen8274d902014-08-06 19:36:51 +03002274static int
2275pointer_cursor_surface_get_label(struct weston_surface *surface,
2276 char *buf, size_t len)
2277{
2278 return snprintf(buf, len, "cursor");
2279}
2280
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002281static void
Quentin Glidic2edc3d52016-08-12 10:41:33 +02002282pointer_cursor_surface_committed(struct weston_surface *es,
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06002283 int32_t dx, int32_t dy)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002284{
Quentin Glidic2edc3d52016-08-12 10:41:33 +02002285 struct weston_pointer *pointer = es->committed_private;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002286 int x, y;
2287
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06002288 if (es->width == 0)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002289 return;
2290
Jason Ekstranda7af7042013-10-12 22:38:11 -05002291 assert(es == pointer->sprite->surface);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002292
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002293 pointer->hotspot_x -= dx;
2294 pointer->hotspot_y -= dy;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002295
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002296 x = wl_fixed_to_int(pointer->x) - pointer->hotspot_x;
2297 y = wl_fixed_to_int(pointer->y) - pointer->hotspot_y;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002298
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06002299 weston_view_set_position(pointer->sprite, x, y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002300
2301 empty_region(&es->pending.input);
Ander Conselvan de Oliveira23900f72014-01-31 16:07:51 +02002302 empty_region(&es->input);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002303
2304 if (!weston_surface_is_mapped(es)) {
Giulio Camuffo412e6a52014-07-09 22:12:56 +03002305 weston_layer_entry_insert(&es->compositor->cursor_layer.view_list,
2306 &pointer->sprite->layer_link);
Jason Ekstranda7af7042013-10-12 22:38:11 -05002307 weston_view_update_transform(pointer->sprite);
Armin Krezovićf8486c32016-06-30 06:04:28 +02002308 es->is_mapped = true;
2309 pointer->sprite->is_mapped = true;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002310 }
2311}
2312
2313static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002314pointer_set_cursor(struct wl_client *client, struct wl_resource *resource,
2315 uint32_t serial, struct wl_resource *surface_resource,
2316 int32_t x, int32_t y)
2317{
Jason Ekstrand44a38632013-06-14 10:08:00 -05002318 struct weston_pointer *pointer = wl_resource_get_user_data(resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002319 struct weston_surface *surface = NULL;
2320
2321 if (surface_resource)
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05002322 surface = wl_resource_get_user_data(surface_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002323
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002324 if (pointer->focus == NULL)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002325 return;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002326 /* pointer->focus->surface->resource can be NULL. Surfaces like the
Giulio Camuffo1fd4b012013-06-20 18:13:07 +02002327 black_surface used in shell.c for fullscreen don't have
2328 a resource, but can still have focus */
Jason Ekstranda7af7042013-10-12 22:38:11 -05002329 if (pointer->focus->surface->resource == NULL)
Giulio Camuffo1fd4b012013-06-20 18:13:07 +02002330 return;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002331 if (wl_resource_get_client(pointer->focus->surface->resource) != client)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002332 return;
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002333 if (pointer->focus_serial - serial > UINT32_MAX / 2)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002334 return;
2335
Derek Foreman4e53c532015-03-23 10:55:32 -05002336 if (!surface) {
2337 if (pointer->sprite)
2338 pointer_unmap_sprite(pointer);
2339 return;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002340 }
2341
Jonas Ådahlb4070242015-03-18 15:08:03 +08002342 if (pointer->sprite && pointer->sprite->surface == surface &&
2343 pointer->hotspot_x == x && pointer->hotspot_y == y)
2344 return;
2345
Derek Foreman4e53c532015-03-23 10:55:32 -05002346 if (!pointer->sprite || pointer->sprite->surface != surface) {
2347 if (weston_surface_set_role(surface, "wl_pointer-cursor",
2348 resource,
2349 WL_POINTER_ERROR_ROLE) < 0)
2350 return;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002351
Derek Foreman4e53c532015-03-23 10:55:32 -05002352 if (pointer->sprite)
2353 pointer_unmap_sprite(pointer);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002354
Derek Foreman4e53c532015-03-23 10:55:32 -05002355 wl_signal_add(&surface->destroy_signal,
2356 &pointer->sprite_destroy_listener);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002357
Quentin Glidic2edc3d52016-08-12 10:41:33 +02002358 surface->committed = pointer_cursor_surface_committed;
2359 surface->committed_private = pointer;
Derek Foreman4e53c532015-03-23 10:55:32 -05002360 weston_surface_set_label_func(surface,
2361 pointer_cursor_surface_get_label);
2362 pointer->sprite = weston_view_create(surface);
2363 }
2364
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002365 pointer->hotspot_x = x;
2366 pointer->hotspot_y = y;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002367
Jonas Ådahl16fe4dc2014-09-08 19:33:41 +02002368 if (surface->buffer_ref.buffer) {
Quentin Glidic2edc3d52016-08-12 10:41:33 +02002369 pointer_cursor_surface_committed(surface, 0, 0);
Jonas Ådahl16fe4dc2014-09-08 19:33:41 +02002370 weston_view_schedule_repaint(pointer->sprite);
2371 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002372}
2373
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002374static void
2375pointer_release(struct wl_client *client, struct wl_resource *resource)
2376{
2377 wl_resource_destroy(resource);
2378}
2379
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002380static const struct wl_pointer_interface pointer_interface = {
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002381 pointer_set_cursor,
2382 pointer_release
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002383};
2384
2385static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002386seat_get_pointer(struct wl_client *client, struct wl_resource *resource,
2387 uint32_t id)
2388{
Jason Ekstrand44a38632013-06-14 10:08:00 -05002389 struct weston_seat *seat = wl_resource_get_user_data(resource);
Derek Foreman1281a362015-07-31 16:55:32 -05002390 /* We use the pointer_state directly, which means we'll
2391 * give a wl_pointer if the seat has ever had one - even though
2392 * the spec explicitly states that this request only takes effect
2393 * if the seat has the pointer capability.
2394 *
2395 * This prevents a race between the compositor sending new
2396 * capabilities and the client trying to use the old ones.
2397 */
2398 struct weston_pointer *pointer = seat->pointer_state;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002399 struct wl_resource *cr;
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08002400 struct weston_pointer_client *pointer_client;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002401
Derek Foreman1281a362015-07-31 16:55:32 -05002402 if (!pointer)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002403 return;
2404
Jason Ekstranda85118c2013-06-27 20:17:02 -05002405 cr = wl_resource_create(client, &wl_pointer_interface,
2406 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07002407 if (cr == NULL) {
2408 wl_client_post_no_memory(client);
2409 return;
2410 }
2411
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08002412 pointer_client = weston_pointer_ensure_pointer_client(pointer, client);
2413 if (!pointer_client) {
2414 wl_client_post_no_memory(client);
2415 return;
2416 }
2417
2418 wl_list_insert(&pointer_client->pointer_resources,
2419 wl_resource_get_link(cr));
Derek Foreman1281a362015-07-31 16:55:32 -05002420 wl_resource_set_implementation(cr, &pointer_interface, pointer,
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08002421 unbind_pointer_client_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002422
Derek Foreman1281a362015-07-31 16:55:32 -05002423 if (pointer->focus && pointer->focus->surface->resource &&
2424 wl_resource_get_client(pointer->focus->surface->resource) == client) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002425 wl_fixed_t sx, sy;
2426
Derek Foreman1281a362015-07-31 16:55:32 -05002427 weston_view_from_global_fixed(pointer->focus,
2428 pointer->x,
2429 pointer->y,
Jason Ekstranda7af7042013-10-12 22:38:11 -05002430 &sx, &sy);
Neil Roberts96d790e2013-09-19 17:32:00 +01002431
Neil Roberts96d790e2013-09-19 17:32:00 +01002432 wl_pointer_send_enter(cr,
Derek Foreman1281a362015-07-31 16:55:32 -05002433 pointer->focus_serial,
2434 pointer->focus->surface->resource,
Neil Roberts96d790e2013-09-19 17:32:00 +01002435 sx, sy);
Peter Hutterer87743e92016-01-18 16:38:22 +10002436 pointer_send_frame(cr);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002437 }
2438}
2439
2440static void
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002441keyboard_release(struct wl_client *client, struct wl_resource *resource)
2442{
2443 wl_resource_destroy(resource);
2444}
2445
2446static const struct wl_keyboard_interface keyboard_interface = {
2447 keyboard_release
2448};
2449
Derek Foreman280e7dd2014-10-03 13:13:42 -05002450static bool
Neil Roberts96d790e2013-09-19 17:32:00 +01002451should_send_modifiers_to_client(struct weston_seat *seat,
2452 struct wl_client *client)
2453{
Derek Foreman1281a362015-07-31 16:55:32 -05002454 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
2455 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
2456
2457 if (keyboard &&
2458 keyboard->focus &&
2459 keyboard->focus->resource &&
2460 wl_resource_get_client(keyboard->focus->resource) == client)
Derek Foreman280e7dd2014-10-03 13:13:42 -05002461 return true;
Neil Roberts96d790e2013-09-19 17:32:00 +01002462
Derek Foreman1281a362015-07-31 16:55:32 -05002463 if (pointer &&
2464 pointer->focus &&
2465 pointer->focus->surface->resource &&
2466 wl_resource_get_client(pointer->focus->surface->resource) == client)
Derek Foreman280e7dd2014-10-03 13:13:42 -05002467 return true;
Neil Roberts96d790e2013-09-19 17:32:00 +01002468
Derek Foreman280e7dd2014-10-03 13:13:42 -05002469 return false;
Neil Roberts96d790e2013-09-19 17:32:00 +01002470}
2471
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002472static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002473seat_get_keyboard(struct wl_client *client, struct wl_resource *resource,
2474 uint32_t id)
2475{
Jason Ekstrand44a38632013-06-14 10:08:00 -05002476 struct weston_seat *seat = wl_resource_get_user_data(resource);
Derek Foreman1281a362015-07-31 16:55:32 -05002477 /* We use the keyboard_state directly, which means we'll
2478 * give a wl_keyboard if the seat has ever had one - even though
2479 * the spec explicitly states that this request only takes effect
2480 * if the seat has the keyboard capability.
2481 *
2482 * This prevents a race between the compositor sending new
2483 * capabilities and the client trying to use the old ones.
2484 */
2485 struct weston_keyboard *keyboard = seat->keyboard_state;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002486 struct wl_resource *cr;
2487
Derek Foreman345c9f32015-06-03 15:53:28 -05002488 if (!keyboard)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002489 return;
2490
Jason Ekstranda85118c2013-06-27 20:17:02 -05002491 cr = wl_resource_create(client, &wl_keyboard_interface,
2492 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07002493 if (cr == NULL) {
2494 wl_client_post_no_memory(client);
2495 return;
2496 }
2497
Neil Roberts96d790e2013-09-19 17:32:00 +01002498 /* May be moved to focused list later by either
2499 * weston_keyboard_set_focus or directly if this client is already
2500 * focused */
Derek Foreman345c9f32015-06-03 15:53:28 -05002501 wl_list_insert(&keyboard->resource_list, wl_resource_get_link(cr));
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002502 wl_resource_set_implementation(cr, &keyboard_interface,
Alexandros Frantzis7a314d62018-01-26 18:47:56 +02002503 keyboard, unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002504
Jonny Lamb66a41a02014-08-12 14:58:25 +02002505 if (wl_resource_get_version(cr) >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) {
2506 wl_keyboard_send_repeat_info(cr,
2507 seat->compositor->kb_repeat_rate,
2508 seat->compositor->kb_repeat_delay);
2509 }
Jasper St. Pierred8c6aeb2014-08-04 13:43:24 -04002510
Derek Foreman185d1582017-06-28 11:17:23 -05002511 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
2512 keyboard->xkb_info->keymap_fd,
2513 keyboard->xkb_info->keymap_size);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002514
Neil Roberts96d790e2013-09-19 17:32:00 +01002515 if (should_send_modifiers_to_client(seat, client)) {
Derek Foreman345c9f32015-06-03 15:53:28 -05002516 send_modifiers_to_resource(keyboard,
Neil Roberts96d790e2013-09-19 17:32:00 +01002517 cr,
Derek Foreman345c9f32015-06-03 15:53:28 -05002518 keyboard->focus_serial);
Neil Roberts96d790e2013-09-19 17:32:00 +01002519 }
2520
Derek Foreman345c9f32015-06-03 15:53:28 -05002521 if (keyboard->focus && keyboard->focus->resource &&
2522 wl_resource_get_client(keyboard->focus->resource) == client) {
Neil Roberts96d790e2013-09-19 17:32:00 +01002523 struct weston_surface *surface =
Derek Foreman345c9f32015-06-03 15:53:28 -05002524 (struct weston_surface *)keyboard->focus;
Neil Roberts96d790e2013-09-19 17:32:00 +01002525
2526 wl_list_remove(wl_resource_get_link(cr));
Derek Foreman345c9f32015-06-03 15:53:28 -05002527 wl_list_insert(&keyboard->focus_resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01002528 wl_resource_get_link(cr));
2529 wl_keyboard_send_enter(cr,
Derek Foreman345c9f32015-06-03 15:53:28 -05002530 keyboard->focus_serial,
Neil Roberts96d790e2013-09-19 17:32:00 +01002531 surface->resource,
Derek Foreman345c9f32015-06-03 15:53:28 -05002532 &keyboard->keys);
Neil Roberts96d790e2013-09-19 17:32:00 +01002533
2534 /* If this is the first keyboard resource for this
2535 * client... */
Derek Foreman345c9f32015-06-03 15:53:28 -05002536 if (keyboard->focus_resource_list.prev ==
Neil Roberts96d790e2013-09-19 17:32:00 +01002537 wl_resource_get_link(cr))
2538 wl_data_device_set_keyboard_focus(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002539 }
2540}
2541
2542static void
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002543touch_release(struct wl_client *client, struct wl_resource *resource)
2544{
2545 wl_resource_destroy(resource);
2546}
2547
2548static const struct wl_touch_interface touch_interface = {
2549 touch_release
2550};
2551
2552static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002553seat_get_touch(struct wl_client *client, struct wl_resource *resource,
2554 uint32_t id)
2555{
Jason Ekstrand44a38632013-06-14 10:08:00 -05002556 struct weston_seat *seat = wl_resource_get_user_data(resource);
Derek Foreman1281a362015-07-31 16:55:32 -05002557 /* We use the touch_state directly, which means we'll
2558 * give a wl_touch if the seat has ever had one - even though
2559 * the spec explicitly states that this request only takes effect
2560 * if the seat has the touch capability.
2561 *
2562 * This prevents a race between the compositor sending new
2563 * capabilities and the client trying to use the old ones.
2564 */
2565 struct weston_touch *touch = seat->touch_state;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002566 struct wl_resource *cr;
2567
Derek Foreman1281a362015-07-31 16:55:32 -05002568 if (!touch)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002569 return;
2570
Jason Ekstranda85118c2013-06-27 20:17:02 -05002571 cr = wl_resource_create(client, &wl_touch_interface,
2572 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07002573 if (cr == NULL) {
2574 wl_client_post_no_memory(client);
2575 return;
2576 }
2577
Derek Foreman1281a362015-07-31 16:55:32 -05002578 if (touch->focus &&
2579 wl_resource_get_client(touch->focus->surface->resource) == client) {
Chokshi, Mituld6697142015-10-09 08:28:47 +00002580 wl_list_insert(&touch->focus_resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01002581 wl_resource_get_link(cr));
2582 } else {
Chokshi, Mituld6697142015-10-09 08:28:47 +00002583 wl_list_insert(&touch->resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01002584 wl_resource_get_link(cr));
2585 }
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002586 wl_resource_set_implementation(cr, &touch_interface,
Alexandros Frantzisb0b598c2018-01-26 18:47:57 +02002587 touch, unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002588}
2589
Quentin Glidicaab1d362016-03-13 17:49:08 +01002590static void
2591seat_release(struct wl_client *client, struct wl_resource *resource)
2592{
2593 wl_resource_destroy(resource);
2594}
2595
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002596static const struct wl_seat_interface seat_interface = {
2597 seat_get_pointer,
2598 seat_get_keyboard,
2599 seat_get_touch,
Quentin Glidicaab1d362016-03-13 17:49:08 +01002600 seat_release,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002601};
2602
2603static void
2604bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
2605{
Kristian Høgsberge3148752013-05-06 23:19:49 -04002606 struct weston_seat *seat = data;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002607 struct wl_resource *resource;
2608 enum wl_seat_capability caps = 0;
2609
Jason Ekstranda85118c2013-06-27 20:17:02 -05002610 resource = wl_resource_create(client,
Derek Foreman1909c102015-11-26 14:17:47 -06002611 &wl_seat_interface, version, id);
Jason Ekstrand44a38632013-06-14 10:08:00 -05002612 wl_list_insert(&seat->base_resource_list, wl_resource_get_link(resource));
Jason Ekstranda85118c2013-06-27 20:17:02 -05002613 wl_resource_set_implementation(resource, &seat_interface, data,
2614 unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002615
Derek Foreman1281a362015-07-31 16:55:32 -05002616 if (weston_seat_get_pointer(seat))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002617 caps |= WL_SEAT_CAPABILITY_POINTER;
Derek Foreman1281a362015-07-31 16:55:32 -05002618 if (weston_seat_get_keyboard(seat))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002619 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
Derek Foreman1281a362015-07-31 16:55:32 -05002620 if (weston_seat_get_touch(seat))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002621 caps |= WL_SEAT_CAPABILITY_TOUCH;
2622
2623 wl_seat_send_capabilities(resource, caps);
Jasper St. Pierre0013a292014-08-07 16:43:11 -04002624 if (version >= WL_SEAT_NAME_SINCE_VERSION)
Rob Bradforde445ae62013-05-31 18:09:51 +01002625 wl_seat_send_name(resource, seat->seat_name);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002626}
2627
Jonas Ådahl30d61d82014-10-22 21:21:17 +02002628static void
2629relative_pointer_destroy(struct wl_client *client,
2630 struct wl_resource *resource)
2631{
2632 wl_resource_destroy(resource);
2633}
2634
2635static const struct zwp_relative_pointer_v1_interface relative_pointer_interface = {
2636 relative_pointer_destroy
2637};
2638
2639static void
2640relative_pointer_manager_destroy(struct wl_client *client,
2641 struct wl_resource *resource)
2642{
2643 wl_resource_destroy(resource);
2644}
2645
2646static void
2647relative_pointer_manager_get_relative_pointer(struct wl_client *client,
2648 struct wl_resource *resource,
2649 uint32_t id,
2650 struct wl_resource *pointer_resource)
2651{
2652 struct weston_pointer *pointer =
2653 wl_resource_get_user_data(pointer_resource);
2654 struct weston_pointer_client *pointer_client;
2655 struct wl_resource *cr;
2656
2657 cr = wl_resource_create(client, &zwp_relative_pointer_v1_interface,
2658 wl_resource_get_version(resource), id);
2659 if (cr == NULL) {
2660 wl_client_post_no_memory(client);
2661 return;
2662 }
2663
2664 pointer_client = weston_pointer_ensure_pointer_client(pointer, client);
2665 if (!pointer_client) {
2666 wl_client_post_no_memory(client);
2667 return;
2668 }
2669
2670 wl_list_insert(&pointer_client->relative_pointer_resources,
2671 wl_resource_get_link(cr));
2672 wl_resource_set_implementation(cr, &relative_pointer_interface,
2673 pointer,
2674 unbind_pointer_client_resource);
2675}
2676
2677static const struct zwp_relative_pointer_manager_v1_interface relative_pointer_manager = {
2678 relative_pointer_manager_destroy,
2679 relative_pointer_manager_get_relative_pointer,
2680};
2681
2682static void
2683bind_relative_pointer_manager(struct wl_client *client, void *data,
2684 uint32_t version, uint32_t id)
2685{
2686 struct weston_compositor *compositor = data;
2687 struct wl_resource *resource;
2688
2689 resource = wl_resource_create(client,
2690 &zwp_relative_pointer_manager_v1_interface,
2691 1, id);
2692
2693 wl_resource_set_implementation(resource, &relative_pointer_manager,
2694 compositor,
2695 NULL);
2696}
2697
Giulio Camuffo0358af42016-06-02 21:48:08 +03002698WL_EXPORT int
2699weston_compositor_set_xkb_rule_names(struct weston_compositor *ec,
2700 struct xkb_rule_names *names)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002701{
2702 if (ec->xkb_context == NULL) {
2703 ec->xkb_context = xkb_context_new(0);
2704 if (ec->xkb_context == NULL) {
2705 weston_log("failed to create XKB context\n");
2706 return -1;
2707 }
2708 }
2709
2710 if (names)
2711 ec->xkb_names = *names;
2712 if (!ec->xkb_names.rules)
2713 ec->xkb_names.rules = strdup("evdev");
2714 if (!ec->xkb_names.model)
2715 ec->xkb_names.model = strdup("pc105");
2716 if (!ec->xkb_names.layout)
2717 ec->xkb_names.layout = strdup("us");
2718
2719 return 0;
2720}
2721
Stefan Schmidtfda26522013-09-17 10:54:09 +01002722static void
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002723weston_xkb_info_destroy(struct weston_xkb_info *xkb_info)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002724{
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002725 if (--xkb_info->ref_count > 0)
2726 return;
2727
Ran Benitac9c74152014-08-19 23:59:52 +03002728 xkb_keymap_unref(xkb_info->keymap);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002729
2730 if (xkb_info->keymap_area)
2731 munmap(xkb_info->keymap_area, xkb_info->keymap_size);
2732 if (xkb_info->keymap_fd >= 0)
2733 close(xkb_info->keymap_fd);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002734 free(xkb_info);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002735}
2736
2737void
2738weston_compositor_xkb_destroy(struct weston_compositor *ec)
2739{
2740 free((char *) ec->xkb_names.rules);
2741 free((char *) ec->xkb_names.model);
2742 free((char *) ec->xkb_names.layout);
2743 free((char *) ec->xkb_names.variant);
2744 free((char *) ec->xkb_names.options);
Stefan Schmidtfda26522013-09-17 10:54:09 +01002745
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002746 if (ec->xkb_info)
2747 weston_xkb_info_destroy(ec->xkb_info);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002748 xkb_context_unref(ec->xkb_context);
2749}
2750
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002751static struct weston_xkb_info *
2752weston_xkb_info_create(struct xkb_keymap *keymap)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002753{
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002754 struct weston_xkb_info *xkb_info = zalloc(sizeof *xkb_info);
2755 if (xkb_info == NULL)
2756 return NULL;
2757
Ran Benita2e1968f2014-08-19 23:59:51 +03002758 xkb_info->keymap = xkb_keymap_ref(keymap);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002759 xkb_info->ref_count = 1;
2760
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002761 char *keymap_str;
2762
Ran Benita2e1968f2014-08-19 23:59:51 +03002763 xkb_info->shift_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2764 XKB_MOD_NAME_SHIFT);
2765 xkb_info->caps_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2766 XKB_MOD_NAME_CAPS);
2767 xkb_info->ctrl_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2768 XKB_MOD_NAME_CTRL);
2769 xkb_info->alt_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2770 XKB_MOD_NAME_ALT);
2771 xkb_info->mod2_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2772 "Mod2");
2773 xkb_info->mod3_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2774 "Mod3");
2775 xkb_info->super_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2776 XKB_MOD_NAME_LOGO);
2777 xkb_info->mod5_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2778 "Mod5");
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002779
Ran Benita2e1968f2014-08-19 23:59:51 +03002780 xkb_info->num_led = xkb_keymap_led_get_index(xkb_info->keymap,
2781 XKB_LED_NAME_NUM);
2782 xkb_info->caps_led = xkb_keymap_led_get_index(xkb_info->keymap,
2783 XKB_LED_NAME_CAPS);
2784 xkb_info->scroll_led = xkb_keymap_led_get_index(xkb_info->keymap,
2785 XKB_LED_NAME_SCROLL);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002786
Ran Benita2e1968f2014-08-19 23:59:51 +03002787 keymap_str = xkb_keymap_get_as_string(xkb_info->keymap,
2788 XKB_KEYMAP_FORMAT_TEXT_V1);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002789 if (keymap_str == NULL) {
2790 weston_log("failed to get string version of keymap\n");
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002791 goto err_keymap;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002792 }
2793 xkb_info->keymap_size = strlen(keymap_str) + 1;
2794
2795 xkb_info->keymap_fd = os_create_anonymous_file(xkb_info->keymap_size);
2796 if (xkb_info->keymap_fd < 0) {
2797 weston_log("creating a keymap file for %lu bytes failed: %m\n",
2798 (unsigned long) xkb_info->keymap_size);
2799 goto err_keymap_str;
2800 }
2801
2802 xkb_info->keymap_area = mmap(NULL, xkb_info->keymap_size,
2803 PROT_READ | PROT_WRITE,
2804 MAP_SHARED, xkb_info->keymap_fd, 0);
2805 if (xkb_info->keymap_area == MAP_FAILED) {
2806 weston_log("failed to mmap() %lu bytes\n",
2807 (unsigned long) xkb_info->keymap_size);
2808 goto err_dev_zero;
2809 }
2810 strcpy(xkb_info->keymap_area, keymap_str);
2811 free(keymap_str);
2812
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002813 return xkb_info;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002814
2815err_dev_zero:
2816 close(xkb_info->keymap_fd);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002817err_keymap_str:
2818 free(keymap_str);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002819err_keymap:
Ran Benita2e1968f2014-08-19 23:59:51 +03002820 xkb_keymap_unref(xkb_info->keymap);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002821 free(xkb_info);
2822 return NULL;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002823}
2824
2825static int
2826weston_compositor_build_global_keymap(struct weston_compositor *ec)
2827{
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002828 struct xkb_keymap *keymap;
2829
2830 if (ec->xkb_info != NULL)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002831 return 0;
2832
Ran Benita2e1968f2014-08-19 23:59:51 +03002833 keymap = xkb_keymap_new_from_names(ec->xkb_context,
2834 &ec->xkb_names,
2835 0);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002836 if (keymap == NULL) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002837 weston_log("failed to compile global XKB keymap\n");
2838 weston_log(" tried rules %s, model %s, layout %s, variant %s, "
2839 "options %s\n",
2840 ec->xkb_names.rules, ec->xkb_names.model,
2841 ec->xkb_names.layout, ec->xkb_names.variant,
2842 ec->xkb_names.options);
2843 return -1;
2844 }
2845
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002846 ec->xkb_info = weston_xkb_info_create(keymap);
Rui Matos73d93952013-10-24 19:28:41 +02002847 xkb_keymap_unref(keymap);
Stefan Schmidtfda26522013-09-17 10:54:09 +01002848 if (ec->xkb_info == NULL)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002849 return -1;
2850
2851 return 0;
2852}
2853
Rui Matos65196bc2013-10-10 19:44:19 +02002854WL_EXPORT void
2855weston_seat_update_keymap(struct weston_seat *seat, struct xkb_keymap *keymap)
2856{
Derek Foreman1281a362015-07-31 16:55:32 -05002857 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
2858
2859 if (!keyboard || !keymap)
Rui Matos65196bc2013-10-10 19:44:19 +02002860 return;
2861
Derek Foreman1281a362015-07-31 16:55:32 -05002862 xkb_keymap_unref(keyboard->pending_keymap);
2863 keyboard->pending_keymap = xkb_keymap_ref(keymap);
Rui Matos65196bc2013-10-10 19:44:19 +02002864
Derek Foreman1281a362015-07-31 16:55:32 -05002865 if (keyboard->keys.size == 0)
Rui Matos65196bc2013-10-10 19:44:19 +02002866 update_keymap(seat);
Rui Matos65196bc2013-10-10 19:44:19 +02002867}
2868
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002869WL_EXPORT int
2870weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap)
2871{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002872 struct weston_keyboard *keyboard;
2873
Derek Foreman1281a362015-07-31 16:55:32 -05002874 if (seat->keyboard_state) {
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002875 seat->keyboard_device_count += 1;
2876 if (seat->keyboard_device_count == 1)
2877 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002878 return 0;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002879 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002880
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002881 keyboard = weston_keyboard_create();
2882 if (keyboard == NULL) {
2883 weston_log("failed to allocate weston keyboard struct\n");
2884 return -1;
2885 }
2886
Derek Foreman185d1582017-06-28 11:17:23 -05002887 if (keymap != NULL) {
2888 keyboard->xkb_info = weston_xkb_info_create(keymap);
2889 if (keyboard->xkb_info == NULL)
Ander Conselvan de Oliveira4d363cf2014-01-31 17:35:45 +02002890 goto err;
Derek Foreman185d1582017-06-28 11:17:23 -05002891 } else {
2892 if (weston_compositor_build_global_keymap(seat->compositor) < 0)
2893 goto err;
2894 keyboard->xkb_info = seat->compositor->xkb_info;
2895 keyboard->xkb_info->ref_count++;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002896 }
Derek Foreman185d1582017-06-28 11:17:23 -05002897
2898 keyboard->xkb_state.state = xkb_state_new(keyboard->xkb_info->keymap);
2899 if (keyboard->xkb_state.state == NULL) {
2900 weston_log("failed to initialise XKB state\n");
2901 goto err;
2902 }
2903
2904 keyboard->xkb_state.leds = 0;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002905
Derek Foreman1281a362015-07-31 16:55:32 -05002906 seat->keyboard_state = keyboard;
Ander Conselvan de Oliveira4d363cf2014-01-31 17:35:45 +02002907 seat->keyboard_device_count = 1;
2908 keyboard->seat = seat;
2909
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002910 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002911
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002912 return 0;
Ander Conselvan de Oliveira4d363cf2014-01-31 17:35:45 +02002913
2914err:
2915 if (keyboard->xkb_info)
2916 weston_xkb_info_destroy(keyboard->xkb_info);
2917 free(keyboard);
2918
2919 return -1;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002920}
2921
Jonas Ådahl91fed542013-12-03 09:14:27 +01002922static void
2923weston_keyboard_reset_state(struct weston_keyboard *keyboard)
2924{
2925 struct weston_seat *seat = keyboard->seat;
2926 struct xkb_state *state;
2927
Derek Foreman185d1582017-06-28 11:17:23 -05002928 state = xkb_state_new(keyboard->xkb_info->keymap);
2929 if (!state) {
2930 weston_log("failed to reset XKB state\n");
2931 return;
Jonas Ådahl91fed542013-12-03 09:14:27 +01002932 }
Derek Foreman185d1582017-06-28 11:17:23 -05002933 xkb_state_unref(keyboard->xkb_state.state);
2934 keyboard->xkb_state.state = state;
2935
2936 keyboard->xkb_state.leds = 0;
Jonas Ådahl91fed542013-12-03 09:14:27 +01002937
2938 seat->modifier_state = 0;
2939}
2940
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002941WL_EXPORT void
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002942weston_seat_release_keyboard(struct weston_seat *seat)
2943{
2944 seat->keyboard_device_count--;
Derek Foremand621df22014-11-19 11:04:12 -06002945 assert(seat->keyboard_device_count >= 0);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002946 if (seat->keyboard_device_count == 0) {
Derek Foreman1281a362015-07-31 16:55:32 -05002947 weston_keyboard_set_focus(seat->keyboard_state, NULL);
2948 weston_keyboard_cancel_grab(seat->keyboard_state);
2949 weston_keyboard_reset_state(seat->keyboard_state);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002950 seat_send_updated_caps(seat);
2951 }
2952}
2953
2954WL_EXPORT void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002955weston_seat_init_pointer(struct weston_seat *seat)
2956{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002957 struct weston_pointer *pointer;
2958
Derek Foreman1281a362015-07-31 16:55:32 -05002959 if (seat->pointer_state) {
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002960 seat->pointer_device_count += 1;
2961 if (seat->pointer_device_count == 1)
2962 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002963 return;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002964 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002965
Giulio Camuffocdb4d292013-11-14 23:42:53 +01002966 pointer = weston_pointer_create(seat);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002967 if (pointer == NULL)
2968 return;
2969
Derek Foreman1281a362015-07-31 16:55:32 -05002970 seat->pointer_state = pointer;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002971 seat->pointer_device_count = 1;
2972 pointer->seat = seat;
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002973
2974 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002975}
2976
2977WL_EXPORT void
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002978weston_seat_release_pointer(struct weston_seat *seat)
2979{
Derek Foreman1281a362015-07-31 16:55:32 -05002980 struct weston_pointer *pointer = seat->pointer_state;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002981
2982 seat->pointer_device_count--;
2983 if (seat->pointer_device_count == 0) {
Derek Foremanf9318d12015-05-11 15:40:11 -05002984 weston_pointer_clear_focus(pointer);
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02002985 weston_pointer_cancel_grab(pointer);
Jonas Ådahl630bae82013-10-17 23:04:06 +02002986
Jonas Ådahla4932742013-10-17 23:04:07 +02002987 if (pointer->sprite)
2988 pointer_unmap_sprite(pointer);
2989
Jonas Ådahl3e12e632013-12-02 22:05:05 +01002990 weston_pointer_reset_state(pointer);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002991 seat_send_updated_caps(seat);
Derek Foremanfd5ca512015-01-07 15:00:25 -06002992
2993 /* seat->pointer is intentionally not destroyed so that
2994 * a newly attached pointer on this seat will retain
2995 * the previous cursor co-ordinates.
2996 */
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002997 }
2998}
2999
3000WL_EXPORT void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003001weston_seat_init_touch(struct weston_seat *seat)
3002{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04003003 struct weston_touch *touch;
3004
Derek Foreman1281a362015-07-31 16:55:32 -05003005 if (seat->touch_state) {
Jonas Ådahld6e1c342013-10-17 23:04:05 +02003006 seat->touch_device_count += 1;
3007 if (seat->touch_device_count == 1)
3008 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003009 return;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02003010 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003011
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04003012 touch = weston_touch_create();
3013 if (touch == NULL)
3014 return;
3015
Derek Foreman1281a362015-07-31 16:55:32 -05003016 seat->touch_state = touch;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02003017 seat->touch_device_count = 1;
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04003018 touch->seat = seat;
3019
3020 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003021}
3022
3023WL_EXPORT void
Jonas Ådahld6e1c342013-10-17 23:04:05 +02003024weston_seat_release_touch(struct weston_seat *seat)
3025{
3026 seat->touch_device_count--;
3027 if (seat->touch_device_count == 0) {
Derek Foreman1281a362015-07-31 16:55:32 -05003028 weston_touch_set_focus(seat->touch_state, NULL);
3029 weston_touch_cancel_grab(seat->touch_state);
3030 weston_touch_reset_state(seat->touch_state);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02003031 seat_send_updated_caps(seat);
3032 }
3033}
3034
3035WL_EXPORT void
Rob Bradford9af5f9e2013-05-31 18:09:50 +01003036weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec,
3037 const char *seat_name)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003038{
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04003039 memset(seat, 0, sizeof *seat);
3040
Kristian Høgsberge3148752013-05-06 23:19:49 -04003041 seat->selection_data_source = NULL;
3042 wl_list_init(&seat->base_resource_list);
3043 wl_signal_init(&seat->selection_signal);
3044 wl_list_init(&seat->drag_resource_list);
Kristian Høgsberge3148752013-05-06 23:19:49 -04003045 wl_signal_init(&seat->destroy_signal);
Jason Ekstranda4ab5422014-04-02 19:53:45 -05003046 wl_signal_init(&seat->updated_caps_signal);
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04003047
Peter Hutterer87743e92016-01-18 16:38:22 +10003048 seat->global = wl_global_create(ec->wl_display, &wl_seat_interface, 5,
Kristian Høgsberg919cddb2013-07-08 19:03:57 -04003049 seat, bind_seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003050
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003051 seat->compositor = ec;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003052 seat->modifier_state = 0;
Rob Bradford9af5f9e2013-05-31 18:09:50 +01003053 seat->seat_name = strdup(seat_name);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003054
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003055 wl_list_insert(ec->seat_list.prev, &seat->link);
3056
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003057 clipboard_create(seat);
3058
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003059 wl_signal_emit(&ec->seat_created_signal, seat);
3060}
3061
3062WL_EXPORT void
3063weston_seat_release(struct weston_seat *seat)
3064{
3065 wl_list_remove(&seat->link);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003066
Jonas Ådahl1afb2382014-01-03 19:46:51 +01003067 if (seat->saved_kbd_focus)
3068 wl_list_remove(&seat->saved_kbd_focus_listener.link);
3069
Derek Foreman1281a362015-07-31 16:55:32 -05003070 if (seat->pointer_state)
3071 weston_pointer_destroy(seat->pointer_state);
3072 if (seat->keyboard_state)
3073 weston_keyboard_destroy(seat->keyboard_state);
3074 if (seat->touch_state)
3075 weston_touch_destroy(seat->touch_state);
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04003076
Rob Bradford9af5f9e2013-05-31 18:09:50 +01003077 free (seat->seat_name);
3078
Kristian Høgsberg919cddb2013-07-08 19:03:57 -04003079 wl_global_destroy(seat->global);
Kristian Høgsbergaaadc772013-07-08 16:20:31 -04003080
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003081 wl_signal_emit(&seat->destroy_signal, seat);
3082}
Derek Foreman1281a362015-07-31 16:55:32 -05003083
3084/** Get a seat's keyboard pointer
3085 *
3086 * \param seat The seat to query
3087 * \return The seat's keyboard pointer, or NULL if no keyboard is present
3088 *
3089 * The keyboard pointer for a seat isn't freed when all keyboards are removed,
3090 * so it should only be used when the seat's keyboard_device_count is greater
3091 * than zero. This function does that test and only returns a pointer
3092 * when a keyboard is present.
3093 */
3094WL_EXPORT struct weston_keyboard *
3095weston_seat_get_keyboard(struct weston_seat *seat)
3096{
3097 if (!seat)
3098 return NULL;
3099
3100 if (seat->keyboard_device_count)
3101 return seat->keyboard_state;
3102
3103 return NULL;
3104}
3105
3106/** Get a seat's pointer pointer
3107 *
3108 * \param seat The seat to query
3109 * \return The seat's pointer pointer, or NULL if no pointer device is present
3110 *
3111 * The pointer pointer for a seat isn't freed when all mice are removed,
3112 * so it should only be used when the seat's pointer_device_count is greater
3113 * than zero. This function does that test and only returns a pointer
3114 * when a pointing device is present.
3115 */
3116WL_EXPORT struct weston_pointer *
3117weston_seat_get_pointer(struct weston_seat *seat)
3118{
3119 if (!seat)
3120 return NULL;
3121
3122 if (seat->pointer_device_count)
3123 return seat->pointer_state;
3124
3125 return NULL;
3126}
3127
Jonas Ådahld3414f22016-07-22 17:56:31 +08003128static const struct zwp_locked_pointer_v1_interface locked_pointer_interface;
3129static const struct zwp_confined_pointer_v1_interface confined_pointer_interface;
3130
3131static enum pointer_constraint_type
3132pointer_constraint_get_type(struct weston_pointer_constraint *constraint)
3133{
3134 if (wl_resource_instance_of(constraint->resource,
3135 &zwp_locked_pointer_v1_interface,
3136 &locked_pointer_interface)) {
3137 return POINTER_CONSTRAINT_TYPE_LOCK;
3138 } else if (wl_resource_instance_of(constraint->resource,
3139 &zwp_confined_pointer_v1_interface,
3140 &confined_pointer_interface)) {
3141 return POINTER_CONSTRAINT_TYPE_CONFINE;
3142 }
3143
3144 abort();
3145 return 0;
3146}
3147
3148static void
3149pointer_constraint_notify_activated(struct weston_pointer_constraint *constraint)
3150{
3151 struct wl_resource *resource = constraint->resource;
3152
3153 switch (pointer_constraint_get_type(constraint)) {
3154 case POINTER_CONSTRAINT_TYPE_LOCK:
3155 zwp_locked_pointer_v1_send_locked(resource);
3156 break;
3157 case POINTER_CONSTRAINT_TYPE_CONFINE:
3158 zwp_confined_pointer_v1_send_confined(resource);
3159 break;
3160 }
3161}
3162
3163static void
3164pointer_constraint_notify_deactivated(struct weston_pointer_constraint *constraint)
3165{
3166 struct wl_resource *resource = constraint->resource;
3167
3168 switch (pointer_constraint_get_type(constraint)) {
3169 case POINTER_CONSTRAINT_TYPE_LOCK:
3170 zwp_locked_pointer_v1_send_unlocked(resource);
3171 break;
3172 case POINTER_CONSTRAINT_TYPE_CONFINE:
3173 zwp_confined_pointer_v1_send_unconfined(resource);
3174 break;
3175 }
3176}
3177
3178static struct weston_pointer_constraint *
3179get_pointer_constraint_for_pointer(struct weston_surface *surface,
3180 struct weston_pointer *pointer)
3181{
3182 struct weston_pointer_constraint *constraint;
3183
3184 wl_list_for_each(constraint, &surface->pointer_constraints, link) {
3185 if (constraint->pointer == pointer)
3186 return constraint;
3187 }
3188
3189 return NULL;
3190}
3191
Derek Foreman1281a362015-07-31 16:55:32 -05003192/** Get a seat's touch pointer
3193 *
3194 * \param seat The seat to query
3195 * \return The seat's touch pointer, or NULL if no touch device is present
3196 *
3197 * The touch pointer for a seat isn't freed when all touch devices are removed,
3198 * so it should only be used when the seat's touch_device_count is greater
3199 * than zero. This function does that test and only returns a pointer
3200 * when a touch device is present.
3201 */
3202WL_EXPORT struct weston_touch *
3203weston_seat_get_touch(struct weston_seat *seat)
3204{
3205 if (!seat)
3206 return NULL;
3207
3208 if (seat->touch_device_count)
3209 return seat->touch_state;
3210
3211 return NULL;
3212}
Bryce Harrington24f917e2016-06-29 19:04:07 -07003213
3214/** Sets the keyboard focus to the given surface
3215 *
3216 * \param seat The seat to query
3217 */
3218WL_EXPORT void
3219weston_seat_set_keyboard_focus(struct weston_seat *seat,
3220 struct weston_surface *surface)
3221{
3222 struct weston_compositor *compositor = seat->compositor;
3223 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Jonas Ådahlf7deb6a2016-07-22 17:50:26 +08003224 struct weston_surface_activation_data activation_data;
Bryce Harrington24f917e2016-06-29 19:04:07 -07003225
Jonas Ådahlef8e1c32016-03-15 20:28:51 +08003226 if (keyboard && keyboard->focus != surface) {
Bryce Harrington24f917e2016-06-29 19:04:07 -07003227 weston_keyboard_set_focus(keyboard, surface);
3228 wl_data_device_set_keyboard_focus(seat);
3229 }
3230
Jonas Ådahl94e2e2d2014-10-18 18:42:19 +02003231 inc_activate_serial(compositor);
Jonas Ådahlf7deb6a2016-07-22 17:50:26 +08003232
3233 activation_data = (struct weston_surface_activation_data) {
3234 .surface = surface,
3235 .seat = seat,
3236 };
3237 wl_signal_emit(&compositor->activate_signal, &activation_data);
Bryce Harrington24f917e2016-06-29 19:04:07 -07003238}
Jonas Ådahl30d61d82014-10-22 21:21:17 +02003239
Jonas Ådahld3414f22016-07-22 17:56:31 +08003240static void
3241enable_pointer_constraint(struct weston_pointer_constraint *constraint,
3242 struct weston_view *view)
3243{
3244 assert(constraint->view == NULL);
3245 constraint->view = view;
3246 pointer_constraint_notify_activated(constraint);
3247 weston_pointer_start_grab(constraint->pointer, &constraint->grab);
3248 wl_list_remove(&constraint->surface_destroy_listener.link);
3249 wl_list_init(&constraint->surface_destroy_listener.link);
3250}
3251
3252static bool
3253is_pointer_constraint_enabled(struct weston_pointer_constraint *constraint)
3254{
3255 return constraint->view != NULL;
3256}
3257
3258static void
3259weston_pointer_constraint_disable(struct weston_pointer_constraint *constraint)
3260{
3261 constraint->view = NULL;
3262 pointer_constraint_notify_deactivated(constraint);
3263 weston_pointer_end_grab(constraint->grab.pointer);
3264}
3265
3266void
3267weston_pointer_constraint_destroy(struct weston_pointer_constraint *constraint)
3268{
3269 if (is_pointer_constraint_enabled(constraint))
3270 weston_pointer_constraint_disable(constraint);
3271
3272 wl_list_remove(&constraint->pointer_destroy_listener.link);
3273 wl_list_remove(&constraint->surface_destroy_listener.link);
3274 wl_list_remove(&constraint->surface_commit_listener.link);
3275 wl_list_remove(&constraint->surface_activate_listener.link);
3276
3277 wl_resource_set_user_data(constraint->resource, NULL);
3278 pixman_region32_fini(&constraint->region);
3279 wl_list_remove(&constraint->link);
3280 free(constraint);
3281}
3282
3283static void
3284disable_pointer_constraint(struct weston_pointer_constraint *constraint)
3285{
3286 switch (constraint->lifetime) {
3287 case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT:
3288 weston_pointer_constraint_destroy(constraint);
3289 break;
3290 case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT:
3291 weston_pointer_constraint_disable(constraint);
3292 break;
3293 }
3294}
3295
3296static bool
3297is_within_constraint_region(struct weston_pointer_constraint *constraint,
3298 wl_fixed_t sx, wl_fixed_t sy)
3299{
3300 struct weston_surface *surface = constraint->surface;
3301 pixman_region32_t constraint_region;
3302 bool result;
3303
3304 pixman_region32_init(&constraint_region);
3305 pixman_region32_intersect(&constraint_region,
3306 &surface->input,
3307 &constraint->region);
3308 result = pixman_region32_contains_point(&constraint_region,
3309 wl_fixed_to_int(sx),
3310 wl_fixed_to_int(sy),
3311 NULL);
3312 pixman_region32_fini(&constraint_region);
3313
3314 return result;
3315}
3316
3317static void
3318maybe_enable_pointer_constraint(struct weston_pointer_constraint *constraint)
3319{
3320 struct weston_surface *surface = constraint->surface;
3321 struct weston_view *vit;
3322 struct weston_view *view = NULL;
3323 struct weston_pointer *pointer = constraint->pointer;
3324 struct weston_keyboard *keyboard;
3325 struct weston_seat *seat = pointer->seat;
3326 int32_t x, y;
3327
3328 /* Postpone if no view of the surface was most recently clicked. */
3329 wl_list_for_each(vit, &surface->views, surface_link) {
3330 if (vit->click_to_activate_serial ==
3331 surface->compositor->activate_serial) {
3332 view = vit;
3333 }
3334 }
3335 if (view == NULL)
3336 return;
3337
3338 /* Postpone if surface doesn't have keyboard focus. */
3339 keyboard = weston_seat_get_keyboard(seat);
3340 if (!keyboard || keyboard->focus != surface)
3341 return;
3342
3343 /* Postpone constraint if the pointer is not within the
3344 * constraint region.
3345 */
3346 weston_view_from_global(view,
3347 wl_fixed_to_int(pointer->x),
3348 wl_fixed_to_int(pointer->y),
3349 &x, &y);
3350 if (!is_within_constraint_region(constraint,
3351 wl_fixed_from_int(x),
3352 wl_fixed_from_int(y)))
3353 return;
3354
3355 enable_pointer_constraint(constraint, view);
3356}
3357
3358static void
3359locked_pointer_grab_pointer_focus(struct weston_pointer_grab *grab)
3360{
3361}
3362
3363static void
3364locked_pointer_grab_pointer_motion(struct weston_pointer_grab *grab,
Alexandros Frantzis84b31f82017-11-24 18:01:46 +02003365 const struct timespec *time,
Jonas Ådahld3414f22016-07-22 17:56:31 +08003366 struct weston_pointer_motion_event *event)
3367{
Quentin Glidiccde13452016-08-12 10:41:32 +02003368 pointer_send_relative_motion(grab->pointer, time, event);
Jonas Ådahld3414f22016-07-22 17:56:31 +08003369}
3370
3371static void
3372locked_pointer_grab_pointer_button(struct weston_pointer_grab *grab,
Alexandros Frantzis215bedc2017-11-16 18:20:55 +02003373 const struct timespec *time,
Jonas Ådahld3414f22016-07-22 17:56:31 +08003374 uint32_t button,
3375 uint32_t state_w)
3376{
3377 weston_pointer_send_button(grab->pointer, time, button, state_w);
3378}
3379
3380static void
3381locked_pointer_grab_pointer_axis(struct weston_pointer_grab *grab,
Alexandros Frantzis80321942017-11-16 18:20:56 +02003382 const struct timespec *time,
Jonas Ådahld3414f22016-07-22 17:56:31 +08003383 struct weston_pointer_axis_event *event)
3384{
3385 weston_pointer_send_axis(grab->pointer, time, event);
3386}
3387
3388static void
3389locked_pointer_grab_pointer_axis_source(struct weston_pointer_grab *grab,
3390 uint32_t source)
3391{
3392 weston_pointer_send_axis_source(grab->pointer, source);
3393}
3394
3395static void
3396locked_pointer_grab_pointer_frame(struct weston_pointer_grab *grab)
3397{
3398 weston_pointer_send_frame(grab->pointer);
3399}
3400
3401static void
3402locked_pointer_grab_pointer_cancel(struct weston_pointer_grab *grab)
3403{
3404 struct weston_pointer_constraint *constraint =
3405 container_of(grab, struct weston_pointer_constraint, grab);
3406
3407 disable_pointer_constraint(constraint);
3408}
3409
3410static const struct weston_pointer_grab_interface
3411 locked_pointer_grab_interface = {
3412 locked_pointer_grab_pointer_focus,
3413 locked_pointer_grab_pointer_motion,
3414 locked_pointer_grab_pointer_button,
3415 locked_pointer_grab_pointer_axis,
3416 locked_pointer_grab_pointer_axis_source,
3417 locked_pointer_grab_pointer_frame,
3418 locked_pointer_grab_pointer_cancel,
3419};
3420
3421static void
3422pointer_constraint_constrain_resource_destroyed(struct wl_resource *resource)
3423{
3424 struct weston_pointer_constraint *constraint =
3425 wl_resource_get_user_data(resource);
3426
3427 if (!constraint)
3428 return;
3429
3430 weston_pointer_constraint_destroy(constraint);
3431}
3432
3433static void
3434pointer_constraint_surface_activate(struct wl_listener *listener, void *data)
3435{
3436 struct weston_surface_activation_data *activation = data;
3437 struct weston_pointer *pointer;
3438 struct weston_surface *focus = activation->surface;
3439 struct weston_pointer_constraint *constraint =
3440 container_of(listener, struct weston_pointer_constraint,
3441 surface_activate_listener);
3442 bool is_constraint_surface;
3443
3444 pointer = weston_seat_get_pointer(activation->seat);
3445 if (!pointer)
3446 return;
3447
3448 is_constraint_surface =
3449 get_pointer_constraint_for_pointer(focus, pointer) == constraint;
3450
3451 if (is_constraint_surface &&
3452 !is_pointer_constraint_enabled(constraint))
3453 maybe_enable_pointer_constraint(constraint);
3454 else if (!is_constraint_surface &&
3455 is_pointer_constraint_enabled(constraint))
3456 disable_pointer_constraint(constraint);
3457}
3458
3459static void
3460pointer_constraint_pointer_destroyed(struct wl_listener *listener, void *data)
3461{
3462 struct weston_pointer_constraint *constraint =
3463 container_of(listener, struct weston_pointer_constraint,
3464 pointer_destroy_listener);
3465
3466 weston_pointer_constraint_destroy(constraint);
3467}
3468
3469static void
3470pointer_constraint_surface_destroyed(struct wl_listener *listener, void *data)
3471{
3472 struct weston_pointer_constraint *constraint =
3473 container_of(listener, struct weston_pointer_constraint,
3474 surface_destroy_listener);
3475
3476 weston_pointer_constraint_destroy(constraint);
3477}
3478
3479static void
3480pointer_constraint_surface_committed(struct wl_listener *listener, void *data)
3481{
3482 struct weston_pointer_constraint *constraint =
3483 container_of(listener, struct weston_pointer_constraint,
3484 surface_commit_listener);
3485
3486 if (constraint->region_is_pending) {
3487 constraint->region_is_pending = false;
3488 pixman_region32_copy(&constraint->region,
3489 &constraint->region_pending);
3490 pixman_region32_fini(&constraint->region_pending);
3491 pixman_region32_init(&constraint->region_pending);
3492 }
3493
3494 if (constraint->hint_is_pending) {
3495 constraint->hint_is_pending = false;
3496
3497 constraint->hint_is_pending = true;
3498 constraint->hint_x = constraint->hint_x_pending;
3499 constraint->hint_y = constraint->hint_y_pending;
3500 }
3501
3502 if (pointer_constraint_get_type(constraint) ==
3503 POINTER_CONSTRAINT_TYPE_CONFINE &&
3504 is_pointer_constraint_enabled(constraint))
3505 maybe_warp_confined_pointer(constraint);
3506}
3507
3508static struct weston_pointer_constraint *
3509weston_pointer_constraint_create(struct weston_surface *surface,
3510 struct weston_pointer *pointer,
3511 struct weston_region *region,
3512 enum zwp_pointer_constraints_v1_lifetime lifetime,
3513 struct wl_resource *cr,
3514 const struct weston_pointer_grab_interface *grab_interface)
3515{
3516 struct weston_pointer_constraint *constraint;
3517
3518 constraint = zalloc(sizeof *constraint);
3519 if (!constraint)
3520 return NULL;
3521
3522 constraint->lifetime = lifetime;
3523 pixman_region32_init(&constraint->region);
3524 pixman_region32_init(&constraint->region_pending);
3525 wl_list_insert(&surface->pointer_constraints, &constraint->link);
3526 constraint->surface = surface;
3527 constraint->pointer = pointer;
3528 constraint->resource = cr;
3529 constraint->grab.interface = grab_interface;
3530 if (region) {
3531 pixman_region32_copy(&constraint->region,
3532 &region->region);
3533 } else {
3534 pixman_region32_fini(&constraint->region);
3535 region_init_infinite(&constraint->region);
3536 }
3537
3538 constraint->surface_activate_listener.notify =
3539 pointer_constraint_surface_activate;
3540 constraint->surface_destroy_listener.notify =
3541 pointer_constraint_surface_destroyed;
3542 constraint->surface_commit_listener.notify =
3543 pointer_constraint_surface_committed;
3544 constraint->pointer_destroy_listener.notify =
3545 pointer_constraint_pointer_destroyed;
3546
3547 wl_signal_add(&surface->compositor->activate_signal,
3548 &constraint->surface_activate_listener);
3549 wl_signal_add(&pointer->destroy_signal,
3550 &constraint->pointer_destroy_listener);
3551 wl_signal_add(&surface->destroy_signal,
3552 &constraint->surface_destroy_listener);
3553 wl_signal_add(&surface->commit_signal,
3554 &constraint->surface_commit_listener);
3555
3556 return constraint;
3557}
3558
3559static void
3560init_pointer_constraint(struct wl_resource *pointer_constraints_resource,
3561 uint32_t id,
3562 struct weston_surface *surface,
3563 struct weston_pointer *pointer,
3564 struct weston_region *region,
3565 enum zwp_pointer_constraints_v1_lifetime lifetime,
3566 const struct wl_interface *interface,
3567 const void *implementation,
3568 const struct weston_pointer_grab_interface *grab_interface)
3569{
3570 struct wl_client *client =
3571 wl_resource_get_client(pointer_constraints_resource);
3572 struct wl_resource *cr;
3573 struct weston_pointer_constraint *constraint;
3574
3575 if (get_pointer_constraint_for_pointer(surface, pointer)) {
3576 wl_resource_post_error(pointer_constraints_resource,
3577 ZWP_POINTER_CONSTRAINTS_V1_ERROR_ALREADY_CONSTRAINED,
3578 "the pointer has a lock/confine request on this surface");
3579 return;
3580 }
3581
3582 cr = wl_resource_create(client, interface,
3583 wl_resource_get_version(pointer_constraints_resource),
3584 id);
3585 if (cr == NULL) {
3586 wl_client_post_no_memory(client);
3587 return;
3588 }
3589
3590 constraint = weston_pointer_constraint_create(surface, pointer,
3591 region, lifetime,
3592 cr, grab_interface);
3593 if (constraint == NULL) {
3594 wl_client_post_no_memory(client);
3595 return;
3596 }
3597
3598 wl_resource_set_implementation(cr, implementation, constraint,
3599 pointer_constraint_constrain_resource_destroyed);
3600
3601 maybe_enable_pointer_constraint(constraint);
3602}
3603
3604static void
3605pointer_constraints_destroy(struct wl_client *client,
3606 struct wl_resource *resource)
3607{
3608 wl_resource_destroy(resource);
3609}
3610
3611static void
3612locked_pointer_destroy(struct wl_client *client,
3613 struct wl_resource *resource)
3614{
3615 struct weston_pointer_constraint *constraint =
3616 wl_resource_get_user_data(resource);
3617 wl_fixed_t x, y;
3618
3619 if (constraint && constraint->view && constraint->hint_is_pending &&
3620 is_within_constraint_region(constraint,
3621 constraint->hint_x,
3622 constraint->hint_y)) {
3623 weston_view_to_global_fixed(constraint->view,
3624 constraint->hint_x,
3625 constraint->hint_y,
3626 &x, &y);
3627 weston_pointer_move_to(constraint->pointer, x, y);
3628 }
3629 wl_resource_destroy(resource);
3630}
3631
3632static void
3633locked_pointer_set_cursor_position_hint(struct wl_client *client,
3634 struct wl_resource *resource,
3635 wl_fixed_t surface_x,
3636 wl_fixed_t surface_y)
3637{
3638 struct weston_pointer_constraint *constraint =
3639 wl_resource_get_user_data(resource);
3640
3641 /* Ignore a set cursor hint that was sent after the lock was cancelled.
3642 */
3643 if (!constraint ||
3644 !constraint->resource ||
3645 constraint->resource != resource)
3646 return;
3647
3648 constraint->hint_is_pending = true;
3649 constraint->hint_x_pending = surface_x;
3650 constraint->hint_y_pending = surface_y;
3651}
3652
3653static void
3654locked_pointer_set_region(struct wl_client *client,
3655 struct wl_resource *resource,
3656 struct wl_resource *region_resource)
3657{
3658 struct weston_pointer_constraint *constraint =
3659 wl_resource_get_user_data(resource);
3660 struct weston_region *region = region_resource ?
3661 wl_resource_get_user_data(region_resource) : NULL;
3662
3663 if (!constraint)
3664 return;
3665
3666 if (region) {
3667 pixman_region32_copy(&constraint->region_pending,
3668 &region->region);
3669 } else {
3670 pixman_region32_fini(&constraint->region_pending);
3671 region_init_infinite(&constraint->region_pending);
3672 }
3673 constraint->region_is_pending = true;
3674}
3675
3676
3677static const struct zwp_locked_pointer_v1_interface locked_pointer_interface = {
3678 locked_pointer_destroy,
3679 locked_pointer_set_cursor_position_hint,
3680 locked_pointer_set_region,
3681};
3682
3683static void
3684pointer_constraints_lock_pointer(struct wl_client *client,
3685 struct wl_resource *resource,
3686 uint32_t id,
3687 struct wl_resource *surface_resource,
3688 struct wl_resource *pointer_resource,
3689 struct wl_resource *region_resource,
3690 uint32_t lifetime)
3691{
3692 struct weston_surface *surface =
3693 wl_resource_get_user_data(surface_resource);
3694 struct weston_pointer *pointer = wl_resource_get_user_data(pointer_resource);
3695 struct weston_region *region = region_resource ?
3696 wl_resource_get_user_data(region_resource) : NULL;
3697
3698 init_pointer_constraint(resource, id, surface, pointer, region, lifetime,
3699 &zwp_locked_pointer_v1_interface,
3700 &locked_pointer_interface,
3701 &locked_pointer_grab_interface);
3702}
3703
3704static void
3705confined_pointer_grab_pointer_focus(struct weston_pointer_grab *grab)
3706{
3707}
3708
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08003709static double
3710vec2d_cross_product(struct vec2d a, struct vec2d b)
3711{
3712 return a.x * b.y - a.y * b.x;
3713}
3714
3715static struct vec2d
3716vec2d_add(struct vec2d a, struct vec2d b)
3717{
3718 return (struct vec2d) {
3719 .x = a.x + b.x,
3720 .y = a.y + b.y,
3721 };
3722}
3723
3724static struct vec2d
3725vec2d_subtract(struct vec2d a, struct vec2d b)
3726{
3727 return (struct vec2d) {
3728 .x = a.x - b.x,
3729 .y = a.y - b.y,
3730 };
3731}
3732
3733static struct vec2d
3734vec2d_multiply_constant(double c, struct vec2d a)
3735{
3736 return (struct vec2d) {
3737 .x = c * a.x,
3738 .y = c * a.y,
3739 };
3740}
3741
3742static bool
3743lines_intersect(struct line *line1, struct line *line2,
3744 struct vec2d *intersection)
3745{
3746 struct vec2d p = line1->a;
3747 struct vec2d r = vec2d_subtract(line1->b, line1->a);
3748 struct vec2d q = line2->a;
3749 struct vec2d s = vec2d_subtract(line2->b, line2->a);
3750 double rxs;
3751 double sxr;
3752 double t;
3753 double u;
3754
3755 /*
3756 * The line (p, r) and (q, s) intersects where
3757 *
3758 * p + t r = q + u s
3759 *
3760 * Calculate t:
3761 *
3762 * (p + t r) × s = (q + u s) × s
3763 * p × s + t (r × s) = q × s + u (s × s)
3764 * p × s + t (r × s) = q × s
3765 * t (r × s) = q × s - p × s
3766 * t (r × s) = (q - p) × s
3767 * t = ((q - p) × s) / (r × s)
3768 *
3769 * Using the same method, for u we get:
3770 *
3771 * u = ((p - q) × r) / (s × r)
3772 */
3773
3774 rxs = vec2d_cross_product(r, s);
3775 sxr = vec2d_cross_product(s, r);
3776
3777 /* If r × s = 0 then the lines are either parallel or collinear. */
3778 if (fabs(rxs) < DBL_MIN)
3779 return false;
3780
3781 t = vec2d_cross_product(vec2d_subtract(q, p), s) / rxs;
3782 u = vec2d_cross_product(vec2d_subtract(p, q), r) / sxr;
3783
3784 /* The lines only intersect if 0 ≤ t ≤ 1 and 0 ≤ u ≤ 1. */
3785 if (t < 0.0 || t > 1.0 || u < 0.0 || u > 1.0)
3786 return false;
3787
3788 *intersection = vec2d_add(p, vec2d_multiply_constant(t, r));
3789 return true;
3790}
3791
3792static struct border *
3793add_border(struct wl_array *array,
3794 double x1, double y1,
3795 double x2, double y2,
3796 enum motion_direction blocking_dir)
3797{
3798 struct border *border = wl_array_add(array, sizeof *border);
3799
3800 *border = (struct border) {
3801 .line = (struct line) {
3802 .a = (struct vec2d) {
3803 .x = x1,
3804 .y = y1,
3805 },
3806 .b = (struct vec2d) {
3807 .x = x2,
3808 .y = y2,
3809 },
3810 },
3811 .blocking_dir = blocking_dir,
3812 };
3813
3814 return border;
3815}
3816
3817static int
3818compare_lines_x(const void *a, const void *b)
3819{
3820 const struct border *border_a = a;
3821 const struct border *border_b = b;
3822
3823
3824 if (border_a->line.a.x == border_b->line.a.x)
3825 return border_a->line.b.x < border_b->line.b.x;
3826 else
3827 return border_a->line.a.x > border_b->line.a.x;
3828}
3829
3830static void
3831add_non_overlapping_edges(pixman_box32_t *boxes,
3832 int band_above_start,
3833 int band_below_start,
3834 int band_below_end,
3835 struct wl_array *borders)
3836{
3837 int i;
3838 struct wl_array band_merge;
3839 struct border *border;
3840 struct border *prev_border;
3841 struct border *new_border;
3842
3843 wl_array_init(&band_merge);
3844
3845 /* Add bottom band of previous row, and top band of current row, and
3846 * sort them so lower left x coordinate comes first. If there are two
3847 * borders with the same left x coordinate, the wider one comes first.
3848 */
3849 for (i = band_above_start; i < band_below_start; i++) {
3850 pixman_box32_t *box = &boxes[i];
3851 add_border(&band_merge, box->x1, box->y2, box->x2, box->y2,
3852 MOTION_DIRECTION_POSITIVE_Y);
3853 }
3854 for (i = band_below_start; i < band_below_end; i++) {
3855 pixman_box32_t *box= &boxes[i];
3856 add_border(&band_merge, box->x1, box->y1, box->x2, box->y1,
3857 MOTION_DIRECTION_NEGATIVE_Y);
3858 }
3859 qsort(band_merge.data,
3860 band_merge.size / sizeof *border,
3861 sizeof *border,
3862 compare_lines_x);
3863
3864 /* Combine the two combined bands so that any overlapping border is
3865 * eliminated. */
3866 prev_border = NULL;
3867 wl_array_for_each(border, &band_merge) {
3868 assert(border->line.a.y == border->line.b.y);
3869 assert(!prev_border ||
3870 prev_border->line.a.y == border->line.a.y);
3871 assert(!prev_border ||
3872 (prev_border->line.a.x != border->line.a.x ||
3873 prev_border->line.b.x != border->line.b.x));
3874 assert(!prev_border ||
3875 prev_border->line.a.x <= border->line.a.x);
3876
3877 if (prev_border &&
3878 prev_border->line.a.x == border->line.a.x) {
3879 /*
3880 * ------------ +
3881 * ------- =
3882 * [ ]-----
3883 */
3884 prev_border->line.a.x = border->line.b.x;
3885 } else if (prev_border &&
3886 prev_border->line.b.x == border->line.b.x) {
3887 /*
3888 * ------------ +
3889 * ------ =
3890 * ------[ ]
3891 */
3892 prev_border->line.b.x = border->line.a.x;
3893 } else if (prev_border &&
3894 prev_border->line.b.x == border->line.a.x) {
3895 /*
3896 * -------- +
3897 * ------ =
3898 * --------------
3899 */
3900 prev_border->line.b.x = border->line.b.x;
3901 } else if (prev_border &&
3902 prev_border->line.b.x >= border->line.a.x) {
3903 /*
3904 * --------------- +
3905 * ------ =
3906 * -----[ ]----
3907 */
3908 new_border = add_border(borders,
3909 border->line.b.x,
3910 border->line.b.y,
3911 prev_border->line.b.x,
3912 prev_border->line.b.y,
3913 prev_border->blocking_dir);
3914 prev_border->line.b.x = border->line.a.x;
3915 prev_border = new_border;
3916 } else {
3917 assert(!prev_border ||
3918 prev_border->line.b.x < border->line.a.x);
3919 /*
3920 * First border or non-overlapping.
3921 *
3922 * ----- +
3923 * ----- =
3924 * ----- -----
3925 */
3926 new_border = wl_array_add(borders, sizeof *border);
3927 *new_border = *border;
3928 prev_border = new_border;
3929 }
3930 }
3931
3932 wl_array_release(&band_merge);
3933}
3934
3935static void
3936add_band_bottom_edges(pixman_box32_t *boxes,
3937 int band_start,
3938 int band_end,
3939 struct wl_array *borders)
3940{
3941 int i;
3942
3943 for (i = band_start; i < band_end; i++) {
3944 add_border(borders,
3945 boxes[i].x1, boxes[i].y2,
3946 boxes[i].x2, boxes[i].y2,
3947 MOTION_DIRECTION_POSITIVE_Y);
3948 }
3949}
3950
3951static void
3952region_to_outline(pixman_region32_t *region, struct wl_array *borders)
3953{
3954 pixman_box32_t *boxes;
3955 int num_boxes;
3956 int i;
3957 int top_most, bottom_most;
3958 int current_roof;
3959 int prev_top;
3960 int band_start, prev_band_start;
3961
3962 /*
3963 * Remove any overlapping lines from the set of rectangles. Note that
3964 * pixman regions are grouped as rows of rectangles, where rectangles
3965 * in one row never touch or overlap and are all of the same height.
3966 *
3967 * -------- --- -------- ---
3968 * | | | | | | | |
3969 * ----------====---- --- ----------- ----- ---
3970 * | | => | |
3971 * ----==========--------- ----- ----------
3972 * | | | |
3973 * ------------------- -------------------
3974 *
3975 */
3976
3977 boxes = pixman_region32_rectangles(region, &num_boxes);
3978 prev_top = 0;
3979 top_most = boxes[0].y1;
3980 current_roof = top_most;
3981 bottom_most = boxes[num_boxes - 1].y2;
3982 band_start = 0;
3983 prev_band_start = 0;
3984 for (i = 0; i < num_boxes; i++) {
3985 /* Detect if there is a vertical empty space, and add the lower
3986 * level of the previous band if so was the case. */
3987 if (i > 0 &&
3988 boxes[i].y1 != prev_top &&
3989 boxes[i].y1 != boxes[i - 1].y2) {
3990 current_roof = boxes[i].y1;
3991 add_band_bottom_edges(boxes,
3992 band_start,
3993 i,
3994 borders);
3995 }
3996
3997 /* Special case adding the last band, since it won't be handled
3998 * by the band change detection below. */
3999 if (boxes[i].y1 != current_roof && i == num_boxes - 1) {
4000 if (boxes[i].y1 != prev_top) {
4001 /* The last band is a single box, so we don't
4002 * have a prev_band_start to tell us when the
4003 * previous band started. */
4004 add_non_overlapping_edges(boxes,
4005 band_start,
4006 i,
4007 i + 1,
4008 borders);
4009 } else {
4010 add_non_overlapping_edges(boxes,
4011 prev_band_start,
4012 band_start,
4013 i + 1,
4014 borders);
4015 }
4016 }
4017
4018 /* Detect when passing a band and combine the top border of the
4019 * just passed band with the bottom band of the previous band.
4020 */
4021 if (boxes[i].y1 != top_most && boxes[i].y1 != prev_top) {
4022 /* Combine the two passed bands. */
4023 if (prev_top != current_roof) {
4024 add_non_overlapping_edges(boxes,
4025 prev_band_start,
4026 band_start,
4027 i,
4028 borders);
4029 }
4030
4031 prev_band_start = band_start;
4032 band_start = i;
4033 }
4034
4035 /* Add the top border if the box is part of the current roof. */
4036 if (boxes[i].y1 == current_roof) {
4037 add_border(borders,
4038 boxes[i].x1, boxes[i].y1,
4039 boxes[i].x2, boxes[i].y1,
4040 MOTION_DIRECTION_NEGATIVE_Y);
4041 }
4042
4043 /* Add the bottom border of the last band. */
4044 if (boxes[i].y2 == bottom_most) {
4045 add_border(borders,
4046 boxes[i].x1, boxes[i].y2,
4047 boxes[i].x2, boxes[i].y2,
4048 MOTION_DIRECTION_POSITIVE_Y);
4049 }
4050
4051 /* Always add the left border. */
4052 add_border(borders,
4053 boxes[i].x1, boxes[i].y1,
4054 boxes[i].x1, boxes[i].y2,
4055 MOTION_DIRECTION_NEGATIVE_X);
4056
4057 /* Always add the right border. */
4058 add_border(borders,
4059 boxes[i].x2, boxes[i].y1,
4060 boxes[i].x2, boxes[i].y2,
4061 MOTION_DIRECTION_POSITIVE_X);
4062
4063 prev_top = boxes[i].y1;
4064 }
4065}
4066
4067static bool
4068is_border_horizontal (struct border *border)
4069{
4070 return border->line.a.y == border->line.b.y;
4071}
4072
4073static bool
4074is_border_blocking_directions(struct border *border,
4075 uint32_t directions)
4076{
4077 /* Don't block parallel motions. */
4078 if (is_border_horizontal(border)) {
4079 if ((directions & (MOTION_DIRECTION_POSITIVE_Y |
4080 MOTION_DIRECTION_NEGATIVE_Y)) == 0)
4081 return false;
4082 } else {
4083 if ((directions & (MOTION_DIRECTION_POSITIVE_X |
4084 MOTION_DIRECTION_NEGATIVE_X)) == 0)
4085 return false;
4086 }
4087
4088 return (~border->blocking_dir & directions) != directions;
4089}
4090
4091static struct border *
4092get_closest_border(struct wl_array *borders,
4093 struct line *motion,
4094 uint32_t directions)
4095{
4096 struct border *border;
4097 struct vec2d intersection;
4098 struct vec2d delta;
4099 double distance_2;
4100 struct border *closest_border = NULL;
4101 double closest_distance_2 = DBL_MAX;
4102
4103 wl_array_for_each(border, borders) {
4104 if (!is_border_blocking_directions(border, directions))
4105 continue;
4106
4107 if (!lines_intersect(&border->line, motion, &intersection))
4108 continue;
4109
4110 delta = vec2d_subtract(intersection, motion->a);
4111 distance_2 = delta.x*delta.x + delta.y*delta.y;
4112 if (distance_2 < closest_distance_2) {
4113 closest_border = border;
4114 closest_distance_2 = distance_2;
4115 }
4116 }
4117
4118 return closest_border;
4119}
4120
4121static void
4122clamp_to_border(struct border *border,
4123 struct line *motion,
4124 uint32_t *motion_dir)
4125{
4126 /*
4127 * When clamping either rightward or downward motions, the motion needs
4128 * to be clamped so that the destination coordinate does not end up on
4129 * the border (see weston_pointer_clamp_event_to_region). Do this by
4130 * clamping such motions to the border minus the smallest possible
4131 * wl_fixed_t value.
4132 */
4133 if (is_border_horizontal(border)) {
4134 if (*motion_dir & MOTION_DIRECTION_POSITIVE_Y)
4135 motion->b.y = border->line.a.y - wl_fixed_to_double(1);
4136 else
4137 motion->b.y = border->line.a.y;
4138 *motion_dir &= ~(MOTION_DIRECTION_POSITIVE_Y |
4139 MOTION_DIRECTION_NEGATIVE_Y);
4140 } else {
4141 if (*motion_dir & MOTION_DIRECTION_POSITIVE_X)
4142 motion->b.x = border->line.a.x - wl_fixed_to_double(1);
4143 else
4144 motion->b.x = border->line.a.x;
4145 *motion_dir &= ~(MOTION_DIRECTION_POSITIVE_X |
4146 MOTION_DIRECTION_NEGATIVE_X);
4147 }
4148}
4149
4150static uint32_t
4151get_motion_directions(struct line *motion)
4152{
4153 uint32_t directions = 0;
4154
4155 if (motion->a.x < motion->b.x)
4156 directions |= MOTION_DIRECTION_POSITIVE_X;
4157 else if (motion->a.x > motion->b.x)
4158 directions |= MOTION_DIRECTION_NEGATIVE_X;
4159 if (motion->a.y < motion->b.y)
4160 directions |= MOTION_DIRECTION_POSITIVE_Y;
4161 else if (motion->a.y > motion->b.y)
4162 directions |= MOTION_DIRECTION_NEGATIVE_Y;
4163
4164 return directions;
4165}
4166
Jonas Ådahld3414f22016-07-22 17:56:31 +08004167static void
4168weston_pointer_clamp_event_to_region(struct weston_pointer *pointer,
4169 struct weston_pointer_motion_event *event,
4170 pixman_region32_t *region,
4171 wl_fixed_t *clamped_x,
4172 wl_fixed_t *clamped_y)
4173{
4174 wl_fixed_t x, y;
4175 wl_fixed_t sx, sy;
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004176 wl_fixed_t old_sx = pointer->sx;
4177 wl_fixed_t old_sy = pointer->sy;
4178 struct wl_array borders;
4179 struct line motion;
4180 struct border *closest_border;
4181 float new_x_f, new_y_f;
4182 uint32_t directions;
Jonas Ådahld3414f22016-07-22 17:56:31 +08004183
4184 weston_pointer_motion_to_abs(pointer, event, &x, &y);
4185 weston_view_from_global_fixed(pointer->focus, x, y, &sx, &sy);
4186
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004187 wl_array_init(&borders);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004188
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004189 /*
4190 * Generate borders given the confine region we are to use. The borders
4191 * are defined to be the outer region of the allowed area. This means
4192 * top/left borders are "within" the allowed area, while bottom/right
4193 * borders are outside. This needs to be considered when clamping
4194 * confined motion vectors.
4195 */
4196 region_to_outline(region, &borders);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004197
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004198 motion = (struct line) {
4199 .a = (struct vec2d) {
4200 .x = wl_fixed_to_double(old_sx),
4201 .y = wl_fixed_to_double(old_sy),
4202 },
4203 .b = (struct vec2d) {
4204 .x = wl_fixed_to_double(sx),
4205 .y = wl_fixed_to_double(sy),
4206 },
4207 };
4208 directions = get_motion_directions(&motion);
4209
4210 while (directions) {
4211 closest_border = get_closest_border(&borders,
4212 &motion,
4213 directions);
4214 if (closest_border)
4215 clamp_to_border(closest_border, &motion, &directions);
4216 else
4217 break;
4218 }
4219
4220 weston_view_to_global_float(pointer->focus,
4221 (float) motion.b.x, (float) motion.b.y,
4222 &new_x_f, &new_y_f);
4223 *clamped_x = wl_fixed_from_double(new_x_f);
4224 *clamped_y = wl_fixed_from_double(new_y_f);
4225
4226 wl_array_release(&borders);
4227}
4228
4229static double
4230point_to_border_distance_2(struct border *border, double x, double y)
4231{
4232 double orig_x, orig_y;
4233 double dx, dy;
4234
4235 if (is_border_horizontal(border)) {
4236 if (x < border->line.a.x)
4237 orig_x = border->line.a.x;
4238 else if (x > border->line.b.x)
4239 orig_x = border->line.b.x;
4240 else
4241 orig_x = x;
4242 orig_y = border->line.a.y;
4243 } else {
4244 if (y < border->line.a.y)
4245 orig_y = border->line.a.y;
4246 else if (y > border->line.b.y)
4247 orig_y = border->line.b.y;
4248 else
4249 orig_y = y;
4250 orig_x = border->line.a.x;
4251 }
4252
4253
4254 dx = fabs(orig_x - x);
4255 dy = fabs(orig_y - y);
4256 return dx*dx + dy*dy;
4257}
4258
4259static void
4260warp_to_behind_border(struct border *border, wl_fixed_t *sx, wl_fixed_t *sy)
4261{
4262 switch (border->blocking_dir) {
4263 case MOTION_DIRECTION_POSITIVE_X:
4264 case MOTION_DIRECTION_NEGATIVE_X:
4265 if (border->blocking_dir == MOTION_DIRECTION_POSITIVE_X)
4266 *sx = wl_fixed_from_double(border->line.a.x) - 1;
4267 else
4268 *sx = wl_fixed_from_double(border->line.a.x) + 1;
4269 if (*sy < wl_fixed_from_double(border->line.a.y))
4270 *sy = wl_fixed_from_double(border->line.a.y) + 1;
4271 else if (*sy > wl_fixed_from_double(border->line.b.y))
4272 *sy = wl_fixed_from_double(border->line.b.y) - 1;
4273 break;
4274 case MOTION_DIRECTION_POSITIVE_Y:
4275 case MOTION_DIRECTION_NEGATIVE_Y:
4276 if (border->blocking_dir == MOTION_DIRECTION_POSITIVE_Y)
4277 *sy = wl_fixed_from_double(border->line.a.y) - 1;
4278 else
4279 *sy = wl_fixed_from_double(border->line.a.y) + 1;
4280 if (*sx < wl_fixed_from_double(border->line.a.x))
4281 *sx = wl_fixed_from_double(border->line.a.x) + 1;
4282 else if (*sx > wl_fixed_from_double(border->line.b.x))
4283 *sx = wl_fixed_from_double(border->line.b.x) - 1;
4284 break;
4285 }
Jonas Ådahld3414f22016-07-22 17:56:31 +08004286}
4287
4288static void
4289maybe_warp_confined_pointer(struct weston_pointer_constraint *constraint)
4290{
4291 wl_fixed_t x;
4292 wl_fixed_t y;
4293 wl_fixed_t sx;
4294 wl_fixed_t sy;
4295
4296 weston_view_from_global_fixed(constraint->view,
4297 constraint->pointer->x,
4298 constraint->pointer->y,
4299 &sx,
4300 &sy);
4301
4302 if (!is_within_constraint_region(constraint, sx, sy)) {
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004303 double xf = wl_fixed_to_double(sx);
4304 double yf = wl_fixed_to_double(sy);
4305 pixman_region32_t confine_region;
4306 struct wl_array borders;
4307 struct border *border;
4308 double closest_distance_2 = DBL_MAX;
4309 struct border *closest_border = NULL;
Jonas Ådahld3414f22016-07-22 17:56:31 +08004310
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004311 wl_array_init(&borders);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004312
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004313 pixman_region32_init(&confine_region);
4314 pixman_region32_intersect(&confine_region,
4315 &constraint->view->surface->input,
4316 &constraint->region);
4317 region_to_outline(&confine_region, &borders);
4318 pixman_region32_fini(&confine_region);
4319
4320 wl_array_for_each(border, &borders) {
4321 double distance_2;
4322
4323 distance_2 = point_to_border_distance_2(border, xf, yf);
4324 if (distance_2 < closest_distance_2) {
4325 closest_border = border;
4326 closest_distance_2 = distance_2;
4327 }
4328 }
4329 assert(closest_border);
4330
4331 warp_to_behind_border(closest_border, &sx, &sy);
4332
4333 wl_array_release(&borders);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004334
4335 weston_view_to_global_fixed(constraint->view, sx, sy, &x, &y);
4336 weston_pointer_move_to(constraint->pointer, x, y);
4337 }
4338}
4339
4340static void
4341confined_pointer_grab_pointer_motion(struct weston_pointer_grab *grab,
Alexandros Frantzis84b31f82017-11-24 18:01:46 +02004342 const struct timespec *time,
Jonas Ådahld3414f22016-07-22 17:56:31 +08004343 struct weston_pointer_motion_event *event)
4344{
4345 struct weston_pointer_constraint *constraint =
4346 container_of(grab, struct weston_pointer_constraint, grab);
4347 struct weston_pointer *pointer = grab->pointer;
4348 struct weston_surface *surface;
4349 wl_fixed_t x, y;
4350 wl_fixed_t old_sx = pointer->sx;
4351 wl_fixed_t old_sy = pointer->sy;
4352 pixman_region32_t confine_region;
4353
4354 assert(pointer->focus);
4355 assert(pointer->focus->surface == constraint->surface);
4356
4357 surface = pointer->focus->surface;
4358
4359 pixman_region32_init(&confine_region);
4360 pixman_region32_intersect(&confine_region,
4361 &surface->input,
4362 &constraint->region);
4363 weston_pointer_clamp_event_to_region(pointer, event,
4364 &confine_region, &x, &y);
4365 weston_pointer_move_to(pointer, x, y);
4366 pixman_region32_fini(&confine_region);
4367
4368 weston_view_from_global_fixed(pointer->focus, x, y,
4369 &pointer->sx, &pointer->sy);
4370
4371 if (old_sx != pointer->sx || old_sy != pointer->sy) {
Quentin Glidiccde13452016-08-12 10:41:32 +02004372 pointer_send_motion(pointer, time,
4373 pointer->sx, pointer->sy);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004374 }
4375
Quentin Glidiccde13452016-08-12 10:41:32 +02004376 pointer_send_relative_motion(pointer, time, event);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004377}
4378
4379static void
4380confined_pointer_grab_pointer_button(struct weston_pointer_grab *grab,
Alexandros Frantzis215bedc2017-11-16 18:20:55 +02004381 const struct timespec *time,
Jonas Ådahld3414f22016-07-22 17:56:31 +08004382 uint32_t button,
4383 uint32_t state_w)
4384{
4385 weston_pointer_send_button(grab->pointer, time, button, state_w);
4386}
4387
4388static void
4389confined_pointer_grab_pointer_axis(struct weston_pointer_grab *grab,
Alexandros Frantzis80321942017-11-16 18:20:56 +02004390 const struct timespec *time,
Jonas Ådahld3414f22016-07-22 17:56:31 +08004391 struct weston_pointer_axis_event *event)
4392{
4393 weston_pointer_send_axis(grab->pointer, time, event);
4394}
4395
4396static void
4397confined_pointer_grab_pointer_axis_source(struct weston_pointer_grab *grab,
4398 uint32_t source)
4399{
4400 weston_pointer_send_axis_source(grab->pointer, source);
4401}
4402
4403static void
4404confined_pointer_grab_pointer_frame(struct weston_pointer_grab *grab)
4405{
4406 weston_pointer_send_frame(grab->pointer);
4407}
4408
4409static void
4410confined_pointer_grab_pointer_cancel(struct weston_pointer_grab *grab)
4411{
4412 struct weston_pointer_constraint *constraint =
4413 container_of(grab, struct weston_pointer_constraint, grab);
4414
4415 disable_pointer_constraint(constraint);
4416
4417 /* If this is a persistent constraint, re-add the surface destroy signal
4418 * listener only if we are currently not destroying the surface. */
4419 switch (constraint->lifetime) {
4420 case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT:
4421 if (constraint->surface->resource)
4422 wl_signal_add(&constraint->surface->destroy_signal,
4423 &constraint->surface_destroy_listener);
4424 break;
4425 case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT:
4426 break;
4427 }
4428}
4429
4430static const struct weston_pointer_grab_interface
4431 confined_pointer_grab_interface = {
4432 confined_pointer_grab_pointer_focus,
4433 confined_pointer_grab_pointer_motion,
4434 confined_pointer_grab_pointer_button,
4435 confined_pointer_grab_pointer_axis,
4436 confined_pointer_grab_pointer_axis_source,
4437 confined_pointer_grab_pointer_frame,
4438 confined_pointer_grab_pointer_cancel,
4439};
4440
4441static void
4442confined_pointer_destroy(struct wl_client *client,
4443 struct wl_resource *resource)
4444{
4445 wl_resource_destroy(resource);
4446}
4447
4448static void
4449confined_pointer_set_region(struct wl_client *client,
4450 struct wl_resource *resource,
4451 struct wl_resource *region_resource)
4452{
4453 struct weston_pointer_constraint *constraint =
4454 wl_resource_get_user_data(resource);
4455 struct weston_region *region = region_resource ?
4456 wl_resource_get_user_data(region_resource) : NULL;
4457
4458 if (!constraint)
4459 return;
4460
4461 if (region) {
4462 pixman_region32_copy(&constraint->region_pending,
4463 &region->region);
4464 } else {
4465 pixman_region32_fini(&constraint->region_pending);
4466 region_init_infinite(&constraint->region_pending);
4467 }
4468 constraint->region_is_pending = true;
4469}
4470
4471static const struct zwp_confined_pointer_v1_interface confined_pointer_interface = {
4472 confined_pointer_destroy,
4473 confined_pointer_set_region,
4474};
4475
4476static void
4477pointer_constraints_confine_pointer(struct wl_client *client,
4478 struct wl_resource *resource,
4479 uint32_t id,
4480 struct wl_resource *surface_resource,
4481 struct wl_resource *pointer_resource,
4482 struct wl_resource *region_resource,
4483 uint32_t lifetime)
4484{
4485 struct weston_surface *surface =
4486 wl_resource_get_user_data(surface_resource);
4487 struct weston_pointer *pointer = wl_resource_get_user_data(pointer_resource);
4488 struct weston_region *region = region_resource ?
4489 wl_resource_get_user_data(region_resource) : NULL;
4490
4491 init_pointer_constraint(resource, id, surface, pointer, region, lifetime,
4492 &zwp_confined_pointer_v1_interface,
4493 &confined_pointer_interface,
4494 &confined_pointer_grab_interface);
4495}
4496
4497static const struct zwp_pointer_constraints_v1_interface pointer_constraints_interface = {
4498 pointer_constraints_destroy,
4499 pointer_constraints_lock_pointer,
4500 pointer_constraints_confine_pointer,
4501};
4502
4503static void
4504bind_pointer_constraints(struct wl_client *client, void *data,
4505 uint32_t version, uint32_t id)
4506{
4507 struct wl_resource *resource;
4508
4509 resource = wl_resource_create(client,
4510 &zwp_pointer_constraints_v1_interface,
4511 1, id);
4512
4513 wl_resource_set_implementation(resource, &pointer_constraints_interface,
4514 NULL, NULL);
4515}
4516
Jonas Ådahl30d61d82014-10-22 21:21:17 +02004517int
4518weston_input_init(struct weston_compositor *compositor)
4519{
4520 if (!wl_global_create(compositor->wl_display,
4521 &zwp_relative_pointer_manager_v1_interface, 1,
4522 compositor, bind_relative_pointer_manager))
4523 return -1;
4524
Jonas Ådahld3414f22016-07-22 17:56:31 +08004525 if (!wl_global_create(compositor->wl_display,
4526 &zwp_pointer_constraints_v1_interface, 1,
4527 NULL, bind_pointer_constraints))
4528 return -1;
4529
Jonas Ådahl30d61d82014-10-22 21:21:17 +02004530 return 0;
4531}