blob: 4213aeebfe7ca004ebbd46af074a9fe8f508b0cd [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>
Matt Roper01a92732013-06-24 16:52:44 +010035#include <fcntl.h>
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +020036#include <limits.h>
Kristian Høgsberg2158a882013-04-18 15:07:39 -040037
Jon Cruz35b2eaa2015-06-15 15:37:08 -070038#include "shared/helpers.h"
Jon Cruz4678bab2015-06-15 15:37:07 -070039#include "shared/os-compatibility.h"
Kristian Høgsberg2158a882013-04-18 15:07:39 -040040#include "compositor.h"
Jonas Ådahl30d61d82014-10-22 21:21:17 +020041#include "protocol/relative-pointer-unstable-v1-server-protocol.h"
Jonas Ådahld3414f22016-07-22 17:56:31 +080042#include "protocol/pointer-constraints-unstable-v1-server-protocol.h"
43
44enum pointer_constraint_type {
45 POINTER_CONSTRAINT_TYPE_LOCK,
46 POINTER_CONSTRAINT_TYPE_CONFINE,
47};
48
49static void
50maybe_warp_confined_pointer(struct weston_pointer_constraint *constraint);
Kristian Høgsberg2158a882013-04-18 15:07:39 -040051
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040052static void
53empty_region(pixman_region32_t *region)
54{
55 pixman_region32_fini(region);
56 pixman_region32_init(region);
57}
58
Jonas Ådahld3414f22016-07-22 17:56:31 +080059static void
60region_init_infinite(pixman_region32_t *region)
61{
62 pixman_region32_init_rect(region, INT32_MIN, INT32_MIN,
63 UINT32_MAX, UINT32_MAX);
64}
65
Jonas Ådahl2cbf2932015-07-22 12:05:38 +080066static struct weston_pointer_client *
67weston_pointer_client_create(struct wl_client *client)
68{
69 struct weston_pointer_client *pointer_client;
70
71 pointer_client = zalloc(sizeof *pointer_client);
72 if (!pointer_client)
73 return NULL;
74
75 pointer_client->client = client;
76 wl_list_init(&pointer_client->pointer_resources);
Jonas Ådahl30d61d82014-10-22 21:21:17 +020077 wl_list_init(&pointer_client->relative_pointer_resources);
Jonas Ådahl2cbf2932015-07-22 12:05:38 +080078
79 return pointer_client;
80}
81
82static void
83weston_pointer_client_destroy(struct weston_pointer_client *pointer_client)
84{
85 free(pointer_client);
86}
87
88static bool
89weston_pointer_client_is_empty(struct weston_pointer_client *pointer_client)
90{
Jonas Ådahl30d61d82014-10-22 21:21:17 +020091 return (wl_list_empty(&pointer_client->pointer_resources) &&
92 wl_list_empty(&pointer_client->relative_pointer_resources));
Jonas Ådahl2cbf2932015-07-22 12:05:38 +080093}
94
95static struct weston_pointer_client *
96weston_pointer_get_pointer_client(struct weston_pointer *pointer,
97 struct wl_client *client)
98{
99 struct weston_pointer_client *pointer_client;
100
101 wl_list_for_each(pointer_client, &pointer->pointer_clients, link) {
102 if (pointer_client->client == client)
103 return pointer_client;
104 }
105
106 return NULL;
107}
108
109static struct weston_pointer_client *
110weston_pointer_ensure_pointer_client(struct weston_pointer *pointer,
111 struct wl_client *client)
112{
113 struct weston_pointer_client *pointer_client;
114
115 pointer_client = weston_pointer_get_pointer_client(pointer, client);
116 if (pointer_client)
117 return pointer_client;
118
119 pointer_client = weston_pointer_client_create(client);
120 wl_list_insert(&pointer->pointer_clients, &pointer_client->link);
121
122 if (pointer->focus &&
123 pointer->focus->surface->resource &&
124 wl_resource_get_client(pointer->focus->surface->resource) == client) {
125 pointer->focus_client = pointer_client;
126 }
127
128 return pointer_client;
129}
130
131static void
132weston_pointer_cleanup_pointer_client(struct weston_pointer *pointer,
133 struct weston_pointer_client *pointer_client)
134{
135 if (weston_pointer_client_is_empty(pointer_client)) {
136 if (pointer->focus_client == pointer_client)
137 pointer->focus_client = NULL;
138 wl_list_remove(&pointer_client->link);
139 weston_pointer_client_destroy(pointer_client);
140 }
141}
142
143static void
144unbind_pointer_client_resource(struct wl_resource *resource)
145{
146 struct weston_pointer *pointer = wl_resource_get_user_data(resource);
147 struct wl_client *client = wl_resource_get_client(resource);
148 struct weston_pointer_client *pointer_client;
149
150 pointer_client = weston_pointer_get_pointer_client(pointer, client);
151 assert(pointer_client);
152
153 wl_list_remove(wl_resource_get_link(resource));
154 weston_pointer_cleanup_pointer_client(pointer, pointer_client);
155}
156
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400157static void unbind_resource(struct wl_resource *resource)
158{
Jason Ekstrand44a38632013-06-14 10:08:00 -0500159 wl_list_remove(wl_resource_get_link(resource));
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400160}
161
Jonas Ådahl3042ffe2013-10-17 23:04:08 +0200162WL_EXPORT void
Jonas Ådahl30d61d82014-10-22 21:21:17 +0200163weston_pointer_motion_to_abs(struct weston_pointer *pointer,
164 struct weston_pointer_motion_event *event,
165 wl_fixed_t *x, wl_fixed_t *y)
166{
167 if (event->mask & WESTON_POINTER_MOTION_ABS) {
168 *x = wl_fixed_from_double(event->x);
169 *y = wl_fixed_from_double(event->y);
170 } else if (event->mask & WESTON_POINTER_MOTION_REL) {
171 *x = pointer->x + wl_fixed_from_double(event->dx);
172 *y = pointer->y + wl_fixed_from_double(event->dy);
173 } else {
174 assert(!"invalid motion event");
175 *x = *y = 0;
176 }
177}
178
179static bool
180weston_pointer_motion_to_rel(struct weston_pointer *pointer,
181 struct weston_pointer_motion_event *event,
182 double *dx, double *dy,
183 double *dx_unaccel, double *dy_unaccel)
184{
185 if (event->mask & WESTON_POINTER_MOTION_REL &&
186 event->mask & WESTON_POINTER_MOTION_REL_UNACCEL) {
187 *dx = event->dx;
188 *dy = event->dy;
189 *dx_unaccel = event->dx_unaccel;
190 *dy_unaccel = event->dy_unaccel;
191 return true;
192 } else if (event->mask & WESTON_POINTER_MOTION_REL) {
193 *dx_unaccel = *dx = event->dx;
194 *dy_unaccel = *dy = event->dy;
195 return true;
196 } else if (event->mask & WESTON_POINTER_MOTION_REL_UNACCEL) {
197 *dx_unaccel = *dx = event->dx_unaccel;
198 *dy_unaccel = *dy = event->dy_unaccel;
199 return true;
200 } else {
201 return false;
202 }
203}
204
205WL_EXPORT void
Kristian Høgsberga71e8b22013-05-06 21:51:21 -0400206weston_seat_repick(struct weston_seat *seat)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400207{
Derek Foreman1281a362015-07-31 16:55:32 -0500208 const struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400209
Derek Foreman1b786ee2015-06-03 15:53:23 -0500210 if (!pointer)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400211 return;
212
Derek Foreman1b786ee2015-06-03 15:53:23 -0500213 pointer->grab->interface->focus(pointer->grab);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400214}
215
216static void
217weston_compositor_idle_inhibit(struct weston_compositor *compositor)
218{
219 weston_compositor_wake(compositor);
220 compositor->idle_inhibit++;
221}
222
223static void
224weston_compositor_idle_release(struct weston_compositor *compositor)
225{
226 compositor->idle_inhibit--;
227 weston_compositor_wake(compositor);
228}
229
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400230static void
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100231pointer_focus_view_destroyed(struct wl_listener *listener, void *data)
232{
233 struct weston_pointer *pointer =
234 container_of(listener, struct weston_pointer,
235 focus_view_listener);
236
Derek Foremanf9318d12015-05-11 15:40:11 -0500237 weston_pointer_clear_focus(pointer);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100238}
239
240static void
241pointer_focus_resource_destroyed(struct wl_listener *listener, void *data)
242{
243 struct weston_pointer *pointer =
244 container_of(listener, struct weston_pointer,
245 focus_resource_listener);
246
Derek Foremanf9318d12015-05-11 15:40:11 -0500247 weston_pointer_clear_focus(pointer);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100248}
249
250static void
251keyboard_focus_resource_destroyed(struct wl_listener *listener, void *data)
252{
253 struct weston_keyboard *keyboard =
254 container_of(listener, struct weston_keyboard,
255 focus_resource_listener);
256
257 weston_keyboard_set_focus(keyboard, NULL);
258}
259
260static void
261touch_focus_view_destroyed(struct wl_listener *listener, void *data)
262{
263 struct weston_touch *touch =
264 container_of(listener, struct weston_touch,
265 focus_view_listener);
266
Derek Foreman4c93c082015-04-30 16:45:41 -0500267 weston_touch_set_focus(touch, NULL);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100268}
269
270static void
271touch_focus_resource_destroyed(struct wl_listener *listener, void *data)
272{
273 struct weston_touch *touch =
274 container_of(listener, struct weston_touch,
275 focus_resource_listener);
276
Derek Foreman4c93c082015-04-30 16:45:41 -0500277 weston_touch_set_focus(touch, NULL);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100278}
279
280static void
Neil Roberts96d790e2013-09-19 17:32:00 +0100281move_resources(struct wl_list *destination, struct wl_list *source)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400282{
Neil Roberts96d790e2013-09-19 17:32:00 +0100283 wl_list_insert_list(destination, source);
284 wl_list_init(source);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400285}
286
287static void
Neil Roberts96d790e2013-09-19 17:32:00 +0100288move_resources_for_client(struct wl_list *destination,
289 struct wl_list *source,
290 struct wl_client *client)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400291{
Neil Roberts96d790e2013-09-19 17:32:00 +0100292 struct wl_resource *resource, *tmp;
293 wl_resource_for_each_safe(resource, tmp, source) {
294 if (wl_resource_get_client(resource) == client) {
295 wl_list_remove(wl_resource_get_link(resource));
296 wl_list_insert(destination,
297 wl_resource_get_link(resource));
298 }
299 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400300}
301
302static void
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700303default_grab_pointer_focus(struct weston_pointer_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400304{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400305 struct weston_pointer *pointer = grab->pointer;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500306 struct weston_view *view;
Kristian Høgsberg6848c252013-05-08 22:02:59 -0400307 wl_fixed_t sx, sy;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400308
309 if (pointer->button_count > 0)
310 return;
311
Jason Ekstranda7af7042013-10-12 22:38:11 -0500312 view = weston_compositor_pick_view(pointer->seat->compositor,
313 pointer->x, pointer->y,
314 &sx, &sy);
Kristian Høgsberg6848c252013-05-08 22:02:59 -0400315
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -0800316 if (pointer->focus != view || pointer->sx != sx || pointer->sy != sy)
Jason Ekstranda7af7042013-10-12 22:38:11 -0500317 weston_pointer_set_focus(pointer, view, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400318}
319
320static void
Jonas Ådahl30d61d82014-10-22 21:21:17 +0200321weston_pointer_send_relative_motion(struct weston_pointer *pointer,
322 uint32_t time,
323 struct weston_pointer_motion_event *event)
324{
325 uint64_t time_usec;
326 double dx, dy, dx_unaccel, dy_unaccel;
327 wl_fixed_t dxf, dyf, dxf_unaccel, dyf_unaccel;
328 struct wl_list *resource_list;
329 struct wl_resource *resource;
330
331 if (!pointer->focus_client)
332 return;
333
334 if (!weston_pointer_motion_to_rel(pointer, event,
335 &dx, &dy,
336 &dx_unaccel, &dy_unaccel))
337 return;
338
339 resource_list = &pointer->focus_client->relative_pointer_resources;
340 time_usec = event->time_usec;
341 if (time_usec == 0)
342 time_usec = time * 1000ULL;
343
344 dxf = wl_fixed_from_double(dx);
345 dyf = wl_fixed_from_double(dy);
346 dxf_unaccel = wl_fixed_from_double(dx_unaccel);
347 dyf_unaccel = wl_fixed_from_double(dy_unaccel);
348
349 wl_resource_for_each(resource, resource_list) {
350 zwp_relative_pointer_v1_send_relative_motion(
351 resource,
352 (uint32_t) (time_usec >> 32),
353 (uint32_t) time_usec,
354 dxf, dyf,
355 dxf_unaccel, dyf_unaccel);
356 }
357}
358
359static void
Jonas Ådahlf44942e2016-07-22 17:54:55 +0800360weston_pointer_send_motion(struct weston_pointer *pointer, uint32_t time,
361 wl_fixed_t sx, wl_fixed_t sy)
362{
363 struct wl_list *resource_list;
364 struct wl_resource *resource;
365
366 if (!pointer->focus_client)
367 return;
368
369 resource_list = &pointer->focus_client->pointer_resources;
370 wl_resource_for_each(resource, resource_list)
371 wl_pointer_send_motion(resource, time, sx, sy);
372}
373
374static void
Giulio Camuffo1959ab82013-11-14 23:42:52 +0100375default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time,
Jonas Ådahld2510102014-10-05 21:39:14 +0200376 struct weston_pointer_motion_event *event)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400377{
Kristian Høgsbergbe6403e2013-05-08 21:03:21 -0400378 struct weston_pointer *pointer = grab->pointer;
Jonas Ådahld2510102014-10-05 21:39:14 +0200379 wl_fixed_t x, y;
Jonas Ådahl8283c342015-04-24 15:26:17 +0800380 wl_fixed_t old_sx = pointer->sx;
381 wl_fixed_t old_sy = pointer->sy;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400382
Jonas Ådahld2510102014-10-05 21:39:14 +0200383 if (pointer->focus) {
384 weston_pointer_motion_to_abs(pointer, event, &x, &y);
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -0800385 weston_view_from_global_fixed(pointer->focus, x, y,
386 &pointer->sx, &pointer->sy);
Jonas Ådahld2510102014-10-05 21:39:14 +0200387 }
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -0800388
Jonas Ådahld2510102014-10-05 21:39:14 +0200389 weston_pointer_move(pointer, event);
Giulio Camuffo1959ab82013-11-14 23:42:52 +0100390
Jonas Ådahlf44942e2016-07-22 17:54:55 +0800391 if (old_sx != pointer->sx || old_sy != pointer->sy) {
392 weston_pointer_send_motion(pointer, time,
393 pointer->sx, pointer->sy);
Kristian Høgsbergbe6403e2013-05-08 21:03:21 -0400394 }
Jonas Ådahl30d61d82014-10-22 21:21:17 +0200395
396 weston_pointer_send_relative_motion(pointer, time, event);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400397}
398
399static void
Jonas Ådahlc02ac112016-07-22 17:55:43 +0800400weston_pointer_send_button(struct weston_pointer *pointer,
401 uint32_t time, uint32_t button, uint32_t state_w)
402{
403 struct wl_display *display = pointer->seat->compositor->wl_display;
404 struct wl_list *resource_list;
405 struct wl_resource *resource;
406 uint32_t serial;
407
408 if (!pointer->focus_client)
409 return;
410
411 resource_list = &pointer->focus_client->pointer_resources;
412 if (resource_list && !wl_list_empty(resource_list)) {
413 resource_list = &pointer->focus_client->pointer_resources;
414 serial = wl_display_next_serial(display);
415 wl_resource_for_each(resource, resource_list) {
416 wl_pointer_send_button(resource,
417 serial,
418 time,
419 button,
420 state_w);
421 }
422 }
423}
424
425static void
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700426default_grab_pointer_button(struct weston_pointer_grab *grab,
427 uint32_t time, uint32_t button, uint32_t state_w)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400428{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400429 struct weston_pointer *pointer = grab->pointer;
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400430 struct weston_compositor *compositor = pointer->seat->compositor;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500431 struct weston_view *view;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400432 enum wl_pointer_button_state state = state_w;
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400433 wl_fixed_t sx, sy;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400434
Jonas Ådahlc02ac112016-07-22 17:55:43 +0800435 weston_pointer_send_button(pointer, time, button, state_w);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400436
437 if (pointer->button_count == 0 &&
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400438 state == WL_POINTER_BUTTON_STATE_RELEASED) {
Jason Ekstranda7af7042013-10-12 22:38:11 -0500439 view = weston_compositor_pick_view(compositor,
440 pointer->x, pointer->y,
441 &sx, &sy);
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400442
Jason Ekstranda7af7042013-10-12 22:38:11 -0500443 weston_pointer_set_focus(pointer, view, sx, sy);
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400444 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400445}
446
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200447/** Send wl_pointer.axis events to focused resources.
448 *
449 * \param pointer The pointer where the axis events originates from.
450 * \param time The timestamp of the event
451 * \param axis The axis enum value of the event
452 * \param value The axis value of the event
453 *
454 * For every resource that is currently in focus, send a wl_pointer.axis event
455 * with the passed parameters. The focused resources are the wl_pointer
456 * resources of the client which currently has the surface with pointer focus.
457 */
458WL_EXPORT void
459weston_pointer_send_axis(struct weston_pointer *pointer,
Peter Hutterer89b6a492016-01-18 15:58:17 +1000460 uint32_t time,
461 struct weston_pointer_axis_event *event)
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200462{
463 struct wl_resource *resource;
464 struct wl_list *resource_list;
465
Jonas Ådahl2cbf2932015-07-22 12:05:38 +0800466 if (!pointer->focus_client)
467 return;
468
469 resource_list = &pointer->focus_client->pointer_resources;
Peter Hutterer87743e92016-01-18 16:38:22 +1000470 wl_resource_for_each(resource, resource_list) {
471 if (event->has_discrete &&
472 wl_resource_get_version(resource) >=
473 WL_POINTER_AXIS_DISCRETE_SINCE_VERSION)
474 wl_pointer_send_axis_discrete(resource, event->axis,
475 event->discrete);
476
477 if (event->value)
478 wl_pointer_send_axis(resource, time,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +0200479 event->axis,
480 wl_fixed_from_double(event->value));
Peter Hutterer87743e92016-01-18 16:38:22 +1000481 else if (wl_resource_get_version(resource) >=
482 WL_POINTER_AXIS_STOP_SINCE_VERSION)
483 wl_pointer_send_axis_stop(resource, time,
484 event->axis);
485 }
486}
487
488WL_EXPORT void
489weston_pointer_send_axis_source(struct weston_pointer *pointer, uint32_t source)
490{
491 struct wl_resource *resource;
492 struct wl_list *resource_list;
493
Jonas Ådahled6014a2016-04-21 10:21:48 +0800494 if (!pointer->focus_client)
495 return;
496
Peter Hutterer87743e92016-01-18 16:38:22 +1000497 resource_list = &pointer->focus_client->pointer_resources;
498 wl_resource_for_each(resource, resource_list) {
499 if (wl_resource_get_version(resource) >=
500 WL_POINTER_AXIS_SOURCE_SINCE_VERSION) {
501 wl_pointer_send_axis_source(resource, source);
502 }
503 }
504}
505
506static void
507pointer_send_frame(struct wl_resource *resource)
508{
509 if (wl_resource_get_version(resource) >=
510 WL_POINTER_FRAME_SINCE_VERSION) {
511 wl_pointer_send_frame(resource);
512 }
513}
514
515WL_EXPORT void
516weston_pointer_send_frame(struct weston_pointer *pointer)
517{
518 struct wl_resource *resource;
519 struct wl_list *resource_list;
520
Derek Foreman8efa31b2016-01-29 10:29:46 -0600521 if (!pointer->focus_client)
522 return;
523
Peter Hutterer87743e92016-01-18 16:38:22 +1000524 resource_list = &pointer->focus_client->pointer_resources;
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200525 wl_resource_for_each(resource, resource_list)
Peter Hutterer87743e92016-01-18 16:38:22 +1000526 pointer_send_frame(resource);
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200527}
528
529static void
530default_grab_pointer_axis(struct weston_pointer_grab *grab,
Peter Hutterer89b6a492016-01-18 15:58:17 +1000531 uint32_t time,
532 struct weston_pointer_axis_event *event)
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200533{
Peter Hutterer89b6a492016-01-18 15:58:17 +1000534 weston_pointer_send_axis(grab->pointer, time, event);
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200535}
536
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200537static void
Peter Hutterer87743e92016-01-18 16:38:22 +1000538default_grab_pointer_axis_source(struct weston_pointer_grab *grab,
539 uint32_t source)
540{
541 weston_pointer_send_axis_source(grab->pointer, source);
542}
543
544static void
545default_grab_pointer_frame(struct weston_pointer_grab *grab)
546{
547 weston_pointer_send_frame(grab->pointer);
548}
549
550static void
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200551default_grab_pointer_cancel(struct weston_pointer_grab *grab)
552{
553}
554
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400555static const struct weston_pointer_grab_interface
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400556 default_pointer_grab_interface = {
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700557 default_grab_pointer_focus,
558 default_grab_pointer_motion,
559 default_grab_pointer_button,
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200560 default_grab_pointer_axis,
Peter Hutterer87743e92016-01-18 16:38:22 +1000561 default_grab_pointer_axis_source,
562 default_grab_pointer_frame,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200563 default_grab_pointer_cancel,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400564};
565
Kristian Høgsberge329f362013-05-06 22:19:57 -0400566static void
567default_grab_touch_down(struct weston_touch_grab *grab, uint32_t time,
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300568 int touch_id, wl_fixed_t x, wl_fixed_t y)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400569{
Kristian Høgsberge329f362013-05-06 22:19:57 -0400570 struct weston_touch *touch = grab->touch;
Rob Bradford880ebc72013-07-22 17:31:38 +0100571 struct wl_display *display = touch->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400572 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +0100573 struct wl_resource *resource;
574 struct wl_list *resource_list;
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300575 wl_fixed_t sx, sy;
576
Bryce Harrington2c40d1d2016-02-02 10:18:48 -0800577 if (!touch->focus)
578 return;
579
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300580 weston_view_from_global_fixed(touch->focus, x, y, &sx, &sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400581
Neil Roberts96d790e2013-09-19 17:32:00 +0100582 resource_list = &touch->focus_resource_list;
583
Bryce Harrington2c40d1d2016-02-02 10:18:48 -0800584 if (!wl_list_empty(resource_list)) {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400585 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +0100586 wl_resource_for_each(resource, resource_list)
587 wl_touch_send_down(resource, serial, time,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500588 touch->focus->surface->resource,
Neil Roberts96d790e2013-09-19 17:32:00 +0100589 touch_id, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400590 }
591}
592
Kristian Høgsberge329f362013-05-06 22:19:57 -0400593static void
594default_grab_touch_up(struct weston_touch_grab *grab,
595 uint32_t time, int touch_id)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400596{
Kristian Høgsberge329f362013-05-06 22:19:57 -0400597 struct weston_touch *touch = grab->touch;
Rob Bradford880ebc72013-07-22 17:31:38 +0100598 struct wl_display *display = touch->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400599 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +0100600 struct wl_resource *resource;
601 struct wl_list *resource_list;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400602
Neil Roberts96d790e2013-09-19 17:32:00 +0100603 resource_list = &touch->focus_resource_list;
604
605 if (!wl_list_empty(resource_list)) {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400606 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +0100607 wl_resource_for_each(resource, resource_list)
608 wl_touch_send_up(resource, serial, time, touch_id);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400609 }
610}
611
Kristian Høgsberge329f362013-05-06 22:19:57 -0400612static void
613default_grab_touch_motion(struct weston_touch_grab *grab, uint32_t time,
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300614 int touch_id, wl_fixed_t x, wl_fixed_t y)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400615{
Kristian Høgsberge329f362013-05-06 22:19:57 -0400616 struct weston_touch *touch = grab->touch;
Neil Roberts96d790e2013-09-19 17:32:00 +0100617 struct wl_resource *resource;
618 struct wl_list *resource_list;
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300619 wl_fixed_t sx, sy;
620
621 weston_view_from_global_fixed(touch->focus, x, y, &sx, &sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400622
Neil Roberts96d790e2013-09-19 17:32:00 +0100623 resource_list = &touch->focus_resource_list;
624
625 wl_resource_for_each(resource, resource_list) {
626 wl_touch_send_motion(resource, time,
Kristian Høgsberge329f362013-05-06 22:19:57 -0400627 touch_id, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400628 }
629}
630
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200631static void
Jonas Ådahl1679f232014-04-12 09:39:51 +0200632default_grab_touch_frame(struct weston_touch_grab *grab)
633{
634 struct wl_resource *resource;
635
636 wl_resource_for_each(resource, &grab->touch->focus_resource_list)
637 wl_touch_send_frame(resource);
638}
639
640static void
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200641default_grab_touch_cancel(struct weston_touch_grab *grab)
642{
643}
644
Kristian Høgsberge329f362013-05-06 22:19:57 -0400645static const struct weston_touch_grab_interface default_touch_grab_interface = {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400646 default_grab_touch_down,
647 default_grab_touch_up,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200648 default_grab_touch_motion,
Jonas Ådahl1679f232014-04-12 09:39:51 +0200649 default_grab_touch_frame,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200650 default_grab_touch_cancel,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400651};
652
653static void
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700654default_grab_keyboard_key(struct weston_keyboard_grab *grab,
655 uint32_t time, uint32_t key, uint32_t state)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400656{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400657 struct weston_keyboard *keyboard = grab->keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400658 struct wl_resource *resource;
Rob Bradford880ebc72013-07-22 17:31:38 +0100659 struct wl_display *display = keyboard->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400660 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +0100661 struct wl_list *resource_list;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400662
Neil Roberts96d790e2013-09-19 17:32:00 +0100663 resource_list = &keyboard->focus_resource_list;
664 if (!wl_list_empty(resource_list)) {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400665 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +0100666 wl_resource_for_each(resource, resource_list)
667 wl_keyboard_send_key(resource,
668 serial,
669 time,
670 key,
671 state);
672 }
673}
674
675static void
676send_modifiers_to_resource(struct weston_keyboard *keyboard,
677 struct wl_resource *resource,
678 uint32_t serial)
679{
680 wl_keyboard_send_modifiers(resource,
681 serial,
682 keyboard->modifiers.mods_depressed,
683 keyboard->modifiers.mods_latched,
684 keyboard->modifiers.mods_locked,
685 keyboard->modifiers.group);
686}
687
688static void
689send_modifiers_to_client_in_list(struct wl_client *client,
690 struct wl_list *list,
691 uint32_t serial,
692 struct weston_keyboard *keyboard)
693{
694 struct wl_resource *resource;
695
696 wl_resource_for_each(resource, list) {
697 if (wl_resource_get_client(resource) == client)
698 send_modifiers_to_resource(keyboard,
699 resource,
700 serial);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400701 }
702}
703
Jonas Ådahl2cbf2932015-07-22 12:05:38 +0800704static struct weston_pointer_client *
705find_pointer_client_for_surface(struct weston_pointer *pointer,
706 struct weston_surface *surface)
707{
708 struct wl_client *client;
709
710 if (!surface)
711 return NULL;
712
713 if (!surface->resource)
714 return NULL;
715
716 client = wl_resource_get_client(surface->resource);
717 return weston_pointer_get_pointer_client(pointer, client);
718}
719
720static struct weston_pointer_client *
721find_pointer_client_for_view(struct weston_pointer *pointer, struct weston_view *view)
722{
723 if (!view)
724 return NULL;
725
726 return find_pointer_client_for_surface(pointer, view->surface);
727}
728
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400729static struct wl_resource *
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400730find_resource_for_surface(struct wl_list *list, struct weston_surface *surface)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400731{
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400732 if (!surface)
733 return NULL;
734
Jason Ekstrand44a38632013-06-14 10:08:00 -0500735 if (!surface->resource)
736 return NULL;
Stefan Schmidtfda26522013-09-17 10:54:09 +0100737
Jason Ekstrand44a38632013-06-14 10:08:00 -0500738 return wl_resource_find_for_client(list, wl_resource_get_client(surface->resource));
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400739}
740
741static void
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700742default_grab_keyboard_modifiers(struct weston_keyboard_grab *grab,
743 uint32_t serial, uint32_t mods_depressed,
744 uint32_t mods_latched,
745 uint32_t mods_locked, uint32_t group)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400746{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400747 struct weston_keyboard *keyboard = grab->keyboard;
Derek Foreman1281a362015-07-31 16:55:32 -0500748 struct weston_pointer *pointer =
749 weston_seat_get_pointer(grab->keyboard->seat);
Neil Roberts96d790e2013-09-19 17:32:00 +0100750 struct wl_resource *resource;
751 struct wl_list *resource_list;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400752
Neil Roberts96d790e2013-09-19 17:32:00 +0100753 resource_list = &keyboard->focus_resource_list;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400754
Neil Roberts96d790e2013-09-19 17:32:00 +0100755 wl_resource_for_each(resource, resource_list) {
756 wl_keyboard_send_modifiers(resource, serial, mods_depressed,
757 mods_latched, mods_locked, group);
758 }
Jason Ekstrand42133d42013-11-14 20:06:16 -0600759 if (pointer && pointer->focus && pointer->focus->surface->resource &&
760 pointer->focus->surface != keyboard->focus) {
Neil Roberts96d790e2013-09-19 17:32:00 +0100761 struct wl_client *pointer_client =
Jason Ekstranda7af7042013-10-12 22:38:11 -0500762 wl_resource_get_client(pointer->focus->surface->resource);
Neil Roberts96d790e2013-09-19 17:32:00 +0100763 send_modifiers_to_client_in_list(pointer_client,
764 &keyboard->resource_list,
765 serial,
766 keyboard);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400767 }
768}
769
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200770static void
771default_grab_keyboard_cancel(struct weston_keyboard_grab *grab)
772{
773}
774
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400775static const struct weston_keyboard_grab_interface
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400776 default_keyboard_grab_interface = {
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700777 default_grab_keyboard_key,
778 default_grab_keyboard_modifiers,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200779 default_grab_keyboard_cancel,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400780};
781
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400782static void
783pointer_unmap_sprite(struct weston_pointer *pointer)
784{
Pekka Paalanenc557ff72014-11-12 16:42:52 +0200785 struct weston_surface *surface = pointer->sprite->surface;
786
787 if (weston_surface_is_mapped(surface))
788 weston_surface_unmap(surface);
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400789
790 wl_list_remove(&pointer->sprite_destroy_listener.link);
Pekka Paalanenc557ff72014-11-12 16:42:52 +0200791 surface->configure = NULL;
792 surface->configure_private = NULL;
Pekka Paalanen8274d902014-08-06 19:36:51 +0300793 weston_surface_set_label_func(surface, NULL);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500794 weston_view_destroy(pointer->sprite);
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400795 pointer->sprite = NULL;
796}
797
798static void
799pointer_handle_sprite_destroy(struct wl_listener *listener, void *data)
800{
801 struct weston_pointer *pointer =
802 container_of(listener, struct weston_pointer,
803 sprite_destroy_listener);
804
805 pointer->sprite = NULL;
806}
807
Jonas Ådahl3e12e632013-12-02 22:05:05 +0100808static void
809weston_pointer_reset_state(struct weston_pointer *pointer)
810{
811 pointer->button_count = 0;
812}
813
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +0200814static void
815weston_pointer_handle_output_destroy(struct wl_listener *listener, void *data);
816
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400817WL_EXPORT struct weston_pointer *
Giulio Camuffocdb4d292013-11-14 23:42:53 +0100818weston_pointer_create(struct weston_seat *seat)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400819{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400820 struct weston_pointer *pointer;
821
Peter Huttererf3d62272013-08-08 11:57:05 +1000822 pointer = zalloc(sizeof *pointer);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400823 if (pointer == NULL)
824 return NULL;
825
Jonas Ådahl2cbf2932015-07-22 12:05:38 +0800826 wl_list_init(&pointer->pointer_clients);
Giulio Camuffocdb4d292013-11-14 23:42:53 +0100827 weston_pointer_set_default_grab(pointer,
828 seat->compositor->default_pointer_grab);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100829 wl_list_init(&pointer->focus_resource_listener.link);
830 pointer->focus_resource_listener.notify = pointer_focus_resource_destroyed;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400831 pointer->default_grab.pointer = pointer;
832 pointer->grab = &pointer->default_grab;
Giulio Camuffo6fcb3782013-11-14 23:42:50 +0100833 wl_signal_init(&pointer->motion_signal);
Emilio Pozuelo Monfortaa7a4762013-11-19 11:37:15 +0100834 wl_signal_init(&pointer->focus_signal);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100835 wl_list_init(&pointer->focus_view_listener.link);
Jonas Ådahl3eb4ddd2016-07-22 17:52:58 +0800836 wl_signal_init(&pointer->destroy_signal);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400837
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400838 pointer->sprite_destroy_listener.notify = pointer_handle_sprite_destroy;
839
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400840 /* FIXME: Pick better co-ords. */
841 pointer->x = wl_fixed_from_int(100);
842 pointer->y = wl_fixed_from_int(100);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400843
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +0200844 pointer->output_destroy_listener.notify =
845 weston_pointer_handle_output_destroy;
846 wl_signal_add(&seat->compositor->output_destroyed_signal,
847 &pointer->output_destroy_listener);
848
Derek Foremanf9318d12015-05-11 15:40:11 -0500849 pointer->sx = wl_fixed_from_int(-1000000);
850 pointer->sy = wl_fixed_from_int(-1000000);
851
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400852 return pointer;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400853}
854
855WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400856weston_pointer_destroy(struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400857{
Jonas Ådahl3eb4ddd2016-07-22 17:52:58 +0800858 wl_signal_emit(&pointer->destroy_signal, pointer);
859
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400860 if (pointer->sprite)
861 pointer_unmap_sprite(pointer);
862
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400863 /* XXX: What about pointer->resource_list? */
Neil Roberts96d790e2013-09-19 17:32:00 +0100864
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100865 wl_list_remove(&pointer->focus_resource_listener.link);
866 wl_list_remove(&pointer->focus_view_listener.link);
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +0200867 wl_list_remove(&pointer->output_destroy_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400868 free(pointer);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400869}
870
Giulio Camuffocdb4d292013-11-14 23:42:53 +0100871void
872weston_pointer_set_default_grab(struct weston_pointer *pointer,
873 const struct weston_pointer_grab_interface *interface)
874{
875 if (interface)
876 pointer->default_grab.interface = interface;
877 else
878 pointer->default_grab.interface =
879 &default_pointer_grab_interface;
880}
881
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400882WL_EXPORT struct weston_keyboard *
883weston_keyboard_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400884{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400885 struct weston_keyboard *keyboard;
886
Peter Huttererf3d62272013-08-08 11:57:05 +1000887 keyboard = zalloc(sizeof *keyboard);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400888 if (keyboard == NULL)
Neil Roberts96d790e2013-09-19 17:32:00 +0100889 return NULL;
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400890
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400891 wl_list_init(&keyboard->resource_list);
Neil Roberts96d790e2013-09-19 17:32:00 +0100892 wl_list_init(&keyboard->focus_resource_list);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100893 wl_list_init(&keyboard->focus_resource_listener.link);
894 keyboard->focus_resource_listener.notify = keyboard_focus_resource_destroyed;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400895 wl_array_init(&keyboard->keys);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400896 keyboard->default_grab.interface = &default_keyboard_grab_interface;
897 keyboard->default_grab.keyboard = keyboard;
898 keyboard->grab = &keyboard->default_grab;
899 wl_signal_init(&keyboard->focus_signal);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400900
901 return keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400902}
903
Jonas Ådahl7395ea02013-12-03 09:14:26 +0100904static void
905weston_xkb_info_destroy(struct weston_xkb_info *xkb_info);
906
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400907WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400908weston_keyboard_destroy(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400909{
910 /* XXX: What about keyboard->resource_list? */
Neil Roberts96d790e2013-09-19 17:32:00 +0100911
Jonas Ådahl7395ea02013-12-03 09:14:26 +0100912#ifdef ENABLE_XKBCOMMON
913 if (keyboard->seat->compositor->use_xkbcommon) {
Ran Benitac9c74152014-08-19 23:59:52 +0300914 xkb_state_unref(keyboard->xkb_state.state);
Jonas Ådahl7395ea02013-12-03 09:14:26 +0100915 if (keyboard->xkb_info)
916 weston_xkb_info_destroy(keyboard->xkb_info);
Ran Benitac9c74152014-08-19 23:59:52 +0300917 xkb_keymap_unref(keyboard->pending_keymap);
Jonas Ådahl7395ea02013-12-03 09:14:26 +0100918 }
919#endif
920
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400921 wl_array_release(&keyboard->keys);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100922 wl_list_remove(&keyboard->focus_resource_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400923 free(keyboard);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400924}
925
Jonas Ådahlcbfa7f72013-12-02 22:05:04 +0100926static void
927weston_touch_reset_state(struct weston_touch *touch)
928{
929 touch->num_tp = 0;
930}
931
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400932WL_EXPORT struct weston_touch *
933weston_touch_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400934{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400935 struct weston_touch *touch;
936
Peter Huttererf3d62272013-08-08 11:57:05 +1000937 touch = zalloc(sizeof *touch);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400938 if (touch == NULL)
939 return NULL;
940
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400941 wl_list_init(&touch->resource_list);
Neil Roberts96d790e2013-09-19 17:32:00 +0100942 wl_list_init(&touch->focus_resource_list);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100943 wl_list_init(&touch->focus_view_listener.link);
944 touch->focus_view_listener.notify = touch_focus_view_destroyed;
945 wl_list_init(&touch->focus_resource_listener.link);
946 touch->focus_resource_listener.notify = touch_focus_resource_destroyed;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400947 touch->default_grab.interface = &default_touch_grab_interface;
948 touch->default_grab.touch = touch;
949 touch->grab = &touch->default_grab;
950 wl_signal_init(&touch->focus_signal);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400951
952 return touch;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400953}
954
955WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400956weston_touch_destroy(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400957{
958 /* XXX: What about touch->resource_list? */
Neil Roberts96d790e2013-09-19 17:32:00 +0100959
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100960 wl_list_remove(&touch->focus_view_listener.link);
961 wl_list_remove(&touch->focus_resource_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400962 free(touch);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400963}
964
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400965static void
Kristian Høgsberge3148752013-05-06 23:19:49 -0400966seat_send_updated_caps(struct weston_seat *seat)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400967{
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400968 enum wl_seat_capability caps = 0;
Rob Bradford6e737f52013-09-06 17:48:19 +0100969 struct wl_resource *resource;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400970
Jonas Ådahld6e1c342013-10-17 23:04:05 +0200971 if (seat->pointer_device_count > 0)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400972 caps |= WL_SEAT_CAPABILITY_POINTER;
Jonas Ådahld6e1c342013-10-17 23:04:05 +0200973 if (seat->keyboard_device_count > 0)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400974 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
Jonas Ådahld6e1c342013-10-17 23:04:05 +0200975 if (seat->touch_device_count > 0)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400976 caps |= WL_SEAT_CAPABILITY_TOUCH;
977
Rob Bradford6e737f52013-09-06 17:48:19 +0100978 wl_resource_for_each(resource, &seat->base_resource_list) {
979 wl_seat_send_capabilities(resource, caps);
Jason Ekstrand44a38632013-06-14 10:08:00 -0500980 }
Jason Ekstranda4ab5422014-04-02 19:53:45 -0500981 wl_signal_emit(&seat->updated_caps_signal, seat);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400982}
983
Derek Foremanf9318d12015-05-11 15:40:11 -0500984
985/** Clear the pointer focus
986 *
987 * \param pointer the pointer to clear focus for.
988 *
989 * This can be used to unset pointer focus and set the co-ordinates to the
990 * arbitrary values we use for the no focus case.
991 *
992 * There's no requirement to use this function. For example, passing the
993 * results of a weston_compositor_pick_view() directly to
994 * weston_pointer_set_focus() will do the right thing when no view is found.
995 */
996WL_EXPORT void
997weston_pointer_clear_focus(struct weston_pointer *pointer)
998{
999 weston_pointer_set_focus(pointer, NULL,
1000 wl_fixed_from_int(-1000000),
1001 wl_fixed_from_int(-1000000));
1002}
1003
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001004WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001005weston_pointer_set_focus(struct weston_pointer *pointer,
Jason Ekstranda7af7042013-10-12 22:38:11 -05001006 struct weston_view *view,
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001007 wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001008{
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001009 struct weston_pointer_client *pointer_client;
Derek Foreman1281a362015-07-31 16:55:32 -05001010 struct weston_keyboard *kbd = weston_seat_get_keyboard(pointer->seat);
Neil Roberts96d790e2013-09-19 17:32:00 +01001011 struct wl_resource *resource;
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001012 struct wl_resource *surface_resource;
Rob Bradford880ebc72013-07-22 17:31:38 +01001013 struct wl_display *display = pointer->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001014 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +01001015 struct wl_list *focus_resource_list;
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -08001016 int refocus = 0;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001017
1018 if ((!pointer->focus && view) ||
1019 (pointer->focus && !view) ||
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -08001020 (pointer->focus && pointer->focus->surface != view->surface) ||
1021 pointer->sx != sx || pointer->sy != sy)
1022 refocus = 1;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001023
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001024 if (pointer->focus_client && refocus) {
1025 focus_resource_list = &pointer->focus_client->pointer_resources;
1026 if (!wl_list_empty(focus_resource_list)) {
1027 serial = wl_display_next_serial(display);
1028 surface_resource = pointer->focus->surface->resource;
1029 wl_resource_for_each(resource, focus_resource_list) {
1030 wl_pointer_send_leave(resource, serial,
1031 surface_resource);
Peter Hutterer87743e92016-01-18 16:38:22 +10001032 pointer_send_frame(resource);
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001033 }
Neil Roberts96d790e2013-09-19 17:32:00 +01001034 }
1035
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001036 pointer->focus_client = NULL;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001037 }
1038
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001039 pointer_client = find_pointer_client_for_view(pointer, view);
1040 if (pointer_client && refocus) {
1041 struct wl_client *surface_client = pointer_client->client;
Neil Roberts96d790e2013-09-19 17:32:00 +01001042
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001043 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +01001044
Jason Ekstranda7af7042013-10-12 22:38:11 -05001045 if (kbd && kbd->focus != view->surface)
Kristian Høgsbergcb406f12013-10-09 10:54:03 -07001046 send_modifiers_to_client_in_list(surface_client,
1047 &kbd->resource_list,
1048 serial,
1049 kbd);
1050
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001051 pointer->focus_client = pointer_client;
Neil Roberts96d790e2013-09-19 17:32:00 +01001052
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001053 focus_resource_list = &pointer->focus_client->pointer_resources;
Neil Roberts96d790e2013-09-19 17:32:00 +01001054 wl_resource_for_each(resource, focus_resource_list) {
1055 wl_pointer_send_enter(resource,
1056 serial,
Jason Ekstranda7af7042013-10-12 22:38:11 -05001057 view->surface->resource,
Neil Roberts96d790e2013-09-19 17:32:00 +01001058 sx, sy);
Peter Hutterer87743e92016-01-18 16:38:22 +10001059 pointer_send_frame(resource);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001060 }
Neil Roberts96d790e2013-09-19 17:32:00 +01001061
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001062 pointer->focus_serial = serial;
1063 }
1064
Giulio Camuffo65a07f82013-12-06 12:46:27 +01001065 wl_list_remove(&pointer->focus_view_listener.link);
1066 wl_list_init(&pointer->focus_view_listener.link);
1067 wl_list_remove(&pointer->focus_resource_listener.link);
1068 wl_list_init(&pointer->focus_resource_listener.link);
Emilio Pozuelo Monfortaa7a4762013-11-19 11:37:15 +01001069 if (view)
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001070 wl_signal_add(&view->destroy_signal, &pointer->focus_view_listener);
Giulio Camuffo65a07f82013-12-06 12:46:27 +01001071 if (view && view->surface->resource)
1072 wl_resource_add_destroy_listener(view->surface->resource,
1073 &pointer->focus_resource_listener);
1074
1075 pointer->focus = view;
1076 pointer->focus_view_listener.notify = pointer_focus_view_destroyed;
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -08001077 pointer->sx = sx;
1078 pointer->sy = sy;
1079
Derek Foremanf9318d12015-05-11 15:40:11 -05001080 assert(view || sx == wl_fixed_from_int(-1000000));
1081 assert(view || sy == wl_fixed_from_int(-1000000));
1082
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001083 wl_signal_emit(&pointer->focus_signal, pointer);
1084}
1085
Neil Roberts96d790e2013-09-19 17:32:00 +01001086static void
1087send_enter_to_resource_list(struct wl_list *list,
1088 struct weston_keyboard *keyboard,
1089 struct weston_surface *surface,
1090 uint32_t serial)
1091{
1092 struct wl_resource *resource;
1093
1094 wl_resource_for_each(resource, list) {
1095 send_modifiers_to_resource(keyboard, resource, serial);
1096 wl_keyboard_send_enter(resource, serial,
1097 surface->resource,
1098 &keyboard->keys);
1099 }
1100}
1101
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001102WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -04001103weston_keyboard_set_focus(struct weston_keyboard *keyboard,
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -04001104 struct weston_surface *surface)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001105{
1106 struct wl_resource *resource;
Rob Bradford880ebc72013-07-22 17:31:38 +01001107 struct wl_display *display = keyboard->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001108 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +01001109 struct wl_list *focus_resource_list;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001110
Neil Roberts96d790e2013-09-19 17:32:00 +01001111 focus_resource_list = &keyboard->focus_resource_list;
1112
1113 if (!wl_list_empty(focus_resource_list) && keyboard->focus != surface) {
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001114 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +01001115 wl_resource_for_each(resource, focus_resource_list) {
1116 wl_keyboard_send_leave(resource, serial,
1117 keyboard->focus->resource);
1118 }
1119 move_resources(&keyboard->resource_list, focus_resource_list);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001120 }
1121
Neil Roberts96d790e2013-09-19 17:32:00 +01001122 if (find_resource_for_surface(&keyboard->resource_list, surface) &&
1123 keyboard->focus != surface) {
1124 struct wl_client *surface_client =
1125 wl_resource_get_client(surface->resource);
1126
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001127 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +01001128
1129 move_resources_for_client(focus_resource_list,
1130 &keyboard->resource_list,
1131 surface_client);
1132 send_enter_to_resource_list(focus_resource_list,
1133 keyboard,
1134 surface,
1135 serial);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001136 keyboard->focus_serial = serial;
Giulio Camuffo65a07f82013-12-06 12:46:27 +01001137 }
1138
1139 wl_list_remove(&keyboard->focus_resource_listener.link);
1140 wl_list_init(&keyboard->focus_resource_listener.link);
1141 if (surface && surface->resource)
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001142 wl_resource_add_destroy_listener(surface->resource,
1143 &keyboard->focus_resource_listener);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001144
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001145 keyboard->focus = surface;
1146 wl_signal_emit(&keyboard->focus_signal, keyboard);
1147}
1148
Giulio Camuffoa20ca812014-11-22 11:16:56 +02001149/* Users of this function must manually manage the keyboard focus */
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001150WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -04001151weston_keyboard_start_grab(struct weston_keyboard *keyboard,
1152 struct weston_keyboard_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001153{
1154 keyboard->grab = grab;
1155 grab->keyboard = keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001156}
1157
1158WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -04001159weston_keyboard_end_grab(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001160{
1161 keyboard->grab = &keyboard->default_grab;
1162}
1163
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02001164static void
1165weston_keyboard_cancel_grab(struct weston_keyboard *keyboard)
1166{
1167 keyboard->grab->interface->cancel(keyboard->grab);
1168}
1169
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001170WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001171weston_pointer_start_grab(struct weston_pointer *pointer,
1172 struct weston_pointer_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001173{
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001174 pointer->grab = grab;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001175 grab->pointer = pointer;
Kristian Høgsbergda751b82013-07-04 00:58:07 -04001176 pointer->grab->interface->focus(pointer->grab);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001177}
1178
1179WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001180weston_pointer_end_grab(struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001181{
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001182 pointer->grab = &pointer->default_grab;
Kristian Høgsbergda751b82013-07-04 00:58:07 -04001183 pointer->grab->interface->focus(pointer->grab);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001184}
1185
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02001186static void
1187weston_pointer_cancel_grab(struct weston_pointer *pointer)
1188{
1189 pointer->grab->interface->cancel(pointer->grab);
1190}
1191
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001192WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -04001193weston_touch_start_grab(struct weston_touch *touch, struct weston_touch_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001194{
1195 touch->grab = grab;
1196 grab->touch = touch;
1197}
1198
1199WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -04001200weston_touch_end_grab(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001201{
1202 touch->grab = &touch->default_grab;
1203}
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001204
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02001205static void
1206weston_touch_cancel_grab(struct weston_touch *touch)
1207{
1208 touch->grab->interface->cancel(touch->grab);
1209}
1210
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001211static void
1212weston_pointer_clamp_for_output(struct weston_pointer *pointer,
1213 struct weston_output *output,
1214 wl_fixed_t *fx, wl_fixed_t *fy)
1215{
1216 int x, y;
1217
1218 x = wl_fixed_to_int(*fx);
1219 y = wl_fixed_to_int(*fy);
1220
1221 if (x < output->x)
1222 *fx = wl_fixed_from_int(output->x);
1223 else if (x >= output->x + output->width)
1224 *fx = wl_fixed_from_int(output->x +
1225 output->width - 1);
1226 if (y < output->y)
1227 *fy = wl_fixed_from_int(output->y);
1228 else if (y >= output->y + output->height)
1229 *fy = wl_fixed_from_int(output->y +
1230 output->height - 1);
1231}
1232
Rob Bradford806d8c02013-06-25 18:56:41 +01001233WL_EXPORT void
1234weston_pointer_clamp(struct weston_pointer *pointer, wl_fixed_t *fx, wl_fixed_t *fy)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001235{
Rob Bradford806d8c02013-06-25 18:56:41 +01001236 struct weston_compositor *ec = pointer->seat->compositor;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001237 struct weston_output *output, *prev = NULL;
1238 int x, y, old_x, old_y, valid = 0;
1239
1240 x = wl_fixed_to_int(*fx);
1241 y = wl_fixed_to_int(*fy);
Rob Bradford806d8c02013-06-25 18:56:41 +01001242 old_x = wl_fixed_to_int(pointer->x);
1243 old_y = wl_fixed_to_int(pointer->y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001244
1245 wl_list_for_each(output, &ec->output_list, link) {
Rob Bradford66bd9f52013-06-25 18:56:42 +01001246 if (pointer->seat->output && pointer->seat->output != output)
1247 continue;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001248 if (pixman_region32_contains_point(&output->region,
1249 x, y, NULL))
1250 valid = 1;
1251 if (pixman_region32_contains_point(&output->region,
1252 old_x, old_y, NULL))
1253 prev = output;
1254 }
1255
Rob Bradford66bd9f52013-06-25 18:56:42 +01001256 if (!prev)
1257 prev = pointer->seat->output;
1258
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001259 if (prev && !valid)
1260 weston_pointer_clamp_for_output(pointer, prev, fx, fy);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001261}
1262
Jonas Ådahld2510102014-10-05 21:39:14 +02001263static void
1264weston_pointer_move_to(struct weston_pointer *pointer,
1265 wl_fixed_t x, wl_fixed_t y)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001266{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001267 int32_t ix, iy;
1268
Rob Bradford806d8c02013-06-25 18:56:41 +01001269 weston_pointer_clamp (pointer, &x, &y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001270
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001271 pointer->x = x;
1272 pointer->y = y;
1273
1274 ix = wl_fixed_to_int(x);
1275 iy = wl_fixed_to_int(y);
1276
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001277 if (pointer->sprite) {
Jason Ekstranda7af7042013-10-12 22:38:11 -05001278 weston_view_set_position(pointer->sprite,
1279 ix - pointer->hotspot_x,
1280 iy - pointer->hotspot_y);
1281 weston_view_schedule_repaint(pointer->sprite);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001282 }
Giulio Camuffo6fcb3782013-11-14 23:42:50 +01001283
Giulio Camuffo1959ab82013-11-14 23:42:52 +01001284 pointer->grab->interface->focus(pointer->grab);
Giulio Camuffo6fcb3782013-11-14 23:42:50 +01001285 wl_signal_emit(&pointer->motion_signal, pointer);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001286}
1287
Jonas Ådahld2510102014-10-05 21:39:14 +02001288WL_EXPORT void
Jonas Ådahld2510102014-10-05 21:39:14 +02001289weston_pointer_move(struct weston_pointer *pointer,
1290 struct weston_pointer_motion_event *event)
1291{
1292 wl_fixed_t x, y;
1293
1294 weston_pointer_motion_to_abs(pointer, event, &x, &y);
1295 weston_pointer_move_to(pointer, x, y);
1296}
1297
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001298/** Verify if the pointer is in a valid position and move it if it isn't.
1299 */
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001300static void
1301weston_pointer_handle_output_destroy(struct wl_listener *listener, void *data)
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001302{
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001303 struct weston_pointer *pointer;
1304 struct weston_compositor *ec;
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001305 struct weston_output *output, *closest = NULL;
1306 int x, y, distance, min = INT_MAX;
1307 wl_fixed_t fx, fy;
1308
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001309 pointer = container_of(listener, struct weston_pointer,
1310 output_destroy_listener);
1311 ec = pointer->seat->compositor;
1312
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001313 x = wl_fixed_to_int(pointer->x);
1314 y = wl_fixed_to_int(pointer->y);
1315
1316 wl_list_for_each(output, &ec->output_list, link) {
1317 if (pixman_region32_contains_point(&output->region,
1318 x, y, NULL))
1319 return;
1320
1321 /* Aproximante the distance from the pointer to the center of
1322 * the output. */
1323 distance = abs(output->x + output->width / 2 - x) +
1324 abs(output->y + output->height / 2 - y);
1325 if (distance < min) {
1326 min = distance;
1327 closest = output;
1328 }
1329 }
1330
1331 /* Nothing to do if there's no output left. */
1332 if (!closest)
1333 return;
1334
1335 fx = pointer->x;
1336 fy = pointer->y;
1337
1338 weston_pointer_clamp_for_output(pointer, closest, &fx, &fy);
Jonas Ådahld2510102014-10-05 21:39:14 +02001339 weston_pointer_move_to(pointer, fx, fy);
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001340}
1341
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001342WL_EXPORT void
1343notify_motion(struct weston_seat *seat,
Jonas Ådahld2510102014-10-05 21:39:14 +02001344 uint32_t time,
1345 struct weston_pointer_motion_event *event)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001346{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001347 struct weston_compositor *ec = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001348 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001349
1350 weston_compositor_wake(ec);
Jonas Ådahld2510102014-10-05 21:39:14 +02001351 pointer->grab->interface->motion(pointer->grab, time, event);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001352}
1353
Daniel Stone96d47c02013-11-19 11:37:12 +01001354static void
1355run_modifier_bindings(struct weston_seat *seat, uint32_t old, uint32_t new)
1356{
1357 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001358 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Daniel Stone96d47c02013-11-19 11:37:12 +01001359 uint32_t diff;
1360 unsigned int i;
1361 struct {
1362 uint32_t xkb;
1363 enum weston_keyboard_modifier weston;
1364 } mods[] = {
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001365 { keyboard->xkb_info->ctrl_mod, MODIFIER_CTRL },
1366 { keyboard->xkb_info->alt_mod, MODIFIER_ALT },
1367 { keyboard->xkb_info->super_mod, MODIFIER_SUPER },
1368 { keyboard->xkb_info->shift_mod, MODIFIER_SHIFT },
Daniel Stone96d47c02013-11-19 11:37:12 +01001369 };
1370
1371 diff = new & ~old;
1372 for (i = 0; i < ARRAY_LENGTH(mods); i++) {
1373 if (diff & (1 << mods[i].xkb))
1374 weston_compositor_run_modifier_binding(compositor,
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001375 keyboard,
Daniel Stone96d47c02013-11-19 11:37:12 +01001376 mods[i].weston,
1377 WL_KEYBOARD_KEY_STATE_PRESSED);
1378 }
1379
1380 diff = old & ~new;
1381 for (i = 0; i < ARRAY_LENGTH(mods); i++) {
1382 if (diff & (1 << mods[i].xkb))
1383 weston_compositor_run_modifier_binding(compositor,
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001384 keyboard,
Daniel Stone96d47c02013-11-19 11:37:12 +01001385 mods[i].weston,
1386 WL_KEYBOARD_KEY_STATE_RELEASED);
1387 }
1388}
1389
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001390WL_EXPORT void
1391notify_motion_absolute(struct weston_seat *seat,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001392 uint32_t time, double x, double y)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001393{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001394 struct weston_compositor *ec = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001395 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Jonas Ådahld2510102014-10-05 21:39:14 +02001396 struct weston_pointer_motion_event event = { 0 };
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001397
1398 weston_compositor_wake(ec);
Jonas Ådahld2510102014-10-05 21:39:14 +02001399
1400 event = (struct weston_pointer_motion_event) {
1401 .mask = WESTON_POINTER_MOTION_ABS,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001402 .x = x,
1403 .y = y,
Jonas Ådahld2510102014-10-05 21:39:14 +02001404 };
1405
1406 pointer->grab->interface->motion(pointer->grab, time, &event);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001407}
1408
Jonas Ådahl94e2e2d2014-10-18 18:42:19 +02001409static unsigned int
1410peek_next_activate_serial(struct weston_compositor *c)
1411{
1412 unsigned serial = c->activate_serial + 1;
1413
1414 return serial == 0 ? 1 : serial;
1415}
1416
1417static void
1418inc_activate_serial(struct weston_compositor *c)
1419{
1420 c->activate_serial = peek_next_activate_serial (c);
1421}
1422
1423WL_EXPORT void
1424weston_view_activate(struct weston_view *view,
1425 struct weston_seat *seat,
1426 uint32_t flags)
1427{
1428 struct weston_compositor *compositor = seat->compositor;
1429
1430 if (flags & WESTON_ACTIVATE_FLAG_CLICKED) {
1431 view->click_to_activate_serial =
1432 peek_next_activate_serial(compositor);
1433 }
1434
1435 weston_seat_set_keyboard_focus(seat, view->surface);
1436}
1437
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001438WL_EXPORT void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001439notify_button(struct weston_seat *seat, uint32_t time, int32_t button,
1440 enum wl_pointer_button_state state)
1441{
1442 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001443 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001444
1445 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001446 weston_compositor_idle_inhibit(compositor);
1447 if (pointer->button_count == 0) {
1448 pointer->grab_button = button;
1449 pointer->grab_time = time;
1450 pointer->grab_x = pointer->x;
1451 pointer->grab_y = pointer->y;
1452 }
1453 pointer->button_count++;
1454 } else {
1455 weston_compositor_idle_release(compositor);
1456 pointer->button_count--;
1457 }
1458
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001459 weston_compositor_run_button_binding(compositor, pointer, time, button,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001460 state);
1461
1462 pointer->grab->interface->button(pointer->grab, time, button, state);
1463
1464 if (pointer->button_count == 1)
1465 pointer->grab_serial =
1466 wl_display_get_serial(compositor->wl_display);
1467}
1468
1469WL_EXPORT void
Peter Hutterer89b6a492016-01-18 15:58:17 +10001470notify_axis(struct weston_seat *seat, uint32_t time,
1471 struct weston_pointer_axis_event *event)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001472{
1473 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001474 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001475
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001476 weston_compositor_wake(compositor);
1477
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001478 if (weston_compositor_run_axis_binding(compositor, pointer,
Peter Hutterer89b6a492016-01-18 15:58:17 +10001479 time, event))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001480 return;
1481
Peter Hutterer89b6a492016-01-18 15:58:17 +10001482 pointer->grab->interface->axis(pointer->grab, time, event);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001483}
1484
Peter Hutterer87743e92016-01-18 16:38:22 +10001485WL_EXPORT void
1486notify_axis_source(struct weston_seat *seat, uint32_t source)
1487{
1488 struct weston_compositor *compositor = seat->compositor;
1489 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1490
1491 weston_compositor_wake(compositor);
1492
1493 pointer->grab->interface->axis_source(pointer->grab, source);
1494}
1495
1496WL_EXPORT void
1497notify_pointer_frame(struct weston_seat *seat)
1498{
1499 struct weston_compositor *compositor = seat->compositor;
1500 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1501
1502 weston_compositor_wake(compositor);
1503
1504 pointer->grab->interface->frame(pointer->grab);
1505}
1506
Giulio Camuffo6ef444d2014-08-28 19:44:09 +03001507WL_EXPORT int
1508weston_keyboard_set_locks(struct weston_keyboard *keyboard,
1509 uint32_t mask, uint32_t value)
1510{
1511#ifdef ENABLE_XKBCOMMON
1512 uint32_t serial;
1513 xkb_mod_mask_t mods_depressed, mods_latched, mods_locked, group;
1514 xkb_mod_mask_t num, caps;
1515
1516 /* We don't want the leds to go out of sync with the actual state
1517 * so if the backend has no way to change the leds don't try to
1518 * change the state */
1519 if (!keyboard->seat->led_update)
1520 return -1;
1521
1522 mods_depressed = xkb_state_serialize_mods(keyboard->xkb_state.state,
1523 XKB_STATE_DEPRESSED);
1524 mods_latched = xkb_state_serialize_mods(keyboard->xkb_state.state,
1525 XKB_STATE_LATCHED);
1526 mods_locked = xkb_state_serialize_mods(keyboard->xkb_state.state,
1527 XKB_STATE_LOCKED);
1528 group = xkb_state_serialize_group(keyboard->xkb_state.state,
1529 XKB_STATE_EFFECTIVE);
1530
1531 num = (1 << keyboard->xkb_info->mod2_mod);
1532 caps = (1 << keyboard->xkb_info->caps_mod);
1533 if (mask & WESTON_NUM_LOCK) {
1534 if (value & WESTON_NUM_LOCK)
1535 mods_locked |= num;
1536 else
1537 mods_locked &= ~num;
1538 }
1539 if (mask & WESTON_CAPS_LOCK) {
1540 if (value & WESTON_CAPS_LOCK)
1541 mods_locked |= caps;
1542 else
1543 mods_locked &= ~caps;
1544 }
1545
1546 xkb_state_update_mask(keyboard->xkb_state.state, mods_depressed,
1547 mods_latched, mods_locked, 0, 0, group);
1548
1549 serial = wl_display_next_serial(
1550 keyboard->seat->compositor->wl_display);
1551 notify_modifiers(keyboard->seat, serial);
1552
1553 return 0;
1554#else
1555 return -1;
1556#endif
1557}
1558
Rob Bradford382ff462013-06-24 16:52:45 +01001559#ifdef ENABLE_XKBCOMMON
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001560WL_EXPORT void
1561notify_modifiers(struct weston_seat *seat, uint32_t serial)
1562{
Derek Foreman1281a362015-07-31 16:55:32 -05001563 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001564 struct weston_keyboard_grab *grab = keyboard->grab;
1565 uint32_t mods_depressed, mods_latched, mods_locked, group;
1566 uint32_t mods_lookup;
1567 enum weston_led leds = 0;
1568 int changed = 0;
1569
1570 /* Serialize and update our internal state, checking to see if it's
1571 * different to the previous state. */
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001572 mods_depressed = xkb_state_serialize_mods(keyboard->xkb_state.state,
Ran Benita2e1968f2014-08-19 23:59:51 +03001573 XKB_STATE_MODS_DEPRESSED);
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001574 mods_latched = xkb_state_serialize_mods(keyboard->xkb_state.state,
Ran Benita2e1968f2014-08-19 23:59:51 +03001575 XKB_STATE_MODS_LATCHED);
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001576 mods_locked = xkb_state_serialize_mods(keyboard->xkb_state.state,
Ran Benita2e1968f2014-08-19 23:59:51 +03001577 XKB_STATE_MODS_LOCKED);
1578 group = xkb_state_serialize_layout(keyboard->xkb_state.state,
1579 XKB_STATE_LAYOUT_EFFECTIVE);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001580
Derek Foreman244e99e2015-06-03 15:53:26 -05001581 if (mods_depressed != keyboard->modifiers.mods_depressed ||
1582 mods_latched != keyboard->modifiers.mods_latched ||
1583 mods_locked != keyboard->modifiers.mods_locked ||
1584 group != keyboard->modifiers.group)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001585 changed = 1;
1586
Derek Foreman244e99e2015-06-03 15:53:26 -05001587 run_modifier_bindings(seat, keyboard->modifiers.mods_depressed,
Daniel Stone96d47c02013-11-19 11:37:12 +01001588 mods_depressed);
1589
Derek Foreman244e99e2015-06-03 15:53:26 -05001590 keyboard->modifiers.mods_depressed = mods_depressed;
1591 keyboard->modifiers.mods_latched = mods_latched;
1592 keyboard->modifiers.mods_locked = mods_locked;
1593 keyboard->modifiers.group = group;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001594
1595 /* And update the modifier_state for bindings. */
1596 mods_lookup = mods_depressed | mods_latched;
1597 seat->modifier_state = 0;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001598 if (mods_lookup & (1 << keyboard->xkb_info->ctrl_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001599 seat->modifier_state |= MODIFIER_CTRL;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001600 if (mods_lookup & (1 << keyboard->xkb_info->alt_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001601 seat->modifier_state |= MODIFIER_ALT;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001602 if (mods_lookup & (1 << keyboard->xkb_info->super_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001603 seat->modifier_state |= MODIFIER_SUPER;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001604 if (mods_lookup & (1 << keyboard->xkb_info->shift_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001605 seat->modifier_state |= MODIFIER_SHIFT;
1606
1607 /* Finally, notify the compositor that LEDs have changed. */
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001608 if (xkb_state_led_index_is_active(keyboard->xkb_state.state,
1609 keyboard->xkb_info->num_led))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001610 leds |= LED_NUM_LOCK;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001611 if (xkb_state_led_index_is_active(keyboard->xkb_state.state,
1612 keyboard->xkb_info->caps_led))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001613 leds |= LED_CAPS_LOCK;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001614 if (xkb_state_led_index_is_active(keyboard->xkb_state.state,
1615 keyboard->xkb_info->scroll_led))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001616 leds |= LED_SCROLL_LOCK;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001617 if (leds != keyboard->xkb_state.leds && seat->led_update)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001618 seat->led_update(seat, leds);
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001619 keyboard->xkb_state.leds = leds;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001620
1621 if (changed) {
1622 grab->interface->modifiers(grab,
1623 serial,
1624 keyboard->modifiers.mods_depressed,
1625 keyboard->modifiers.mods_latched,
1626 keyboard->modifiers.mods_locked,
1627 keyboard->modifiers.group);
1628 }
1629}
1630
1631static void
1632update_modifier_state(struct weston_seat *seat, uint32_t serial, uint32_t key,
1633 enum wl_keyboard_key_state state)
1634{
Derek Foreman1281a362015-07-31 16:55:32 -05001635 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001636 enum xkb_key_direction direction;
1637
Matt Roper01a92732013-06-24 16:52:44 +01001638 /* Keyboard modifiers don't exist in raw keyboard mode */
1639 if (!seat->compositor->use_xkbcommon)
1640 return;
1641
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001642 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
1643 direction = XKB_KEY_DOWN;
1644 else
1645 direction = XKB_KEY_UP;
1646
1647 /* Offset the keycode by 8, as the evdev XKB rules reflect X's
1648 * broken keycode system, which starts at 8. */
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001649 xkb_state_update_key(keyboard->xkb_state.state, key + 8, direction);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001650
1651 notify_modifiers(seat, serial);
1652}
Rui Matos65196bc2013-10-10 19:44:19 +02001653
1654static void
1655send_keymap(struct wl_resource *resource, struct weston_xkb_info *xkb_info)
1656{
1657 wl_keyboard_send_keymap(resource,
1658 WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
1659 xkb_info->keymap_fd,
1660 xkb_info->keymap_size);
1661}
1662
1663static void
1664send_modifiers(struct wl_resource *resource, uint32_t serial, struct weston_keyboard *keyboard)
1665{
1666 wl_keyboard_send_modifiers(resource, serial,
1667 keyboard->modifiers.mods_depressed,
1668 keyboard->modifiers.mods_latched,
1669 keyboard->modifiers.mods_locked,
1670 keyboard->modifiers.group);
1671}
1672
1673static struct weston_xkb_info *
1674weston_xkb_info_create(struct xkb_keymap *keymap);
Rui Matos65196bc2013-10-10 19:44:19 +02001675
1676static void
1677update_keymap(struct weston_seat *seat)
1678{
Derek Foreman1281a362015-07-31 16:55:32 -05001679 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Rui Matos65196bc2013-10-10 19:44:19 +02001680 struct wl_resource *resource;
1681 struct weston_xkb_info *xkb_info;
1682 struct xkb_state *state;
1683 xkb_mod_mask_t latched_mods;
1684 xkb_mod_mask_t locked_mods;
1685
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001686 xkb_info = weston_xkb_info_create(keyboard->pending_keymap);
Rui Matos65196bc2013-10-10 19:44:19 +02001687
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001688 xkb_keymap_unref(keyboard->pending_keymap);
1689 keyboard->pending_keymap = NULL;
Rui Matos65196bc2013-10-10 19:44:19 +02001690
1691 if (!xkb_info) {
1692 weston_log("failed to create XKB info\n");
1693 return;
1694 }
1695
1696 state = xkb_state_new(xkb_info->keymap);
1697 if (!state) {
1698 weston_log("failed to initialise XKB state\n");
1699 weston_xkb_info_destroy(xkb_info);
1700 return;
1701 }
1702
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001703 latched_mods = xkb_state_serialize_mods(keyboard->xkb_state.state,
1704 XKB_STATE_MODS_LATCHED);
1705 locked_mods = xkb_state_serialize_mods(keyboard->xkb_state.state,
1706 XKB_STATE_MODS_LOCKED);
Rui Matos65196bc2013-10-10 19:44:19 +02001707 xkb_state_update_mask(state,
1708 0, /* depressed */
1709 latched_mods,
1710 locked_mods,
1711 0, 0, 0);
1712
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001713 weston_xkb_info_destroy(keyboard->xkb_info);
1714 keyboard->xkb_info = xkb_info;
Rui Matos65196bc2013-10-10 19:44:19 +02001715
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001716 xkb_state_unref(keyboard->xkb_state.state);
1717 keyboard->xkb_state.state = state;
Rui Matos65196bc2013-10-10 19:44:19 +02001718
Derek Foremanbc91e542015-06-03 15:53:27 -05001719 wl_resource_for_each(resource, &keyboard->resource_list)
Rui Matos65196bc2013-10-10 19:44:19 +02001720 send_keymap(resource, xkb_info);
Derek Foremanbc91e542015-06-03 15:53:27 -05001721 wl_resource_for_each(resource, &keyboard->focus_resource_list)
Rui Matos65196bc2013-10-10 19:44:19 +02001722 send_keymap(resource, xkb_info);
1723
1724 notify_modifiers(seat, wl_display_next_serial(seat->compositor->wl_display));
1725
1726 if (!latched_mods && !locked_mods)
1727 return;
1728
Derek Foremanbc91e542015-06-03 15:53:27 -05001729 wl_resource_for_each(resource, &keyboard->resource_list)
1730 send_modifiers(resource, wl_display_get_serial(seat->compositor->wl_display), keyboard);
1731 wl_resource_for_each(resource, &keyboard->focus_resource_list)
1732 send_modifiers(resource, wl_display_get_serial(seat->compositor->wl_display), keyboard);
Rui Matos65196bc2013-10-10 19:44:19 +02001733}
Rob Bradford382ff462013-06-24 16:52:45 +01001734#else
1735WL_EXPORT void
1736notify_modifiers(struct weston_seat *seat, uint32_t serial)
1737{
1738}
1739
1740static void
1741update_modifier_state(struct weston_seat *seat, uint32_t serial, uint32_t key,
1742 enum wl_keyboard_key_state state)
1743{
1744}
Rui Matos65196bc2013-10-10 19:44:19 +02001745
1746static void
1747update_keymap(struct weston_seat *seat)
1748{
1749}
Rob Bradford382ff462013-06-24 16:52:45 +01001750#endif
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001751
1752WL_EXPORT void
1753notify_key(struct weston_seat *seat, uint32_t time, uint32_t key,
1754 enum wl_keyboard_key_state state,
1755 enum weston_key_state_update update_state)
1756{
1757 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001758 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001759 struct weston_keyboard_grab *grab = keyboard->grab;
Pekka Paalanen86b53962014-11-19 13:43:32 +02001760 uint32_t *k, *end;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001761
1762 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001763 weston_compositor_idle_inhibit(compositor);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001764 } else {
1765 weston_compositor_idle_release(compositor);
1766 }
1767
Pekka Paalanen86b53962014-11-19 13:43:32 +02001768 end = keyboard->keys.data + keyboard->keys.size;
1769 for (k = keyboard->keys.data; k < end; k++) {
1770 if (*k == key) {
1771 /* Ignore server-generated repeats. */
1772 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
1773 return;
1774 *k = *--end;
1775 }
1776 }
1777 keyboard->keys.size = (void *) end - keyboard->keys.data;
1778 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
1779 k = wl_array_add(&keyboard->keys, sizeof *k);
1780 *k = key;
1781 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001782
1783 if (grab == &keyboard->default_grab ||
1784 grab == &keyboard->input_method_grab) {
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001785 weston_compositor_run_key_binding(compositor, keyboard, time,
1786 key, state);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001787 grab = keyboard->grab;
1788 }
1789
1790 grab->interface->key(grab, time, key, state);
1791
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001792 if (keyboard->pending_keymap &&
Pekka Paalanen86b53962014-11-19 13:43:32 +02001793 keyboard->keys.size == 0)
Rui Matos65196bc2013-10-10 19:44:19 +02001794 update_keymap(seat);
1795
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001796 if (update_state == STATE_UPDATE_AUTOMATIC) {
1797 update_modifier_state(seat,
1798 wl_display_get_serial(compositor->wl_display),
1799 key,
1800 state);
1801 }
Giulio Camuffob6ddf6c2015-02-06 19:06:54 +02001802
1803 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
1804 keyboard->grab_serial =
1805 wl_display_get_serial(compositor->wl_display);
1806 keyboard->grab_time = time;
1807 keyboard->grab_key = key;
1808 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001809}
1810
1811WL_EXPORT void
1812notify_pointer_focus(struct weston_seat *seat, struct weston_output *output,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001813 double x, double y)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001814{
Derek Foreman1281a362015-07-31 16:55:32 -05001815 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1816
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001817 if (output) {
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001818 weston_pointer_move_to(pointer,
1819 wl_fixed_from_double(x),
1820 wl_fixed_from_double(y));
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001821 } else {
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001822 /* FIXME: We should call weston_pointer_set_focus(seat,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001823 * NULL) here, but somehow that breaks re-entry... */
1824 }
1825}
1826
1827static void
1828destroy_device_saved_kbd_focus(struct wl_listener *listener, void *data)
1829{
1830 struct weston_seat *ws;
1831
1832 ws = container_of(listener, struct weston_seat,
1833 saved_kbd_focus_listener);
1834
1835 ws->saved_kbd_focus = NULL;
1836}
1837
1838WL_EXPORT void
1839notify_keyboard_focus_in(struct weston_seat *seat, struct wl_array *keys,
1840 enum weston_key_state_update update_state)
1841{
1842 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001843 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -04001844 struct weston_surface *surface;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001845 uint32_t *k, serial;
1846
1847 serial = wl_display_next_serial(compositor->wl_display);
1848 wl_array_copy(&keyboard->keys, keys);
1849 wl_array_for_each(k, &keyboard->keys) {
1850 weston_compositor_idle_inhibit(compositor);
1851 if (update_state == STATE_UPDATE_AUTOMATIC)
1852 update_modifier_state(seat, serial, *k,
1853 WL_KEYBOARD_KEY_STATE_PRESSED);
1854 }
1855
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001856 surface = seat->saved_kbd_focus;
1857
1858 if (surface) {
1859 wl_list_remove(&seat->saved_kbd_focus_listener.link);
1860 weston_keyboard_set_focus(keyboard, surface);
1861 seat->saved_kbd_focus = NULL;
1862 }
1863}
1864
1865WL_EXPORT void
1866notify_keyboard_focus_out(struct weston_seat *seat)
1867{
1868 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001869 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
1870 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001871 uint32_t *k, serial;
1872
1873 serial = wl_display_next_serial(compositor->wl_display);
1874 wl_array_for_each(k, &keyboard->keys) {
1875 weston_compositor_idle_release(compositor);
1876 update_modifier_state(seat, serial, *k,
1877 WL_KEYBOARD_KEY_STATE_RELEASED);
1878 }
1879
1880 seat->modifier_state = 0;
1881
1882 if (keyboard->focus) {
1883 seat->saved_kbd_focus = keyboard->focus;
1884 seat->saved_kbd_focus_listener.notify =
1885 destroy_device_saved_kbd_focus;
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05001886 wl_signal_add(&keyboard->focus->destroy_signal,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001887 &seat->saved_kbd_focus_listener);
1888 }
1889
1890 weston_keyboard_set_focus(keyboard, NULL);
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02001891 weston_keyboard_cancel_grab(keyboard);
Derek Foreman1281a362015-07-31 16:55:32 -05001892 if (pointer)
1893 weston_pointer_cancel_grab(pointer);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001894}
1895
Michael Fua2bb7912013-07-23 15:51:06 +08001896WL_EXPORT void
Derek Foreman4c93c082015-04-30 16:45:41 -05001897weston_touch_set_focus(struct weston_touch *touch, struct weston_view *view)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001898{
Neil Roberts96d790e2013-09-19 17:32:00 +01001899 struct wl_list *focus_resource_list;
1900
Derek Foreman4c93c082015-04-30 16:45:41 -05001901 focus_resource_list = &touch->focus_resource_list;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001902
Derek Foreman4c93c082015-04-30 16:45:41 -05001903 if (view && touch->focus &&
1904 touch->focus->surface == view->surface) {
1905 touch->focus = view;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001906 return;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001907 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001908
Derek Foreman4c93c082015-04-30 16:45:41 -05001909 wl_list_remove(&touch->focus_resource_listener.link);
1910 wl_list_init(&touch->focus_resource_listener.link);
1911 wl_list_remove(&touch->focus_view_listener.link);
1912 wl_list_init(&touch->focus_view_listener.link);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001913
Neil Roberts96d790e2013-09-19 17:32:00 +01001914 if (!wl_list_empty(focus_resource_list)) {
Derek Foreman4c93c082015-04-30 16:45:41 -05001915 move_resources(&touch->resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01001916 focus_resource_list);
1917 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001918
Jason Ekstranda7af7042013-10-12 22:38:11 -05001919 if (view) {
Derek Foreman362656b2014-09-04 10:23:05 -05001920 struct wl_client *surface_client;
1921
1922 if (!view->surface->resource) {
Derek Foreman4c93c082015-04-30 16:45:41 -05001923 touch->focus = NULL;
Derek Foreman362656b2014-09-04 10:23:05 -05001924 return;
1925 }
1926
1927 surface_client = wl_resource_get_client(view->surface->resource);
Neil Roberts96d790e2013-09-19 17:32:00 +01001928 move_resources_for_client(focus_resource_list,
Derek Foreman4c93c082015-04-30 16:45:41 -05001929 &touch->resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01001930 surface_client);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001931 wl_resource_add_destroy_listener(view->surface->resource,
Derek Foreman4c93c082015-04-30 16:45:41 -05001932 &touch->focus_resource_listener);
1933 wl_signal_add(&view->destroy_signal, &touch->focus_view_listener);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001934 }
Derek Foreman4c93c082015-04-30 16:45:41 -05001935 touch->focus = view;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001936}
1937
1938/**
1939 * notify_touch - emulates button touches and notifies surfaces accordingly.
1940 *
1941 * It assumes always the correct cycle sequence until it gets here: touch_down
1942 * → touch_update → ... → touch_update → touch_end. The driver is responsible
1943 * for sending along such order.
1944 *
1945 */
1946WL_EXPORT void
1947notify_touch(struct weston_seat *seat, uint32_t time, int touch_id,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001948 double double_x, double double_y, int touch_type)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001949{
1950 struct weston_compositor *ec = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001951 struct weston_touch *touch = weston_seat_get_touch(seat);
Kristian Høgsberge329f362013-05-06 22:19:57 -04001952 struct weston_touch_grab *grab = touch->grab;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001953 struct weston_view *ev;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001954 wl_fixed_t sx, sy;
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001955 wl_fixed_t x = wl_fixed_from_double(double_x);
1956 wl_fixed_t y = wl_fixed_from_double(double_y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001957
1958 /* Update grab's global coordinates. */
Neil Roberts306fe082013-10-03 16:43:06 +01001959 if (touch_id == touch->grab_touch_id && touch_type != WL_TOUCH_UP) {
1960 touch->grab_x = x;
1961 touch->grab_y = y;
1962 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001963
1964 switch (touch_type) {
1965 case WL_TOUCH_DOWN:
1966 weston_compositor_idle_inhibit(ec);
1967
Jonas Ådahl9484b692013-12-02 22:05:03 +01001968 touch->num_tp++;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001969
Jason Ekstranda7af7042013-10-12 22:38:11 -05001970 /* the first finger down picks the view, and all further go
1971 * to that view for the remainder of the touch session i.e.
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001972 * until all touch points are up again. */
Jonas Ådahl9484b692013-12-02 22:05:03 +01001973 if (touch->num_tp == 1) {
Jason Ekstranda7af7042013-10-12 22:38:11 -05001974 ev = weston_compositor_pick_view(ec, x, y, &sx, &sy);
Derek Foreman4c93c082015-04-30 16:45:41 -05001975 weston_touch_set_focus(touch, ev);
Giulio Camuffo61ed7b62015-07-08 11:55:28 +03001976 } else if (!touch->focus) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001977 /* Unexpected condition: We have non-initial touch but
1978 * there is no focused surface.
1979 */
Chris Michael3f607d32015-10-07 11:59:49 -04001980 weston_log("touch event received with %d points down "
Jonas Ådahl9484b692013-12-02 22:05:03 +01001981 "but no surface focused\n", touch->num_tp);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001982 return;
1983 }
1984
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001985 weston_compositor_run_touch_binding(ec, touch,
Kristian Høgsbergc8964012014-02-05 14:25:18 -08001986 time, touch_type);
1987
Giulio Camuffo61ed7b62015-07-08 11:55:28 +03001988 grab->interface->down(grab, time, touch_id, x, y);
Jonas Ådahl9484b692013-12-02 22:05:03 +01001989 if (touch->num_tp == 1) {
Rusty Lynchf1407ff2013-08-08 21:13:57 -07001990 touch->grab_serial =
1991 wl_display_get_serial(ec->wl_display);
Neil Roberts306fe082013-10-03 16:43:06 +01001992 touch->grab_touch_id = touch_id;
Rusty Lynchf1407ff2013-08-08 21:13:57 -07001993 touch->grab_time = time;
1994 touch->grab_x = x;
1995 touch->grab_y = y;
1996 }
1997
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001998 break;
1999 case WL_TOUCH_MOTION:
Jason Ekstranda7af7042013-10-12 22:38:11 -05002000 ev = touch->focus;
2001 if (!ev)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002002 break;
2003
Giulio Camuffo61ed7b62015-07-08 11:55:28 +03002004 grab->interface->motion(grab, time, touch_id, x, y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002005 break;
2006 case WL_TOUCH_UP:
Kristian Høgsberga30e29a2014-01-08 22:29:20 -08002007 if (touch->num_tp == 0) {
2008 /* This can happen if we start out with one or
2009 * more fingers on the touch screen, in which
2010 * case we didn't get the corresponding down
2011 * event. */
2012 weston_log("unmatched touch up event\n");
2013 break;
2014 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002015 weston_compositor_idle_release(ec);
Jonas Ådahl9484b692013-12-02 22:05:03 +01002016 touch->num_tp--;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002017
2018 grab->interface->up(grab, time, touch_id);
Jonas Ådahl9484b692013-12-02 22:05:03 +01002019 if (touch->num_tp == 0)
Derek Foreman4c93c082015-04-30 16:45:41 -05002020 weston_touch_set_focus(touch, NULL);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002021 break;
2022 }
2023}
2024
Jonas Ådahl1679f232014-04-12 09:39:51 +02002025WL_EXPORT void
2026notify_touch_frame(struct weston_seat *seat)
2027{
Derek Foreman1281a362015-07-31 16:55:32 -05002028 struct weston_touch *touch = weston_seat_get_touch(seat);
Jonas Ådahl1679f232014-04-12 09:39:51 +02002029 struct weston_touch_grab *grab = touch->grab;
2030
2031 grab->interface->frame(grab);
2032}
2033
Derek Foreman3cc004a2015-11-06 15:56:09 -06002034WL_EXPORT void
2035notify_touch_cancel(struct weston_seat *seat)
2036{
2037 struct weston_touch *touch = weston_seat_get_touch(seat);
2038 struct weston_touch_grab *grab = touch->grab;
2039
2040 grab->interface->cancel(grab);
2041}
2042
Pekka Paalanen8274d902014-08-06 19:36:51 +03002043static int
2044pointer_cursor_surface_get_label(struct weston_surface *surface,
2045 char *buf, size_t len)
2046{
2047 return snprintf(buf, len, "cursor");
2048}
2049
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002050static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002051pointer_cursor_surface_configure(struct weston_surface *es,
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06002052 int32_t dx, int32_t dy)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002053{
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002054 struct weston_pointer *pointer = es->configure_private;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002055 int x, y;
2056
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06002057 if (es->width == 0)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002058 return;
2059
Jason Ekstranda7af7042013-10-12 22:38:11 -05002060 assert(es == pointer->sprite->surface);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002061
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002062 pointer->hotspot_x -= dx;
2063 pointer->hotspot_y -= dy;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002064
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002065 x = wl_fixed_to_int(pointer->x) - pointer->hotspot_x;
2066 y = wl_fixed_to_int(pointer->y) - pointer->hotspot_y;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002067
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06002068 weston_view_set_position(pointer->sprite, x, y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002069
2070 empty_region(&es->pending.input);
Ander Conselvan de Oliveira23900f72014-01-31 16:07:51 +02002071 empty_region(&es->input);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002072
2073 if (!weston_surface_is_mapped(es)) {
Giulio Camuffo412e6a52014-07-09 22:12:56 +03002074 weston_layer_entry_insert(&es->compositor->cursor_layer.view_list,
2075 &pointer->sprite->layer_link);
Jason Ekstranda7af7042013-10-12 22:38:11 -05002076 weston_view_update_transform(pointer->sprite);
Armin Krezovićf8486c32016-06-30 06:04:28 +02002077 es->is_mapped = true;
2078 pointer->sprite->is_mapped = true;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002079 }
2080}
2081
2082static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002083pointer_set_cursor(struct wl_client *client, struct wl_resource *resource,
2084 uint32_t serial, struct wl_resource *surface_resource,
2085 int32_t x, int32_t y)
2086{
Jason Ekstrand44a38632013-06-14 10:08:00 -05002087 struct weston_pointer *pointer = wl_resource_get_user_data(resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002088 struct weston_surface *surface = NULL;
2089
2090 if (surface_resource)
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05002091 surface = wl_resource_get_user_data(surface_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002092
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002093 if (pointer->focus == NULL)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002094 return;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002095 /* pointer->focus->surface->resource can be NULL. Surfaces like the
Giulio Camuffo1fd4b012013-06-20 18:13:07 +02002096 black_surface used in shell.c for fullscreen don't have
2097 a resource, but can still have focus */
Jason Ekstranda7af7042013-10-12 22:38:11 -05002098 if (pointer->focus->surface->resource == NULL)
Giulio Camuffo1fd4b012013-06-20 18:13:07 +02002099 return;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002100 if (wl_resource_get_client(pointer->focus->surface->resource) != client)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002101 return;
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002102 if (pointer->focus_serial - serial > UINT32_MAX / 2)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002103 return;
2104
Derek Foreman4e53c532015-03-23 10:55:32 -05002105 if (!surface) {
2106 if (pointer->sprite)
2107 pointer_unmap_sprite(pointer);
2108 return;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002109 }
2110
Jonas Ådahlb4070242015-03-18 15:08:03 +08002111 if (pointer->sprite && pointer->sprite->surface == surface &&
2112 pointer->hotspot_x == x && pointer->hotspot_y == y)
2113 return;
2114
Derek Foreman4e53c532015-03-23 10:55:32 -05002115 if (!pointer->sprite || pointer->sprite->surface != surface) {
2116 if (weston_surface_set_role(surface, "wl_pointer-cursor",
2117 resource,
2118 WL_POINTER_ERROR_ROLE) < 0)
2119 return;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002120
Derek Foreman4e53c532015-03-23 10:55:32 -05002121 if (pointer->sprite)
2122 pointer_unmap_sprite(pointer);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002123
Derek Foreman4e53c532015-03-23 10:55:32 -05002124 wl_signal_add(&surface->destroy_signal,
2125 &pointer->sprite_destroy_listener);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002126
Derek Foreman4e53c532015-03-23 10:55:32 -05002127 surface->configure = pointer_cursor_surface_configure;
2128 surface->configure_private = pointer;
2129 weston_surface_set_label_func(surface,
2130 pointer_cursor_surface_get_label);
2131 pointer->sprite = weston_view_create(surface);
2132 }
2133
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002134 pointer->hotspot_x = x;
2135 pointer->hotspot_y = y;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002136
Jonas Ådahl16fe4dc2014-09-08 19:33:41 +02002137 if (surface->buffer_ref.buffer) {
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06002138 pointer_cursor_surface_configure(surface, 0, 0);
Jonas Ådahl16fe4dc2014-09-08 19:33:41 +02002139 weston_view_schedule_repaint(pointer->sprite);
2140 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002141}
2142
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002143static void
2144pointer_release(struct wl_client *client, struct wl_resource *resource)
2145{
2146 wl_resource_destroy(resource);
2147}
2148
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002149static const struct wl_pointer_interface pointer_interface = {
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002150 pointer_set_cursor,
2151 pointer_release
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002152};
2153
2154static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002155seat_get_pointer(struct wl_client *client, struct wl_resource *resource,
2156 uint32_t id)
2157{
Jason Ekstrand44a38632013-06-14 10:08:00 -05002158 struct weston_seat *seat = wl_resource_get_user_data(resource);
Derek Foreman1281a362015-07-31 16:55:32 -05002159 /* We use the pointer_state directly, which means we'll
2160 * give a wl_pointer if the seat has ever had one - even though
2161 * the spec explicitly states that this request only takes effect
2162 * if the seat has the pointer capability.
2163 *
2164 * This prevents a race between the compositor sending new
2165 * capabilities and the client trying to use the old ones.
2166 */
2167 struct weston_pointer *pointer = seat->pointer_state;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002168 struct wl_resource *cr;
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08002169 struct weston_pointer_client *pointer_client;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002170
Derek Foreman1281a362015-07-31 16:55:32 -05002171 if (!pointer)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002172 return;
2173
Jason Ekstranda85118c2013-06-27 20:17:02 -05002174 cr = wl_resource_create(client, &wl_pointer_interface,
2175 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07002176 if (cr == NULL) {
2177 wl_client_post_no_memory(client);
2178 return;
2179 }
2180
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08002181 pointer_client = weston_pointer_ensure_pointer_client(pointer, client);
2182 if (!pointer_client) {
2183 wl_client_post_no_memory(client);
2184 return;
2185 }
2186
2187 wl_list_insert(&pointer_client->pointer_resources,
2188 wl_resource_get_link(cr));
Derek Foreman1281a362015-07-31 16:55:32 -05002189 wl_resource_set_implementation(cr, &pointer_interface, pointer,
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08002190 unbind_pointer_client_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002191
Derek Foreman1281a362015-07-31 16:55:32 -05002192 if (pointer->focus && pointer->focus->surface->resource &&
2193 wl_resource_get_client(pointer->focus->surface->resource) == client) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002194 wl_fixed_t sx, sy;
2195
Derek Foreman1281a362015-07-31 16:55:32 -05002196 weston_view_from_global_fixed(pointer->focus,
2197 pointer->x,
2198 pointer->y,
Jason Ekstranda7af7042013-10-12 22:38:11 -05002199 &sx, &sy);
Neil Roberts96d790e2013-09-19 17:32:00 +01002200
Neil Roberts96d790e2013-09-19 17:32:00 +01002201 wl_pointer_send_enter(cr,
Derek Foreman1281a362015-07-31 16:55:32 -05002202 pointer->focus_serial,
2203 pointer->focus->surface->resource,
Neil Roberts96d790e2013-09-19 17:32:00 +01002204 sx, sy);
Peter Hutterer87743e92016-01-18 16:38:22 +10002205 pointer_send_frame(cr);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002206 }
2207}
2208
2209static void
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002210keyboard_release(struct wl_client *client, struct wl_resource *resource)
2211{
2212 wl_resource_destroy(resource);
2213}
2214
2215static const struct wl_keyboard_interface keyboard_interface = {
2216 keyboard_release
2217};
2218
Derek Foreman280e7dd2014-10-03 13:13:42 -05002219static bool
Neil Roberts96d790e2013-09-19 17:32:00 +01002220should_send_modifiers_to_client(struct weston_seat *seat,
2221 struct wl_client *client)
2222{
Derek Foreman1281a362015-07-31 16:55:32 -05002223 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
2224 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
2225
2226 if (keyboard &&
2227 keyboard->focus &&
2228 keyboard->focus->resource &&
2229 wl_resource_get_client(keyboard->focus->resource) == client)
Derek Foreman280e7dd2014-10-03 13:13:42 -05002230 return true;
Neil Roberts96d790e2013-09-19 17:32:00 +01002231
Derek Foreman1281a362015-07-31 16:55:32 -05002232 if (pointer &&
2233 pointer->focus &&
2234 pointer->focus->surface->resource &&
2235 wl_resource_get_client(pointer->focus->surface->resource) == client)
Derek Foreman280e7dd2014-10-03 13:13:42 -05002236 return true;
Neil Roberts96d790e2013-09-19 17:32:00 +01002237
Derek Foreman280e7dd2014-10-03 13:13:42 -05002238 return false;
Neil Roberts96d790e2013-09-19 17:32:00 +01002239}
2240
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002241static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002242seat_get_keyboard(struct wl_client *client, struct wl_resource *resource,
2243 uint32_t id)
2244{
Jason Ekstrand44a38632013-06-14 10:08:00 -05002245 struct weston_seat *seat = wl_resource_get_user_data(resource);
Derek Foreman1281a362015-07-31 16:55:32 -05002246 /* We use the keyboard_state directly, which means we'll
2247 * give a wl_keyboard if the seat has ever had one - even though
2248 * the spec explicitly states that this request only takes effect
2249 * if the seat has the keyboard capability.
2250 *
2251 * This prevents a race between the compositor sending new
2252 * capabilities and the client trying to use the old ones.
2253 */
2254 struct weston_keyboard *keyboard = seat->keyboard_state;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002255 struct wl_resource *cr;
2256
Derek Foreman345c9f32015-06-03 15:53:28 -05002257 if (!keyboard)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002258 return;
2259
Jason Ekstranda85118c2013-06-27 20:17:02 -05002260 cr = wl_resource_create(client, &wl_keyboard_interface,
2261 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07002262 if (cr == NULL) {
2263 wl_client_post_no_memory(client);
2264 return;
2265 }
2266
Neil Roberts96d790e2013-09-19 17:32:00 +01002267 /* May be moved to focused list later by either
2268 * weston_keyboard_set_focus or directly if this client is already
2269 * focused */
Derek Foreman345c9f32015-06-03 15:53:28 -05002270 wl_list_insert(&keyboard->resource_list, wl_resource_get_link(cr));
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002271 wl_resource_set_implementation(cr, &keyboard_interface,
2272 seat, unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002273
Jonny Lamb66a41a02014-08-12 14:58:25 +02002274 if (wl_resource_get_version(cr) >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) {
2275 wl_keyboard_send_repeat_info(cr,
2276 seat->compositor->kb_repeat_rate,
2277 seat->compositor->kb_repeat_delay);
2278 }
Jasper St. Pierred8c6aeb2014-08-04 13:43:24 -04002279
Matt Roper01a92732013-06-24 16:52:44 +01002280 if (seat->compositor->use_xkbcommon) {
2281 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002282 keyboard->xkb_info->keymap_fd,
2283 keyboard->xkb_info->keymap_size);
Matt Roper01a92732013-06-24 16:52:44 +01002284 } else {
2285 int null_fd = open("/dev/null", O_RDONLY);
2286 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP,
2287 null_fd,
2288 0);
2289 close(null_fd);
2290 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002291
Neil Roberts96d790e2013-09-19 17:32:00 +01002292 if (should_send_modifiers_to_client(seat, client)) {
Derek Foreman345c9f32015-06-03 15:53:28 -05002293 send_modifiers_to_resource(keyboard,
Neil Roberts96d790e2013-09-19 17:32:00 +01002294 cr,
Derek Foreman345c9f32015-06-03 15:53:28 -05002295 keyboard->focus_serial);
Neil Roberts96d790e2013-09-19 17:32:00 +01002296 }
2297
Derek Foreman345c9f32015-06-03 15:53:28 -05002298 if (keyboard->focus && keyboard->focus->resource &&
2299 wl_resource_get_client(keyboard->focus->resource) == client) {
Neil Roberts96d790e2013-09-19 17:32:00 +01002300 struct weston_surface *surface =
Derek Foreman345c9f32015-06-03 15:53:28 -05002301 (struct weston_surface *)keyboard->focus;
Neil Roberts96d790e2013-09-19 17:32:00 +01002302
2303 wl_list_remove(wl_resource_get_link(cr));
Derek Foreman345c9f32015-06-03 15:53:28 -05002304 wl_list_insert(&keyboard->focus_resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01002305 wl_resource_get_link(cr));
2306 wl_keyboard_send_enter(cr,
Derek Foreman345c9f32015-06-03 15:53:28 -05002307 keyboard->focus_serial,
Neil Roberts96d790e2013-09-19 17:32:00 +01002308 surface->resource,
Derek Foreman345c9f32015-06-03 15:53:28 -05002309 &keyboard->keys);
Neil Roberts96d790e2013-09-19 17:32:00 +01002310
2311 /* If this is the first keyboard resource for this
2312 * client... */
Derek Foreman345c9f32015-06-03 15:53:28 -05002313 if (keyboard->focus_resource_list.prev ==
Neil Roberts96d790e2013-09-19 17:32:00 +01002314 wl_resource_get_link(cr))
2315 wl_data_device_set_keyboard_focus(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002316 }
2317}
2318
2319static void
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002320touch_release(struct wl_client *client, struct wl_resource *resource)
2321{
2322 wl_resource_destroy(resource);
2323}
2324
2325static const struct wl_touch_interface touch_interface = {
2326 touch_release
2327};
2328
2329static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002330seat_get_touch(struct wl_client *client, struct wl_resource *resource,
2331 uint32_t id)
2332{
Jason Ekstrand44a38632013-06-14 10:08:00 -05002333 struct weston_seat *seat = wl_resource_get_user_data(resource);
Derek Foreman1281a362015-07-31 16:55:32 -05002334 /* We use the touch_state directly, which means we'll
2335 * give a wl_touch if the seat has ever had one - even though
2336 * the spec explicitly states that this request only takes effect
2337 * if the seat has the touch capability.
2338 *
2339 * This prevents a race between the compositor sending new
2340 * capabilities and the client trying to use the old ones.
2341 */
2342 struct weston_touch *touch = seat->touch_state;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002343 struct wl_resource *cr;
2344
Derek Foreman1281a362015-07-31 16:55:32 -05002345 if (!touch)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002346 return;
2347
Jason Ekstranda85118c2013-06-27 20:17:02 -05002348 cr = wl_resource_create(client, &wl_touch_interface,
2349 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07002350 if (cr == NULL) {
2351 wl_client_post_no_memory(client);
2352 return;
2353 }
2354
Derek Foreman1281a362015-07-31 16:55:32 -05002355 if (touch->focus &&
2356 wl_resource_get_client(touch->focus->surface->resource) == client) {
Chokshi, Mituld6697142015-10-09 08:28:47 +00002357 wl_list_insert(&touch->focus_resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01002358 wl_resource_get_link(cr));
2359 } else {
Chokshi, Mituld6697142015-10-09 08:28:47 +00002360 wl_list_insert(&touch->resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01002361 wl_resource_get_link(cr));
2362 }
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002363 wl_resource_set_implementation(cr, &touch_interface,
2364 seat, unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002365}
2366
Quentin Glidicaab1d362016-03-13 17:49:08 +01002367static void
2368seat_release(struct wl_client *client, struct wl_resource *resource)
2369{
2370 wl_resource_destroy(resource);
2371}
2372
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002373static const struct wl_seat_interface seat_interface = {
2374 seat_get_pointer,
2375 seat_get_keyboard,
2376 seat_get_touch,
Quentin Glidicaab1d362016-03-13 17:49:08 +01002377 seat_release,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002378};
2379
2380static void
2381bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
2382{
Kristian Høgsberge3148752013-05-06 23:19:49 -04002383 struct weston_seat *seat = data;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002384 struct wl_resource *resource;
2385 enum wl_seat_capability caps = 0;
2386
Jason Ekstranda85118c2013-06-27 20:17:02 -05002387 resource = wl_resource_create(client,
Derek Foreman1909c102015-11-26 14:17:47 -06002388 &wl_seat_interface, version, id);
Jason Ekstrand44a38632013-06-14 10:08:00 -05002389 wl_list_insert(&seat->base_resource_list, wl_resource_get_link(resource));
Jason Ekstranda85118c2013-06-27 20:17:02 -05002390 wl_resource_set_implementation(resource, &seat_interface, data,
2391 unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002392
Derek Foreman1281a362015-07-31 16:55:32 -05002393 if (weston_seat_get_pointer(seat))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002394 caps |= WL_SEAT_CAPABILITY_POINTER;
Derek Foreman1281a362015-07-31 16:55:32 -05002395 if (weston_seat_get_keyboard(seat))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002396 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
Derek Foreman1281a362015-07-31 16:55:32 -05002397 if (weston_seat_get_touch(seat))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002398 caps |= WL_SEAT_CAPABILITY_TOUCH;
2399
2400 wl_seat_send_capabilities(resource, caps);
Jasper St. Pierre0013a292014-08-07 16:43:11 -04002401 if (version >= WL_SEAT_NAME_SINCE_VERSION)
Rob Bradforde445ae62013-05-31 18:09:51 +01002402 wl_seat_send_name(resource, seat->seat_name);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002403}
2404
Jonas Ådahl30d61d82014-10-22 21:21:17 +02002405static void
2406relative_pointer_destroy(struct wl_client *client,
2407 struct wl_resource *resource)
2408{
2409 wl_resource_destroy(resource);
2410}
2411
2412static const struct zwp_relative_pointer_v1_interface relative_pointer_interface = {
2413 relative_pointer_destroy
2414};
2415
2416static void
2417relative_pointer_manager_destroy(struct wl_client *client,
2418 struct wl_resource *resource)
2419{
2420 wl_resource_destroy(resource);
2421}
2422
2423static void
2424relative_pointer_manager_get_relative_pointer(struct wl_client *client,
2425 struct wl_resource *resource,
2426 uint32_t id,
2427 struct wl_resource *pointer_resource)
2428{
2429 struct weston_pointer *pointer =
2430 wl_resource_get_user_data(pointer_resource);
2431 struct weston_pointer_client *pointer_client;
2432 struct wl_resource *cr;
2433
2434 cr = wl_resource_create(client, &zwp_relative_pointer_v1_interface,
2435 wl_resource_get_version(resource), id);
2436 if (cr == NULL) {
2437 wl_client_post_no_memory(client);
2438 return;
2439 }
2440
2441 pointer_client = weston_pointer_ensure_pointer_client(pointer, client);
2442 if (!pointer_client) {
2443 wl_client_post_no_memory(client);
2444 return;
2445 }
2446
2447 wl_list_insert(&pointer_client->relative_pointer_resources,
2448 wl_resource_get_link(cr));
2449 wl_resource_set_implementation(cr, &relative_pointer_interface,
2450 pointer,
2451 unbind_pointer_client_resource);
2452}
2453
2454static const struct zwp_relative_pointer_manager_v1_interface relative_pointer_manager = {
2455 relative_pointer_manager_destroy,
2456 relative_pointer_manager_get_relative_pointer,
2457};
2458
2459static void
2460bind_relative_pointer_manager(struct wl_client *client, void *data,
2461 uint32_t version, uint32_t id)
2462{
2463 struct weston_compositor *compositor = data;
2464 struct wl_resource *resource;
2465
2466 resource = wl_resource_create(client,
2467 &zwp_relative_pointer_manager_v1_interface,
2468 1, id);
2469
2470 wl_resource_set_implementation(resource, &relative_pointer_manager,
2471 compositor,
2472 NULL);
2473}
2474
Rob Bradford382ff462013-06-24 16:52:45 +01002475#ifdef ENABLE_XKBCOMMON
Giulio Camuffo0358af42016-06-02 21:48:08 +03002476WL_EXPORT int
2477weston_compositor_set_xkb_rule_names(struct weston_compositor *ec,
2478 struct xkb_rule_names *names)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002479{
Rob Bradford382ff462013-06-24 16:52:45 +01002480 ec->use_xkbcommon = 1;
Matt Roper01a92732013-06-24 16:52:44 +01002481
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002482 if (ec->xkb_context == NULL) {
2483 ec->xkb_context = xkb_context_new(0);
2484 if (ec->xkb_context == NULL) {
2485 weston_log("failed to create XKB context\n");
2486 return -1;
2487 }
2488 }
2489
2490 if (names)
2491 ec->xkb_names = *names;
2492 if (!ec->xkb_names.rules)
2493 ec->xkb_names.rules = strdup("evdev");
2494 if (!ec->xkb_names.model)
2495 ec->xkb_names.model = strdup("pc105");
2496 if (!ec->xkb_names.layout)
2497 ec->xkb_names.layout = strdup("us");
2498
2499 return 0;
2500}
2501
Stefan Schmidtfda26522013-09-17 10:54:09 +01002502static void
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002503weston_xkb_info_destroy(struct weston_xkb_info *xkb_info)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002504{
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002505 if (--xkb_info->ref_count > 0)
2506 return;
2507
Ran Benitac9c74152014-08-19 23:59:52 +03002508 xkb_keymap_unref(xkb_info->keymap);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002509
2510 if (xkb_info->keymap_area)
2511 munmap(xkb_info->keymap_area, xkb_info->keymap_size);
2512 if (xkb_info->keymap_fd >= 0)
2513 close(xkb_info->keymap_fd);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002514 free(xkb_info);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002515}
2516
2517void
2518weston_compositor_xkb_destroy(struct weston_compositor *ec)
2519{
Matt Roper01a92732013-06-24 16:52:44 +01002520 /*
2521 * If we're operating in raw keyboard mode, we never initialized
2522 * libxkbcommon so there's no cleanup to do either.
2523 */
2524 if (!ec->use_xkbcommon)
2525 return;
2526
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002527 free((char *) ec->xkb_names.rules);
2528 free((char *) ec->xkb_names.model);
2529 free((char *) ec->xkb_names.layout);
2530 free((char *) ec->xkb_names.variant);
2531 free((char *) ec->xkb_names.options);
Stefan Schmidtfda26522013-09-17 10:54:09 +01002532
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002533 if (ec->xkb_info)
2534 weston_xkb_info_destroy(ec->xkb_info);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002535 xkb_context_unref(ec->xkb_context);
2536}
2537
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002538static struct weston_xkb_info *
2539weston_xkb_info_create(struct xkb_keymap *keymap)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002540{
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002541 struct weston_xkb_info *xkb_info = zalloc(sizeof *xkb_info);
2542 if (xkb_info == NULL)
2543 return NULL;
2544
Ran Benita2e1968f2014-08-19 23:59:51 +03002545 xkb_info->keymap = xkb_keymap_ref(keymap);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002546 xkb_info->ref_count = 1;
2547
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002548 char *keymap_str;
2549
Ran Benita2e1968f2014-08-19 23:59:51 +03002550 xkb_info->shift_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2551 XKB_MOD_NAME_SHIFT);
2552 xkb_info->caps_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2553 XKB_MOD_NAME_CAPS);
2554 xkb_info->ctrl_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2555 XKB_MOD_NAME_CTRL);
2556 xkb_info->alt_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2557 XKB_MOD_NAME_ALT);
2558 xkb_info->mod2_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2559 "Mod2");
2560 xkb_info->mod3_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2561 "Mod3");
2562 xkb_info->super_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2563 XKB_MOD_NAME_LOGO);
2564 xkb_info->mod5_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2565 "Mod5");
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002566
Ran Benita2e1968f2014-08-19 23:59:51 +03002567 xkb_info->num_led = xkb_keymap_led_get_index(xkb_info->keymap,
2568 XKB_LED_NAME_NUM);
2569 xkb_info->caps_led = xkb_keymap_led_get_index(xkb_info->keymap,
2570 XKB_LED_NAME_CAPS);
2571 xkb_info->scroll_led = xkb_keymap_led_get_index(xkb_info->keymap,
2572 XKB_LED_NAME_SCROLL);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002573
Ran Benita2e1968f2014-08-19 23:59:51 +03002574 keymap_str = xkb_keymap_get_as_string(xkb_info->keymap,
2575 XKB_KEYMAP_FORMAT_TEXT_V1);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002576 if (keymap_str == NULL) {
2577 weston_log("failed to get string version of keymap\n");
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002578 goto err_keymap;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002579 }
2580 xkb_info->keymap_size = strlen(keymap_str) + 1;
2581
2582 xkb_info->keymap_fd = os_create_anonymous_file(xkb_info->keymap_size);
2583 if (xkb_info->keymap_fd < 0) {
2584 weston_log("creating a keymap file for %lu bytes failed: %m\n",
2585 (unsigned long) xkb_info->keymap_size);
2586 goto err_keymap_str;
2587 }
2588
2589 xkb_info->keymap_area = mmap(NULL, xkb_info->keymap_size,
2590 PROT_READ | PROT_WRITE,
2591 MAP_SHARED, xkb_info->keymap_fd, 0);
2592 if (xkb_info->keymap_area == MAP_FAILED) {
2593 weston_log("failed to mmap() %lu bytes\n",
2594 (unsigned long) xkb_info->keymap_size);
2595 goto err_dev_zero;
2596 }
2597 strcpy(xkb_info->keymap_area, keymap_str);
2598 free(keymap_str);
2599
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002600 return xkb_info;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002601
2602err_dev_zero:
2603 close(xkb_info->keymap_fd);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002604err_keymap_str:
2605 free(keymap_str);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002606err_keymap:
Ran Benita2e1968f2014-08-19 23:59:51 +03002607 xkb_keymap_unref(xkb_info->keymap);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002608 free(xkb_info);
2609 return NULL;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002610}
2611
2612static int
2613weston_compositor_build_global_keymap(struct weston_compositor *ec)
2614{
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002615 struct xkb_keymap *keymap;
2616
2617 if (ec->xkb_info != NULL)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002618 return 0;
2619
Ran Benita2e1968f2014-08-19 23:59:51 +03002620 keymap = xkb_keymap_new_from_names(ec->xkb_context,
2621 &ec->xkb_names,
2622 0);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002623 if (keymap == NULL) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002624 weston_log("failed to compile global XKB keymap\n");
2625 weston_log(" tried rules %s, model %s, layout %s, variant %s, "
2626 "options %s\n",
2627 ec->xkb_names.rules, ec->xkb_names.model,
2628 ec->xkb_names.layout, ec->xkb_names.variant,
2629 ec->xkb_names.options);
2630 return -1;
2631 }
2632
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002633 ec->xkb_info = weston_xkb_info_create(keymap);
Rui Matos73d93952013-10-24 19:28:41 +02002634 xkb_keymap_unref(keymap);
Stefan Schmidtfda26522013-09-17 10:54:09 +01002635 if (ec->xkb_info == NULL)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002636 return -1;
2637
2638 return 0;
2639}
Rob Bradford382ff462013-06-24 16:52:45 +01002640#else
Giulio Camuffo0358af42016-06-02 21:48:08 +03002641WL_EXPORT int
2642weston_compositor_set_xkb_rule_names(struct weston_compositor *ec,
2643 struct xkb_rule_names *names)
Rob Bradford382ff462013-06-24 16:52:45 +01002644{
2645 return 0;
2646}
2647
2648void
2649weston_compositor_xkb_destroy(struct weston_compositor *ec)
2650{
2651}
2652#endif
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002653
Rui Matos65196bc2013-10-10 19:44:19 +02002654WL_EXPORT void
2655weston_seat_update_keymap(struct weston_seat *seat, struct xkb_keymap *keymap)
2656{
Derek Foreman1281a362015-07-31 16:55:32 -05002657 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
2658
2659 if (!keyboard || !keymap)
Rui Matos65196bc2013-10-10 19:44:19 +02002660 return;
2661
2662#ifdef ENABLE_XKBCOMMON
2663 if (!seat->compositor->use_xkbcommon)
2664 return;
2665
Derek Foreman1281a362015-07-31 16:55:32 -05002666 xkb_keymap_unref(keyboard->pending_keymap);
2667 keyboard->pending_keymap = xkb_keymap_ref(keymap);
Rui Matos65196bc2013-10-10 19:44:19 +02002668
Derek Foreman1281a362015-07-31 16:55:32 -05002669 if (keyboard->keys.size == 0)
Rui Matos65196bc2013-10-10 19:44:19 +02002670 update_keymap(seat);
2671#endif
2672}
2673
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002674WL_EXPORT int
2675weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap)
2676{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002677 struct weston_keyboard *keyboard;
2678
Derek Foreman1281a362015-07-31 16:55:32 -05002679 if (seat->keyboard_state) {
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002680 seat->keyboard_device_count += 1;
2681 if (seat->keyboard_device_count == 1)
2682 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002683 return 0;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002684 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002685
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002686 keyboard = weston_keyboard_create();
2687 if (keyboard == NULL) {
2688 weston_log("failed to allocate weston keyboard struct\n");
2689 return -1;
2690 }
2691
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002692#ifdef ENABLE_XKBCOMMON
2693 if (seat->compositor->use_xkbcommon) {
2694 if (keymap != NULL) {
2695 keyboard->xkb_info = weston_xkb_info_create(keymap);
2696 if (keyboard->xkb_info == NULL)
Ander Conselvan de Oliveira4d363cf2014-01-31 17:35:45 +02002697 goto err;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002698 } else {
2699 if (weston_compositor_build_global_keymap(seat->compositor) < 0)
Ander Conselvan de Oliveira4d363cf2014-01-31 17:35:45 +02002700 goto err;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002701 keyboard->xkb_info = seat->compositor->xkb_info;
2702 keyboard->xkb_info->ref_count++;
2703 }
2704
2705 keyboard->xkb_state.state = xkb_state_new(keyboard->xkb_info->keymap);
2706 if (keyboard->xkb_state.state == NULL) {
2707 weston_log("failed to initialise XKB state\n");
Ander Conselvan de Oliveira4d363cf2014-01-31 17:35:45 +02002708 goto err;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002709 }
2710
2711 keyboard->xkb_state.leds = 0;
2712 }
2713#endif
2714
Derek Foreman1281a362015-07-31 16:55:32 -05002715 seat->keyboard_state = keyboard;
Ander Conselvan de Oliveira4d363cf2014-01-31 17:35:45 +02002716 seat->keyboard_device_count = 1;
2717 keyboard->seat = seat;
2718
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002719 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002720
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002721 return 0;
Ander Conselvan de Oliveira4d363cf2014-01-31 17:35:45 +02002722
2723err:
2724 if (keyboard->xkb_info)
2725 weston_xkb_info_destroy(keyboard->xkb_info);
2726 free(keyboard);
2727
2728 return -1;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002729}
2730
Jonas Ådahl91fed542013-12-03 09:14:27 +01002731static void
2732weston_keyboard_reset_state(struct weston_keyboard *keyboard)
2733{
2734 struct weston_seat *seat = keyboard->seat;
2735 struct xkb_state *state;
2736
2737#ifdef ENABLE_XKBCOMMON
2738 if (seat->compositor->use_xkbcommon) {
2739 state = xkb_state_new(keyboard->xkb_info->keymap);
2740 if (!state) {
2741 weston_log("failed to reset XKB state\n");
2742 return;
2743 }
2744 xkb_state_unref(keyboard->xkb_state.state);
2745 keyboard->xkb_state.state = state;
2746
2747 keyboard->xkb_state.leds = 0;
2748 }
2749#endif
2750
2751 seat->modifier_state = 0;
2752}
2753
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002754WL_EXPORT void
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002755weston_seat_release_keyboard(struct weston_seat *seat)
2756{
2757 seat->keyboard_device_count--;
Derek Foremand621df22014-11-19 11:04:12 -06002758 assert(seat->keyboard_device_count >= 0);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002759 if (seat->keyboard_device_count == 0) {
Derek Foreman1281a362015-07-31 16:55:32 -05002760 weston_keyboard_set_focus(seat->keyboard_state, NULL);
2761 weston_keyboard_cancel_grab(seat->keyboard_state);
2762 weston_keyboard_reset_state(seat->keyboard_state);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002763 seat_send_updated_caps(seat);
2764 }
2765}
2766
2767WL_EXPORT void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002768weston_seat_init_pointer(struct weston_seat *seat)
2769{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002770 struct weston_pointer *pointer;
2771
Derek Foreman1281a362015-07-31 16:55:32 -05002772 if (seat->pointer_state) {
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002773 seat->pointer_device_count += 1;
2774 if (seat->pointer_device_count == 1)
2775 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002776 return;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002777 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002778
Giulio Camuffocdb4d292013-11-14 23:42:53 +01002779 pointer = weston_pointer_create(seat);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002780 if (pointer == NULL)
2781 return;
2782
Derek Foreman1281a362015-07-31 16:55:32 -05002783 seat->pointer_state = pointer;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002784 seat->pointer_device_count = 1;
2785 pointer->seat = seat;
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002786
2787 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002788}
2789
2790WL_EXPORT void
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002791weston_seat_release_pointer(struct weston_seat *seat)
2792{
Derek Foreman1281a362015-07-31 16:55:32 -05002793 struct weston_pointer *pointer = seat->pointer_state;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002794
2795 seat->pointer_device_count--;
2796 if (seat->pointer_device_count == 0) {
Derek Foremanf9318d12015-05-11 15:40:11 -05002797 weston_pointer_clear_focus(pointer);
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02002798 weston_pointer_cancel_grab(pointer);
Jonas Ådahl630bae82013-10-17 23:04:06 +02002799
Jonas Ådahla4932742013-10-17 23:04:07 +02002800 if (pointer->sprite)
2801 pointer_unmap_sprite(pointer);
2802
Jonas Ådahl3e12e632013-12-02 22:05:05 +01002803 weston_pointer_reset_state(pointer);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002804 seat_send_updated_caps(seat);
Derek Foremanfd5ca512015-01-07 15:00:25 -06002805
2806 /* seat->pointer is intentionally not destroyed so that
2807 * a newly attached pointer on this seat will retain
2808 * the previous cursor co-ordinates.
2809 */
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002810 }
2811}
2812
2813WL_EXPORT void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002814weston_seat_init_touch(struct weston_seat *seat)
2815{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002816 struct weston_touch *touch;
2817
Derek Foreman1281a362015-07-31 16:55:32 -05002818 if (seat->touch_state) {
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002819 seat->touch_device_count += 1;
2820 if (seat->touch_device_count == 1)
2821 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002822 return;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002823 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002824
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002825 touch = weston_touch_create();
2826 if (touch == NULL)
2827 return;
2828
Derek Foreman1281a362015-07-31 16:55:32 -05002829 seat->touch_state = touch;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002830 seat->touch_device_count = 1;
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002831 touch->seat = seat;
2832
2833 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002834}
2835
2836WL_EXPORT void
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002837weston_seat_release_touch(struct weston_seat *seat)
2838{
2839 seat->touch_device_count--;
2840 if (seat->touch_device_count == 0) {
Derek Foreman1281a362015-07-31 16:55:32 -05002841 weston_touch_set_focus(seat->touch_state, NULL);
2842 weston_touch_cancel_grab(seat->touch_state);
2843 weston_touch_reset_state(seat->touch_state);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002844 seat_send_updated_caps(seat);
2845 }
2846}
2847
2848WL_EXPORT void
Rob Bradford9af5f9e2013-05-31 18:09:50 +01002849weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec,
2850 const char *seat_name)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002851{
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04002852 memset(seat, 0, sizeof *seat);
2853
Kristian Høgsberge3148752013-05-06 23:19:49 -04002854 seat->selection_data_source = NULL;
2855 wl_list_init(&seat->base_resource_list);
2856 wl_signal_init(&seat->selection_signal);
2857 wl_list_init(&seat->drag_resource_list);
Kristian Høgsberge3148752013-05-06 23:19:49 -04002858 wl_signal_init(&seat->destroy_signal);
Jason Ekstranda4ab5422014-04-02 19:53:45 -05002859 wl_signal_init(&seat->updated_caps_signal);
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04002860
Peter Hutterer87743e92016-01-18 16:38:22 +10002861 seat->global = wl_global_create(ec->wl_display, &wl_seat_interface, 5,
Kristian Høgsberg919cddb2013-07-08 19:03:57 -04002862 seat, bind_seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002863
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002864 seat->compositor = ec;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002865 seat->modifier_state = 0;
Rob Bradford9af5f9e2013-05-31 18:09:50 +01002866 seat->seat_name = strdup(seat_name);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002867
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002868 wl_list_insert(ec->seat_list.prev, &seat->link);
2869
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002870 clipboard_create(seat);
2871
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002872 wl_signal_emit(&ec->seat_created_signal, seat);
2873}
2874
2875WL_EXPORT void
2876weston_seat_release(struct weston_seat *seat)
2877{
2878 wl_list_remove(&seat->link);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002879
Jonas Ådahl1afb2382014-01-03 19:46:51 +01002880 if (seat->saved_kbd_focus)
2881 wl_list_remove(&seat->saved_kbd_focus_listener.link);
2882
Derek Foreman1281a362015-07-31 16:55:32 -05002883 if (seat->pointer_state)
2884 weston_pointer_destroy(seat->pointer_state);
2885 if (seat->keyboard_state)
2886 weston_keyboard_destroy(seat->keyboard_state);
2887 if (seat->touch_state)
2888 weston_touch_destroy(seat->touch_state);
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04002889
Rob Bradford9af5f9e2013-05-31 18:09:50 +01002890 free (seat->seat_name);
2891
Kristian Høgsberg919cddb2013-07-08 19:03:57 -04002892 wl_global_destroy(seat->global);
Kristian Høgsbergaaadc772013-07-08 16:20:31 -04002893
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002894 wl_signal_emit(&seat->destroy_signal, seat);
2895}
Derek Foreman1281a362015-07-31 16:55:32 -05002896
2897/** Get a seat's keyboard pointer
2898 *
2899 * \param seat The seat to query
2900 * \return The seat's keyboard pointer, or NULL if no keyboard is present
2901 *
2902 * The keyboard pointer for a seat isn't freed when all keyboards are removed,
2903 * so it should only be used when the seat's keyboard_device_count is greater
2904 * than zero. This function does that test and only returns a pointer
2905 * when a keyboard is present.
2906 */
2907WL_EXPORT struct weston_keyboard *
2908weston_seat_get_keyboard(struct weston_seat *seat)
2909{
2910 if (!seat)
2911 return NULL;
2912
2913 if (seat->keyboard_device_count)
2914 return seat->keyboard_state;
2915
2916 return NULL;
2917}
2918
2919/** Get a seat's pointer pointer
2920 *
2921 * \param seat The seat to query
2922 * \return The seat's pointer pointer, or NULL if no pointer device is present
2923 *
2924 * The pointer pointer for a seat isn't freed when all mice are removed,
2925 * so it should only be used when the seat's pointer_device_count is greater
2926 * than zero. This function does that test and only returns a pointer
2927 * when a pointing device is present.
2928 */
2929WL_EXPORT struct weston_pointer *
2930weston_seat_get_pointer(struct weston_seat *seat)
2931{
2932 if (!seat)
2933 return NULL;
2934
2935 if (seat->pointer_device_count)
2936 return seat->pointer_state;
2937
2938 return NULL;
2939}
2940
Jonas Ådahld3414f22016-07-22 17:56:31 +08002941static const struct zwp_locked_pointer_v1_interface locked_pointer_interface;
2942static const struct zwp_confined_pointer_v1_interface confined_pointer_interface;
2943
2944static enum pointer_constraint_type
2945pointer_constraint_get_type(struct weston_pointer_constraint *constraint)
2946{
2947 if (wl_resource_instance_of(constraint->resource,
2948 &zwp_locked_pointer_v1_interface,
2949 &locked_pointer_interface)) {
2950 return POINTER_CONSTRAINT_TYPE_LOCK;
2951 } else if (wl_resource_instance_of(constraint->resource,
2952 &zwp_confined_pointer_v1_interface,
2953 &confined_pointer_interface)) {
2954 return POINTER_CONSTRAINT_TYPE_CONFINE;
2955 }
2956
2957 abort();
2958 return 0;
2959}
2960
2961static void
2962pointer_constraint_notify_activated(struct weston_pointer_constraint *constraint)
2963{
2964 struct wl_resource *resource = constraint->resource;
2965
2966 switch (pointer_constraint_get_type(constraint)) {
2967 case POINTER_CONSTRAINT_TYPE_LOCK:
2968 zwp_locked_pointer_v1_send_locked(resource);
2969 break;
2970 case POINTER_CONSTRAINT_TYPE_CONFINE:
2971 zwp_confined_pointer_v1_send_confined(resource);
2972 break;
2973 }
2974}
2975
2976static void
2977pointer_constraint_notify_deactivated(struct weston_pointer_constraint *constraint)
2978{
2979 struct wl_resource *resource = constraint->resource;
2980
2981 switch (pointer_constraint_get_type(constraint)) {
2982 case POINTER_CONSTRAINT_TYPE_LOCK:
2983 zwp_locked_pointer_v1_send_unlocked(resource);
2984 break;
2985 case POINTER_CONSTRAINT_TYPE_CONFINE:
2986 zwp_confined_pointer_v1_send_unconfined(resource);
2987 break;
2988 }
2989}
2990
2991static struct weston_pointer_constraint *
2992get_pointer_constraint_for_pointer(struct weston_surface *surface,
2993 struct weston_pointer *pointer)
2994{
2995 struct weston_pointer_constraint *constraint;
2996
2997 wl_list_for_each(constraint, &surface->pointer_constraints, link) {
2998 if (constraint->pointer == pointer)
2999 return constraint;
3000 }
3001
3002 return NULL;
3003}
3004
Derek Foreman1281a362015-07-31 16:55:32 -05003005/** Get a seat's touch pointer
3006 *
3007 * \param seat The seat to query
3008 * \return The seat's touch pointer, or NULL if no touch device is present
3009 *
3010 * The touch pointer for a seat isn't freed when all touch devices are removed,
3011 * so it should only be used when the seat's touch_device_count is greater
3012 * than zero. This function does that test and only returns a pointer
3013 * when a touch device is present.
3014 */
3015WL_EXPORT struct weston_touch *
3016weston_seat_get_touch(struct weston_seat *seat)
3017{
3018 if (!seat)
3019 return NULL;
3020
3021 if (seat->touch_device_count)
3022 return seat->touch_state;
3023
3024 return NULL;
3025}
Bryce Harrington24f917e2016-06-29 19:04:07 -07003026
3027/** Sets the keyboard focus to the given surface
3028 *
3029 * \param seat The seat to query
3030 */
3031WL_EXPORT void
3032weston_seat_set_keyboard_focus(struct weston_seat *seat,
3033 struct weston_surface *surface)
3034{
3035 struct weston_compositor *compositor = seat->compositor;
3036 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Jonas Ådahlf7deb6a2016-07-22 17:50:26 +08003037 struct weston_surface_activation_data activation_data;
Bryce Harrington24f917e2016-06-29 19:04:07 -07003038
Jonas Ådahlef8e1c32016-03-15 20:28:51 +08003039 if (keyboard && keyboard->focus != surface) {
Bryce Harrington24f917e2016-06-29 19:04:07 -07003040 weston_keyboard_set_focus(keyboard, surface);
3041 wl_data_device_set_keyboard_focus(seat);
3042 }
3043
Jonas Ådahl94e2e2d2014-10-18 18:42:19 +02003044 inc_activate_serial(compositor);
Jonas Ådahlf7deb6a2016-07-22 17:50:26 +08003045
3046 activation_data = (struct weston_surface_activation_data) {
3047 .surface = surface,
3048 .seat = seat,
3049 };
3050 wl_signal_emit(&compositor->activate_signal, &activation_data);
Bryce Harrington24f917e2016-06-29 19:04:07 -07003051}
Jonas Ådahl30d61d82014-10-22 21:21:17 +02003052
Jonas Ådahld3414f22016-07-22 17:56:31 +08003053static void
3054enable_pointer_constraint(struct weston_pointer_constraint *constraint,
3055 struct weston_view *view)
3056{
3057 assert(constraint->view == NULL);
3058 constraint->view = view;
3059 pointer_constraint_notify_activated(constraint);
3060 weston_pointer_start_grab(constraint->pointer, &constraint->grab);
3061 wl_list_remove(&constraint->surface_destroy_listener.link);
3062 wl_list_init(&constraint->surface_destroy_listener.link);
3063}
3064
3065static bool
3066is_pointer_constraint_enabled(struct weston_pointer_constraint *constraint)
3067{
3068 return constraint->view != NULL;
3069}
3070
3071static void
3072weston_pointer_constraint_disable(struct weston_pointer_constraint *constraint)
3073{
3074 constraint->view = NULL;
3075 pointer_constraint_notify_deactivated(constraint);
3076 weston_pointer_end_grab(constraint->grab.pointer);
3077}
3078
3079void
3080weston_pointer_constraint_destroy(struct weston_pointer_constraint *constraint)
3081{
3082 if (is_pointer_constraint_enabled(constraint))
3083 weston_pointer_constraint_disable(constraint);
3084
3085 wl_list_remove(&constraint->pointer_destroy_listener.link);
3086 wl_list_remove(&constraint->surface_destroy_listener.link);
3087 wl_list_remove(&constraint->surface_commit_listener.link);
3088 wl_list_remove(&constraint->surface_activate_listener.link);
3089
3090 wl_resource_set_user_data(constraint->resource, NULL);
3091 pixman_region32_fini(&constraint->region);
3092 wl_list_remove(&constraint->link);
3093 free(constraint);
3094}
3095
3096static void
3097disable_pointer_constraint(struct weston_pointer_constraint *constraint)
3098{
3099 switch (constraint->lifetime) {
3100 case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT:
3101 weston_pointer_constraint_destroy(constraint);
3102 break;
3103 case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT:
3104 weston_pointer_constraint_disable(constraint);
3105 break;
3106 }
3107}
3108
3109static bool
3110is_within_constraint_region(struct weston_pointer_constraint *constraint,
3111 wl_fixed_t sx, wl_fixed_t sy)
3112{
3113 struct weston_surface *surface = constraint->surface;
3114 pixman_region32_t constraint_region;
3115 bool result;
3116
3117 pixman_region32_init(&constraint_region);
3118 pixman_region32_intersect(&constraint_region,
3119 &surface->input,
3120 &constraint->region);
3121 result = pixman_region32_contains_point(&constraint_region,
3122 wl_fixed_to_int(sx),
3123 wl_fixed_to_int(sy),
3124 NULL);
3125 pixman_region32_fini(&constraint_region);
3126
3127 return result;
3128}
3129
3130static void
3131maybe_enable_pointer_constraint(struct weston_pointer_constraint *constraint)
3132{
3133 struct weston_surface *surface = constraint->surface;
3134 struct weston_view *vit;
3135 struct weston_view *view = NULL;
3136 struct weston_pointer *pointer = constraint->pointer;
3137 struct weston_keyboard *keyboard;
3138 struct weston_seat *seat = pointer->seat;
3139 int32_t x, y;
3140
3141 /* Postpone if no view of the surface was most recently clicked. */
3142 wl_list_for_each(vit, &surface->views, surface_link) {
3143 if (vit->click_to_activate_serial ==
3144 surface->compositor->activate_serial) {
3145 view = vit;
3146 }
3147 }
3148 if (view == NULL)
3149 return;
3150
3151 /* Postpone if surface doesn't have keyboard focus. */
3152 keyboard = weston_seat_get_keyboard(seat);
3153 if (!keyboard || keyboard->focus != surface)
3154 return;
3155
3156 /* Postpone constraint if the pointer is not within the
3157 * constraint region.
3158 */
3159 weston_view_from_global(view,
3160 wl_fixed_to_int(pointer->x),
3161 wl_fixed_to_int(pointer->y),
3162 &x, &y);
3163 if (!is_within_constraint_region(constraint,
3164 wl_fixed_from_int(x),
3165 wl_fixed_from_int(y)))
3166 return;
3167
3168 enable_pointer_constraint(constraint, view);
3169}
3170
3171static void
3172locked_pointer_grab_pointer_focus(struct weston_pointer_grab *grab)
3173{
3174}
3175
3176static void
3177locked_pointer_grab_pointer_motion(struct weston_pointer_grab *grab,
3178 uint32_t time,
3179 struct weston_pointer_motion_event *event)
3180{
3181 weston_pointer_send_relative_motion(grab->pointer, time, event);
3182}
3183
3184static void
3185locked_pointer_grab_pointer_button(struct weston_pointer_grab *grab,
3186 uint32_t time,
3187 uint32_t button,
3188 uint32_t state_w)
3189{
3190 weston_pointer_send_button(grab->pointer, time, button, state_w);
3191}
3192
3193static void
3194locked_pointer_grab_pointer_axis(struct weston_pointer_grab *grab,
3195 uint32_t time,
3196 struct weston_pointer_axis_event *event)
3197{
3198 weston_pointer_send_axis(grab->pointer, time, event);
3199}
3200
3201static void
3202locked_pointer_grab_pointer_axis_source(struct weston_pointer_grab *grab,
3203 uint32_t source)
3204{
3205 weston_pointer_send_axis_source(grab->pointer, source);
3206}
3207
3208static void
3209locked_pointer_grab_pointer_frame(struct weston_pointer_grab *grab)
3210{
3211 weston_pointer_send_frame(grab->pointer);
3212}
3213
3214static void
3215locked_pointer_grab_pointer_cancel(struct weston_pointer_grab *grab)
3216{
3217 struct weston_pointer_constraint *constraint =
3218 container_of(grab, struct weston_pointer_constraint, grab);
3219
3220 disable_pointer_constraint(constraint);
3221}
3222
3223static const struct weston_pointer_grab_interface
3224 locked_pointer_grab_interface = {
3225 locked_pointer_grab_pointer_focus,
3226 locked_pointer_grab_pointer_motion,
3227 locked_pointer_grab_pointer_button,
3228 locked_pointer_grab_pointer_axis,
3229 locked_pointer_grab_pointer_axis_source,
3230 locked_pointer_grab_pointer_frame,
3231 locked_pointer_grab_pointer_cancel,
3232};
3233
3234static void
3235pointer_constraint_constrain_resource_destroyed(struct wl_resource *resource)
3236{
3237 struct weston_pointer_constraint *constraint =
3238 wl_resource_get_user_data(resource);
3239
3240 if (!constraint)
3241 return;
3242
3243 weston_pointer_constraint_destroy(constraint);
3244}
3245
3246static void
3247pointer_constraint_surface_activate(struct wl_listener *listener, void *data)
3248{
3249 struct weston_surface_activation_data *activation = data;
3250 struct weston_pointer *pointer;
3251 struct weston_surface *focus = activation->surface;
3252 struct weston_pointer_constraint *constraint =
3253 container_of(listener, struct weston_pointer_constraint,
3254 surface_activate_listener);
3255 bool is_constraint_surface;
3256
3257 pointer = weston_seat_get_pointer(activation->seat);
3258 if (!pointer)
3259 return;
3260
3261 is_constraint_surface =
3262 get_pointer_constraint_for_pointer(focus, pointer) == constraint;
3263
3264 if (is_constraint_surface &&
3265 !is_pointer_constraint_enabled(constraint))
3266 maybe_enable_pointer_constraint(constraint);
3267 else if (!is_constraint_surface &&
3268 is_pointer_constraint_enabled(constraint))
3269 disable_pointer_constraint(constraint);
3270}
3271
3272static void
3273pointer_constraint_pointer_destroyed(struct wl_listener *listener, void *data)
3274{
3275 struct weston_pointer_constraint *constraint =
3276 container_of(listener, struct weston_pointer_constraint,
3277 pointer_destroy_listener);
3278
3279 weston_pointer_constraint_destroy(constraint);
3280}
3281
3282static void
3283pointer_constraint_surface_destroyed(struct wl_listener *listener, void *data)
3284{
3285 struct weston_pointer_constraint *constraint =
3286 container_of(listener, struct weston_pointer_constraint,
3287 surface_destroy_listener);
3288
3289 weston_pointer_constraint_destroy(constraint);
3290}
3291
3292static void
3293pointer_constraint_surface_committed(struct wl_listener *listener, void *data)
3294{
3295 struct weston_pointer_constraint *constraint =
3296 container_of(listener, struct weston_pointer_constraint,
3297 surface_commit_listener);
3298
3299 if (constraint->region_is_pending) {
3300 constraint->region_is_pending = false;
3301 pixman_region32_copy(&constraint->region,
3302 &constraint->region_pending);
3303 pixman_region32_fini(&constraint->region_pending);
3304 pixman_region32_init(&constraint->region_pending);
3305 }
3306
3307 if (constraint->hint_is_pending) {
3308 constraint->hint_is_pending = false;
3309
3310 constraint->hint_is_pending = true;
3311 constraint->hint_x = constraint->hint_x_pending;
3312 constraint->hint_y = constraint->hint_y_pending;
3313 }
3314
3315 if (pointer_constraint_get_type(constraint) ==
3316 POINTER_CONSTRAINT_TYPE_CONFINE &&
3317 is_pointer_constraint_enabled(constraint))
3318 maybe_warp_confined_pointer(constraint);
3319}
3320
3321static struct weston_pointer_constraint *
3322weston_pointer_constraint_create(struct weston_surface *surface,
3323 struct weston_pointer *pointer,
3324 struct weston_region *region,
3325 enum zwp_pointer_constraints_v1_lifetime lifetime,
3326 struct wl_resource *cr,
3327 const struct weston_pointer_grab_interface *grab_interface)
3328{
3329 struct weston_pointer_constraint *constraint;
3330
3331 constraint = zalloc(sizeof *constraint);
3332 if (!constraint)
3333 return NULL;
3334
3335 constraint->lifetime = lifetime;
3336 pixman_region32_init(&constraint->region);
3337 pixman_region32_init(&constraint->region_pending);
3338 wl_list_insert(&surface->pointer_constraints, &constraint->link);
3339 constraint->surface = surface;
3340 constraint->pointer = pointer;
3341 constraint->resource = cr;
3342 constraint->grab.interface = grab_interface;
3343 if (region) {
3344 pixman_region32_copy(&constraint->region,
3345 &region->region);
3346 } else {
3347 pixman_region32_fini(&constraint->region);
3348 region_init_infinite(&constraint->region);
3349 }
3350
3351 constraint->surface_activate_listener.notify =
3352 pointer_constraint_surface_activate;
3353 constraint->surface_destroy_listener.notify =
3354 pointer_constraint_surface_destroyed;
3355 constraint->surface_commit_listener.notify =
3356 pointer_constraint_surface_committed;
3357 constraint->pointer_destroy_listener.notify =
3358 pointer_constraint_pointer_destroyed;
3359
3360 wl_signal_add(&surface->compositor->activate_signal,
3361 &constraint->surface_activate_listener);
3362 wl_signal_add(&pointer->destroy_signal,
3363 &constraint->pointer_destroy_listener);
3364 wl_signal_add(&surface->destroy_signal,
3365 &constraint->surface_destroy_listener);
3366 wl_signal_add(&surface->commit_signal,
3367 &constraint->surface_commit_listener);
3368
3369 return constraint;
3370}
3371
3372static void
3373init_pointer_constraint(struct wl_resource *pointer_constraints_resource,
3374 uint32_t id,
3375 struct weston_surface *surface,
3376 struct weston_pointer *pointer,
3377 struct weston_region *region,
3378 enum zwp_pointer_constraints_v1_lifetime lifetime,
3379 const struct wl_interface *interface,
3380 const void *implementation,
3381 const struct weston_pointer_grab_interface *grab_interface)
3382{
3383 struct wl_client *client =
3384 wl_resource_get_client(pointer_constraints_resource);
3385 struct wl_resource *cr;
3386 struct weston_pointer_constraint *constraint;
3387
3388 if (get_pointer_constraint_for_pointer(surface, pointer)) {
3389 wl_resource_post_error(pointer_constraints_resource,
3390 ZWP_POINTER_CONSTRAINTS_V1_ERROR_ALREADY_CONSTRAINED,
3391 "the pointer has a lock/confine request on this surface");
3392 return;
3393 }
3394
3395 cr = wl_resource_create(client, interface,
3396 wl_resource_get_version(pointer_constraints_resource),
3397 id);
3398 if (cr == NULL) {
3399 wl_client_post_no_memory(client);
3400 return;
3401 }
3402
3403 constraint = weston_pointer_constraint_create(surface, pointer,
3404 region, lifetime,
3405 cr, grab_interface);
3406 if (constraint == NULL) {
3407 wl_client_post_no_memory(client);
3408 return;
3409 }
3410
3411 wl_resource_set_implementation(cr, implementation, constraint,
3412 pointer_constraint_constrain_resource_destroyed);
3413
3414 maybe_enable_pointer_constraint(constraint);
3415}
3416
3417static void
3418pointer_constraints_destroy(struct wl_client *client,
3419 struct wl_resource *resource)
3420{
3421 wl_resource_destroy(resource);
3422}
3423
3424static void
3425locked_pointer_destroy(struct wl_client *client,
3426 struct wl_resource *resource)
3427{
3428 struct weston_pointer_constraint *constraint =
3429 wl_resource_get_user_data(resource);
3430 wl_fixed_t x, y;
3431
3432 if (constraint && constraint->view && constraint->hint_is_pending &&
3433 is_within_constraint_region(constraint,
3434 constraint->hint_x,
3435 constraint->hint_y)) {
3436 weston_view_to_global_fixed(constraint->view,
3437 constraint->hint_x,
3438 constraint->hint_y,
3439 &x, &y);
3440 weston_pointer_move_to(constraint->pointer, x, y);
3441 }
3442 wl_resource_destroy(resource);
3443}
3444
3445static void
3446locked_pointer_set_cursor_position_hint(struct wl_client *client,
3447 struct wl_resource *resource,
3448 wl_fixed_t surface_x,
3449 wl_fixed_t surface_y)
3450{
3451 struct weston_pointer_constraint *constraint =
3452 wl_resource_get_user_data(resource);
3453
3454 /* Ignore a set cursor hint that was sent after the lock was cancelled.
3455 */
3456 if (!constraint ||
3457 !constraint->resource ||
3458 constraint->resource != resource)
3459 return;
3460
3461 constraint->hint_is_pending = true;
3462 constraint->hint_x_pending = surface_x;
3463 constraint->hint_y_pending = surface_y;
3464}
3465
3466static void
3467locked_pointer_set_region(struct wl_client *client,
3468 struct wl_resource *resource,
3469 struct wl_resource *region_resource)
3470{
3471 struct weston_pointer_constraint *constraint =
3472 wl_resource_get_user_data(resource);
3473 struct weston_region *region = region_resource ?
3474 wl_resource_get_user_data(region_resource) : NULL;
3475
3476 if (!constraint)
3477 return;
3478
3479 if (region) {
3480 pixman_region32_copy(&constraint->region_pending,
3481 &region->region);
3482 } else {
3483 pixman_region32_fini(&constraint->region_pending);
3484 region_init_infinite(&constraint->region_pending);
3485 }
3486 constraint->region_is_pending = true;
3487}
3488
3489
3490static const struct zwp_locked_pointer_v1_interface locked_pointer_interface = {
3491 locked_pointer_destroy,
3492 locked_pointer_set_cursor_position_hint,
3493 locked_pointer_set_region,
3494};
3495
3496static void
3497pointer_constraints_lock_pointer(struct wl_client *client,
3498 struct wl_resource *resource,
3499 uint32_t id,
3500 struct wl_resource *surface_resource,
3501 struct wl_resource *pointer_resource,
3502 struct wl_resource *region_resource,
3503 uint32_t lifetime)
3504{
3505 struct weston_surface *surface =
3506 wl_resource_get_user_data(surface_resource);
3507 struct weston_pointer *pointer = wl_resource_get_user_data(pointer_resource);
3508 struct weston_region *region = region_resource ?
3509 wl_resource_get_user_data(region_resource) : NULL;
3510
3511 init_pointer_constraint(resource, id, surface, pointer, region, lifetime,
3512 &zwp_locked_pointer_v1_interface,
3513 &locked_pointer_interface,
3514 &locked_pointer_grab_interface);
3515}
3516
3517static void
3518confined_pointer_grab_pointer_focus(struct weston_pointer_grab *grab)
3519{
3520}
3521
3522static void
3523weston_pointer_clamp_event_to_region(struct weston_pointer *pointer,
3524 struct weston_pointer_motion_event *event,
3525 pixman_region32_t *region,
3526 wl_fixed_t *clamped_x,
3527 wl_fixed_t *clamped_y)
3528{
3529 wl_fixed_t x, y;
3530 wl_fixed_t sx, sy;
3531 wl_fixed_t min_sx = wl_fixed_from_int(region->extents.x1);
3532 wl_fixed_t max_sx = wl_fixed_from_int(region->extents.x2 - 1);
3533 wl_fixed_t max_sy = wl_fixed_from_int(region->extents.y2 - 1);
3534 wl_fixed_t min_sy = wl_fixed_from_int(region->extents.y1);
3535
3536 weston_pointer_motion_to_abs(pointer, event, &x, &y);
3537 weston_view_from_global_fixed(pointer->focus, x, y, &sx, &sy);
3538
3539 if (sx < min_sx)
3540 sx = min_sx;
3541 else if (sx > max_sx)
3542 sx = max_sx;
3543
3544 if (sy < min_sy)
3545 sy = min_sy;
3546 else if (sy > max_sy)
3547 sy = max_sy;
3548
3549 weston_view_to_global_fixed(pointer->focus, sx, sy,
3550 clamped_x, clamped_y);
3551}
3552
3553static void
3554maybe_warp_confined_pointer(struct weston_pointer_constraint *constraint)
3555{
3556 wl_fixed_t x;
3557 wl_fixed_t y;
3558 wl_fixed_t sx;
3559 wl_fixed_t sy;
3560
3561 weston_view_from_global_fixed(constraint->view,
3562 constraint->pointer->x,
3563 constraint->pointer->y,
3564 &sx,
3565 &sy);
3566
3567 if (!is_within_constraint_region(constraint, sx, sy)) {
3568 pixman_region32_t *region = &constraint->region;
3569 wl_fixed_t min_sx = wl_fixed_from_int(region->extents.x1);
3570 wl_fixed_t max_sx = wl_fixed_from_int(region->extents.x2 - 1);
3571 wl_fixed_t max_sy = wl_fixed_from_int(region->extents.y2 - 1);
3572 wl_fixed_t min_sy = wl_fixed_from_int(region->extents.y1);
3573
3574 if (sx < min_sx)
3575 sx = min_sx;
3576 else if (sx > max_sx)
3577 sx = max_sx;
3578
3579 if (sy < min_sy)
3580 sy = min_sy;
3581 else if (sy > max_sy)
3582 sy = max_sy;
3583
3584 weston_view_to_global_fixed(constraint->view, sx, sy, &x, &y);
3585 weston_pointer_move_to(constraint->pointer, x, y);
3586 }
3587}
3588
3589static void
3590confined_pointer_grab_pointer_motion(struct weston_pointer_grab *grab,
3591 uint32_t time,
3592 struct weston_pointer_motion_event *event)
3593{
3594 struct weston_pointer_constraint *constraint =
3595 container_of(grab, struct weston_pointer_constraint, grab);
3596 struct weston_pointer *pointer = grab->pointer;
3597 struct weston_surface *surface;
3598 wl_fixed_t x, y;
3599 wl_fixed_t old_sx = pointer->sx;
3600 wl_fixed_t old_sy = pointer->sy;
3601 pixman_region32_t confine_region;
3602
3603 assert(pointer->focus);
3604 assert(pointer->focus->surface == constraint->surface);
3605
3606 surface = pointer->focus->surface;
3607
3608 pixman_region32_init(&confine_region);
3609 pixman_region32_intersect(&confine_region,
3610 &surface->input,
3611 &constraint->region);
3612 weston_pointer_clamp_event_to_region(pointer, event,
3613 &confine_region, &x, &y);
3614 weston_pointer_move_to(pointer, x, y);
3615 pixman_region32_fini(&confine_region);
3616
3617 weston_view_from_global_fixed(pointer->focus, x, y,
3618 &pointer->sx, &pointer->sy);
3619
3620 if (old_sx != pointer->sx || old_sy != pointer->sy) {
3621 weston_pointer_send_motion(pointer, time,
3622 pointer->sx, pointer->sy);
3623 }
3624
3625 weston_pointer_send_relative_motion(pointer, time, event);
3626}
3627
3628static void
3629confined_pointer_grab_pointer_button(struct weston_pointer_grab *grab,
3630 uint32_t time,
3631 uint32_t button,
3632 uint32_t state_w)
3633{
3634 weston_pointer_send_button(grab->pointer, time, button, state_w);
3635}
3636
3637static void
3638confined_pointer_grab_pointer_axis(struct weston_pointer_grab *grab,
3639 uint32_t time,
3640 struct weston_pointer_axis_event *event)
3641{
3642 weston_pointer_send_axis(grab->pointer, time, event);
3643}
3644
3645static void
3646confined_pointer_grab_pointer_axis_source(struct weston_pointer_grab *grab,
3647 uint32_t source)
3648{
3649 weston_pointer_send_axis_source(grab->pointer, source);
3650}
3651
3652static void
3653confined_pointer_grab_pointer_frame(struct weston_pointer_grab *grab)
3654{
3655 weston_pointer_send_frame(grab->pointer);
3656}
3657
3658static void
3659confined_pointer_grab_pointer_cancel(struct weston_pointer_grab *grab)
3660{
3661 struct weston_pointer_constraint *constraint =
3662 container_of(grab, struct weston_pointer_constraint, grab);
3663
3664 disable_pointer_constraint(constraint);
3665
3666 /* If this is a persistent constraint, re-add the surface destroy signal
3667 * listener only if we are currently not destroying the surface. */
3668 switch (constraint->lifetime) {
3669 case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT:
3670 if (constraint->surface->resource)
3671 wl_signal_add(&constraint->surface->destroy_signal,
3672 &constraint->surface_destroy_listener);
3673 break;
3674 case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT:
3675 break;
3676 }
3677}
3678
3679static const struct weston_pointer_grab_interface
3680 confined_pointer_grab_interface = {
3681 confined_pointer_grab_pointer_focus,
3682 confined_pointer_grab_pointer_motion,
3683 confined_pointer_grab_pointer_button,
3684 confined_pointer_grab_pointer_axis,
3685 confined_pointer_grab_pointer_axis_source,
3686 confined_pointer_grab_pointer_frame,
3687 confined_pointer_grab_pointer_cancel,
3688};
3689
3690static void
3691confined_pointer_destroy(struct wl_client *client,
3692 struct wl_resource *resource)
3693{
3694 wl_resource_destroy(resource);
3695}
3696
3697static void
3698confined_pointer_set_region(struct wl_client *client,
3699 struct wl_resource *resource,
3700 struct wl_resource *region_resource)
3701{
3702 struct weston_pointer_constraint *constraint =
3703 wl_resource_get_user_data(resource);
3704 struct weston_region *region = region_resource ?
3705 wl_resource_get_user_data(region_resource) : NULL;
3706
3707 if (!constraint)
3708 return;
3709
3710 if (region) {
3711 pixman_region32_copy(&constraint->region_pending,
3712 &region->region);
3713 } else {
3714 pixman_region32_fini(&constraint->region_pending);
3715 region_init_infinite(&constraint->region_pending);
3716 }
3717 constraint->region_is_pending = true;
3718}
3719
3720static const struct zwp_confined_pointer_v1_interface confined_pointer_interface = {
3721 confined_pointer_destroy,
3722 confined_pointer_set_region,
3723};
3724
3725static void
3726pointer_constraints_confine_pointer(struct wl_client *client,
3727 struct wl_resource *resource,
3728 uint32_t id,
3729 struct wl_resource *surface_resource,
3730 struct wl_resource *pointer_resource,
3731 struct wl_resource *region_resource,
3732 uint32_t lifetime)
3733{
3734 struct weston_surface *surface =
3735 wl_resource_get_user_data(surface_resource);
3736 struct weston_pointer *pointer = wl_resource_get_user_data(pointer_resource);
3737 struct weston_region *region = region_resource ?
3738 wl_resource_get_user_data(region_resource) : NULL;
3739
3740 init_pointer_constraint(resource, id, surface, pointer, region, lifetime,
3741 &zwp_confined_pointer_v1_interface,
3742 &confined_pointer_interface,
3743 &confined_pointer_grab_interface);
3744}
3745
3746static const struct zwp_pointer_constraints_v1_interface pointer_constraints_interface = {
3747 pointer_constraints_destroy,
3748 pointer_constraints_lock_pointer,
3749 pointer_constraints_confine_pointer,
3750};
3751
3752static void
3753bind_pointer_constraints(struct wl_client *client, void *data,
3754 uint32_t version, uint32_t id)
3755{
3756 struct wl_resource *resource;
3757
3758 resource = wl_resource_create(client,
3759 &zwp_pointer_constraints_v1_interface,
3760 1, id);
3761
3762 wl_resource_set_implementation(resource, &pointer_constraints_interface,
3763 NULL, NULL);
3764}
3765
Jonas Ådahl30d61d82014-10-22 21:21:17 +02003766int
3767weston_input_init(struct weston_compositor *compositor)
3768{
3769 if (!wl_global_create(compositor->wl_display,
3770 &zwp_relative_pointer_manager_v1_interface, 1,
3771 compositor, bind_relative_pointer_manager))
3772 return -1;
3773
Jonas Ådahld3414f22016-07-22 17:56:31 +08003774 if (!wl_global_create(compositor->wl_display,
3775 &zwp_pointer_constraints_v1_interface, 1,
3776 NULL, bind_pointer_constraints))
3777 return -1;
3778
Jonas Ådahl30d61d82014-10-22 21:21:17 +02003779 return 0;
3780}