blob: 81a94a929f2ed9e487c3aed6466265e6affd665c [file] [log] [blame]
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001/*
2 * Copyright © 2013 Intel Corporation
3 *
Bryce Harringtona0bbfea2015-06-11 15:35:43 -07004 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
Kristian Høgsberg2158a882013-04-18 15:07:39 -040011 *
Bryce Harringtona0bbfea2015-06-11 15:35:43 -070012 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial
14 * portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
Kristian Høgsberg2158a882013-04-18 15:07:39 -040024 */
25
Daniel Stone8e7a8bd2013-08-15 01:10:24 +010026#include "config.h"
27
Jonas Ådahld3414f22016-07-22 17:56:31 +080028#include <stdbool.h>
Kristian Høgsberg2158a882013-04-18 15:07:39 -040029#include <stdlib.h>
30#include <stdint.h>
31#include <string.h>
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040032#include <sys/mman.h>
33#include <assert.h>
34#include <unistd.h>
Jonas Ådahld0be2bb2015-04-30 17:56:37 +080035#include <values.h>
Matt Roper01a92732013-06-24 16:52:44 +010036#include <fcntl.h>
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +020037#include <limits.h>
Kristian Høgsberg2158a882013-04-18 15:07:39 -040038
Jon Cruz35b2eaa2015-06-15 15:37:08 -070039#include "shared/helpers.h"
Jon Cruz4678bab2015-06-15 15:37:07 -070040#include "shared/os-compatibility.h"
Kristian Høgsberg2158a882013-04-18 15:07:39 -040041#include "compositor.h"
Daniel Stone7dbb0e12016-11-24 15:30:41 +000042#include "relative-pointer-unstable-v1-server-protocol.h"
43#include "pointer-constraints-unstable-v1-server-protocol.h"
Jonas Ådahld3414f22016-07-22 17:56:31 +080044
45enum pointer_constraint_type {
46 POINTER_CONSTRAINT_TYPE_LOCK,
47 POINTER_CONSTRAINT_TYPE_CONFINE,
48};
49
Jonas Ådahld0be2bb2015-04-30 17:56:37 +080050enum motion_direction {
51 MOTION_DIRECTION_POSITIVE_X = 1 << 0,
52 MOTION_DIRECTION_NEGATIVE_X = 1 << 1,
53 MOTION_DIRECTION_POSITIVE_Y = 1 << 2,
54 MOTION_DIRECTION_NEGATIVE_Y = 1 << 3,
55};
56
57struct vec2d {
58 double x, y;
59};
60
61struct line {
62 struct vec2d a;
63 struct vec2d b;
64};
65
66struct border {
67 struct line line;
68 enum motion_direction blocking_dir;
69};
70
Jonas Ådahld3414f22016-07-22 17:56:31 +080071static void
72maybe_warp_confined_pointer(struct weston_pointer_constraint *constraint);
Kristian Høgsberg2158a882013-04-18 15:07:39 -040073
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040074static void
75empty_region(pixman_region32_t *region)
76{
77 pixman_region32_fini(region);
78 pixman_region32_init(region);
79}
80
Jonas Ådahld3414f22016-07-22 17:56:31 +080081static void
82region_init_infinite(pixman_region32_t *region)
83{
84 pixman_region32_init_rect(region, INT32_MIN, INT32_MIN,
85 UINT32_MAX, UINT32_MAX);
86}
87
Jonas Ådahl2cbf2932015-07-22 12:05:38 +080088static struct weston_pointer_client *
89weston_pointer_client_create(struct wl_client *client)
90{
91 struct weston_pointer_client *pointer_client;
92
93 pointer_client = zalloc(sizeof *pointer_client);
94 if (!pointer_client)
95 return NULL;
96
97 pointer_client->client = client;
98 wl_list_init(&pointer_client->pointer_resources);
Jonas Ådahl30d61d82014-10-22 21:21:17 +020099 wl_list_init(&pointer_client->relative_pointer_resources);
Jonas Ådahl2cbf2932015-07-22 12:05:38 +0800100
101 return pointer_client;
102}
103
104static void
105weston_pointer_client_destroy(struct weston_pointer_client *pointer_client)
106{
107 free(pointer_client);
108}
109
110static bool
111weston_pointer_client_is_empty(struct weston_pointer_client *pointer_client)
112{
Jonas Ådahl30d61d82014-10-22 21:21:17 +0200113 return (wl_list_empty(&pointer_client->pointer_resources) &&
114 wl_list_empty(&pointer_client->relative_pointer_resources));
Jonas Ådahl2cbf2932015-07-22 12:05:38 +0800115}
116
117static struct weston_pointer_client *
118weston_pointer_get_pointer_client(struct weston_pointer *pointer,
119 struct wl_client *client)
120{
121 struct weston_pointer_client *pointer_client;
122
123 wl_list_for_each(pointer_client, &pointer->pointer_clients, link) {
124 if (pointer_client->client == client)
125 return pointer_client;
126 }
127
128 return NULL;
129}
130
131static struct weston_pointer_client *
132weston_pointer_ensure_pointer_client(struct weston_pointer *pointer,
133 struct wl_client *client)
134{
135 struct weston_pointer_client *pointer_client;
136
137 pointer_client = weston_pointer_get_pointer_client(pointer, client);
138 if (pointer_client)
139 return pointer_client;
140
141 pointer_client = weston_pointer_client_create(client);
142 wl_list_insert(&pointer->pointer_clients, &pointer_client->link);
143
144 if (pointer->focus &&
145 pointer->focus->surface->resource &&
146 wl_resource_get_client(pointer->focus->surface->resource) == client) {
147 pointer->focus_client = pointer_client;
148 }
149
150 return pointer_client;
151}
152
153static void
154weston_pointer_cleanup_pointer_client(struct weston_pointer *pointer,
155 struct weston_pointer_client *pointer_client)
156{
157 if (weston_pointer_client_is_empty(pointer_client)) {
158 if (pointer->focus_client == pointer_client)
159 pointer->focus_client = NULL;
160 wl_list_remove(&pointer_client->link);
161 weston_pointer_client_destroy(pointer_client);
162 }
163}
164
165static void
166unbind_pointer_client_resource(struct wl_resource *resource)
167{
168 struct weston_pointer *pointer = wl_resource_get_user_data(resource);
169 struct wl_client *client = wl_resource_get_client(resource);
170 struct weston_pointer_client *pointer_client;
171
172 pointer_client = weston_pointer_get_pointer_client(pointer, client);
173 assert(pointer_client);
174
175 wl_list_remove(wl_resource_get_link(resource));
176 weston_pointer_cleanup_pointer_client(pointer, pointer_client);
177}
178
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400179static void unbind_resource(struct wl_resource *resource)
180{
Jason Ekstrand44a38632013-06-14 10:08:00 -0500181 wl_list_remove(wl_resource_get_link(resource));
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400182}
183
Jonas Ådahl3042ffe2013-10-17 23:04:08 +0200184WL_EXPORT void
Jonas Ådahl30d61d82014-10-22 21:21:17 +0200185weston_pointer_motion_to_abs(struct weston_pointer *pointer,
186 struct weston_pointer_motion_event *event,
187 wl_fixed_t *x, wl_fixed_t *y)
188{
189 if (event->mask & WESTON_POINTER_MOTION_ABS) {
190 *x = wl_fixed_from_double(event->x);
191 *y = wl_fixed_from_double(event->y);
192 } else if (event->mask & WESTON_POINTER_MOTION_REL) {
193 *x = pointer->x + wl_fixed_from_double(event->dx);
194 *y = pointer->y + wl_fixed_from_double(event->dy);
195 } else {
196 assert(!"invalid motion event");
197 *x = *y = 0;
198 }
199}
200
201static bool
202weston_pointer_motion_to_rel(struct weston_pointer *pointer,
203 struct weston_pointer_motion_event *event,
204 double *dx, double *dy,
205 double *dx_unaccel, double *dy_unaccel)
206{
207 if (event->mask & WESTON_POINTER_MOTION_REL &&
208 event->mask & WESTON_POINTER_MOTION_REL_UNACCEL) {
209 *dx = event->dx;
210 *dy = event->dy;
211 *dx_unaccel = event->dx_unaccel;
212 *dy_unaccel = event->dy_unaccel;
213 return true;
214 } else if (event->mask & WESTON_POINTER_MOTION_REL) {
215 *dx_unaccel = *dx = event->dx;
216 *dy_unaccel = *dy = event->dy;
217 return true;
218 } else if (event->mask & WESTON_POINTER_MOTION_REL_UNACCEL) {
219 *dx_unaccel = *dx = event->dx_unaccel;
220 *dy_unaccel = *dy = event->dy_unaccel;
221 return true;
222 } else {
223 return false;
224 }
225}
226
227WL_EXPORT void
Kristian Høgsberga71e8b22013-05-06 21:51:21 -0400228weston_seat_repick(struct weston_seat *seat)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400229{
Derek Foreman1281a362015-07-31 16:55:32 -0500230 const struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400231
Derek Foreman1b786ee2015-06-03 15:53:23 -0500232 if (!pointer)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400233 return;
234
Derek Foreman1b786ee2015-06-03 15:53:23 -0500235 pointer->grab->interface->focus(pointer->grab);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400236}
237
238static void
239weston_compositor_idle_inhibit(struct weston_compositor *compositor)
240{
241 weston_compositor_wake(compositor);
242 compositor->idle_inhibit++;
243}
244
245static void
246weston_compositor_idle_release(struct weston_compositor *compositor)
247{
248 compositor->idle_inhibit--;
249 weston_compositor_wake(compositor);
250}
251
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400252static void
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100253pointer_focus_view_destroyed(struct wl_listener *listener, void *data)
254{
255 struct weston_pointer *pointer =
256 container_of(listener, struct weston_pointer,
257 focus_view_listener);
258
Derek Foremanf9318d12015-05-11 15:40:11 -0500259 weston_pointer_clear_focus(pointer);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100260}
261
262static void
263pointer_focus_resource_destroyed(struct wl_listener *listener, void *data)
264{
265 struct weston_pointer *pointer =
266 container_of(listener, struct weston_pointer,
267 focus_resource_listener);
268
Derek Foremanf9318d12015-05-11 15:40:11 -0500269 weston_pointer_clear_focus(pointer);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100270}
271
272static void
273keyboard_focus_resource_destroyed(struct wl_listener *listener, void *data)
274{
275 struct weston_keyboard *keyboard =
276 container_of(listener, struct weston_keyboard,
277 focus_resource_listener);
278
279 weston_keyboard_set_focus(keyboard, NULL);
280}
281
282static void
283touch_focus_view_destroyed(struct wl_listener *listener, void *data)
284{
285 struct weston_touch *touch =
286 container_of(listener, struct weston_touch,
287 focus_view_listener);
288
Derek Foreman4c93c082015-04-30 16:45:41 -0500289 weston_touch_set_focus(touch, NULL);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100290}
291
292static void
293touch_focus_resource_destroyed(struct wl_listener *listener, void *data)
294{
295 struct weston_touch *touch =
296 container_of(listener, struct weston_touch,
297 focus_resource_listener);
298
Derek Foreman4c93c082015-04-30 16:45:41 -0500299 weston_touch_set_focus(touch, NULL);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100300}
301
302static void
Neil Roberts96d790e2013-09-19 17:32:00 +0100303move_resources(struct wl_list *destination, struct wl_list *source)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400304{
Neil Roberts96d790e2013-09-19 17:32:00 +0100305 wl_list_insert_list(destination, source);
306 wl_list_init(source);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400307}
308
309static void
Neil Roberts96d790e2013-09-19 17:32:00 +0100310move_resources_for_client(struct wl_list *destination,
311 struct wl_list *source,
312 struct wl_client *client)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400313{
Neil Roberts96d790e2013-09-19 17:32:00 +0100314 struct wl_resource *resource, *tmp;
315 wl_resource_for_each_safe(resource, tmp, source) {
316 if (wl_resource_get_client(resource) == client) {
317 wl_list_remove(wl_resource_get_link(resource));
318 wl_list_insert(destination,
319 wl_resource_get_link(resource));
320 }
321 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400322}
323
324static void
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700325default_grab_pointer_focus(struct weston_pointer_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400326{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400327 struct weston_pointer *pointer = grab->pointer;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500328 struct weston_view *view;
Kristian Høgsberg6848c252013-05-08 22:02:59 -0400329 wl_fixed_t sx, sy;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400330
331 if (pointer->button_count > 0)
332 return;
333
Jason Ekstranda7af7042013-10-12 22:38:11 -0500334 view = weston_compositor_pick_view(pointer->seat->compositor,
335 pointer->x, pointer->y,
336 &sx, &sy);
Kristian Høgsberg6848c252013-05-08 22:02:59 -0400337
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -0800338 if (pointer->focus != view || pointer->sx != sx || pointer->sy != sy)
Jason Ekstranda7af7042013-10-12 22:38:11 -0500339 weston_pointer_set_focus(pointer, view, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400340}
341
342static void
Quentin Glidiccde13452016-08-12 10:41:32 +0200343pointer_send_relative_motion(struct weston_pointer *pointer,
344 uint32_t time,
345 struct weston_pointer_motion_event *event)
Jonas Ådahl30d61d82014-10-22 21:21:17 +0200346{
347 uint64_t time_usec;
348 double dx, dy, dx_unaccel, dy_unaccel;
349 wl_fixed_t dxf, dyf, dxf_unaccel, dyf_unaccel;
350 struct wl_list *resource_list;
351 struct wl_resource *resource;
352
353 if (!pointer->focus_client)
354 return;
355
356 if (!weston_pointer_motion_to_rel(pointer, event,
357 &dx, &dy,
358 &dx_unaccel, &dy_unaccel))
359 return;
360
361 resource_list = &pointer->focus_client->relative_pointer_resources;
362 time_usec = event->time_usec;
363 if (time_usec == 0)
364 time_usec = time * 1000ULL;
365
366 dxf = wl_fixed_from_double(dx);
367 dyf = wl_fixed_from_double(dy);
368 dxf_unaccel = wl_fixed_from_double(dx_unaccel);
369 dyf_unaccel = wl_fixed_from_double(dy_unaccel);
370
371 wl_resource_for_each(resource, resource_list) {
372 zwp_relative_pointer_v1_send_relative_motion(
373 resource,
374 (uint32_t) (time_usec >> 32),
375 (uint32_t) time_usec,
376 dxf, dyf,
377 dxf_unaccel, dyf_unaccel);
378 }
379}
380
381static void
Quentin Glidiccde13452016-08-12 10:41:32 +0200382pointer_send_motion(struct weston_pointer *pointer, uint32_t time,
383 wl_fixed_t sx, wl_fixed_t sy)
Jonas Ådahlf44942e2016-07-22 17:54:55 +0800384{
385 struct wl_list *resource_list;
386 struct wl_resource *resource;
387
388 if (!pointer->focus_client)
389 return;
390
391 resource_list = &pointer->focus_client->pointer_resources;
392 wl_resource_for_each(resource, resource_list)
393 wl_pointer_send_motion(resource, time, sx, sy);
394}
395
Quentin Glidiccde13452016-08-12 10:41:32 +0200396WL_EXPORT void
397weston_pointer_send_motion(struct weston_pointer *pointer, uint32_t time,
398 struct weston_pointer_motion_event *event)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400399{
Jonas Ådahld2510102014-10-05 21:39:14 +0200400 wl_fixed_t x, y;
Jonas Ådahl8283c342015-04-24 15:26:17 +0800401 wl_fixed_t old_sx = pointer->sx;
402 wl_fixed_t old_sy = pointer->sy;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400403
Jonas Ådahld2510102014-10-05 21:39:14 +0200404 if (pointer->focus) {
405 weston_pointer_motion_to_abs(pointer, event, &x, &y);
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -0800406 weston_view_from_global_fixed(pointer->focus, x, y,
407 &pointer->sx, &pointer->sy);
Jonas Ådahld2510102014-10-05 21:39:14 +0200408 }
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -0800409
Jonas Ådahld2510102014-10-05 21:39:14 +0200410 weston_pointer_move(pointer, event);
Giulio Camuffo1959ab82013-11-14 23:42:52 +0100411
Jonas Ådahlf44942e2016-07-22 17:54:55 +0800412 if (old_sx != pointer->sx || old_sy != pointer->sy) {
Quentin Glidiccde13452016-08-12 10:41:32 +0200413 pointer_send_motion(pointer, time,
414 pointer->sx, pointer->sy);
Kristian Høgsbergbe6403e2013-05-08 21:03:21 -0400415 }
Jonas Ådahl30d61d82014-10-22 21:21:17 +0200416
Quentin Glidiccde13452016-08-12 10:41:32 +0200417 pointer_send_relative_motion(pointer, time, event);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400418}
419
420static void
Quentin Glidiccde13452016-08-12 10:41:32 +0200421default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time,
422 struct weston_pointer_motion_event *event)
423{
424 weston_pointer_send_motion(grab->pointer, time, event);
425}
426
427/** Check if the pointer has focused resources.
428 *
429 * \param pointer The pointer to check for focused resources.
430 * \return Whether or not this pointer has focused resources
431 */
432WL_EXPORT bool
433weston_pointer_has_focus_resource(struct weston_pointer *pointer)
434{
435 if (!pointer->focus_client)
436 return false;
437
438 if (wl_list_empty(&pointer->focus_client->pointer_resources))
439 return false;
440
441 return true;
442}
443
444/** Send wl_pointer.button events to focused resources.
445 *
446 * \param pointer The pointer where the button events originates from.
447 * \param time The timestamp of the event
448 * \param button The button value of the event
449 * \param value The state enum value of the event
450 *
451 * For every resource that is currently in focus, send a wl_pointer.button event
452 * with the passed parameters. The focused resources are the wl_pointer
453 * resources of the client which currently has the surface with pointer focus.
454 */
455WL_EXPORT void
Jonas Ådahlc02ac112016-07-22 17:55:43 +0800456weston_pointer_send_button(struct weston_pointer *pointer,
Quentin Glidiccde13452016-08-12 10:41:32 +0200457 uint32_t time, uint32_t button,
458 enum wl_pointer_button_state state)
Jonas Ådahlc02ac112016-07-22 17:55:43 +0800459{
460 struct wl_display *display = pointer->seat->compositor->wl_display;
461 struct wl_list *resource_list;
462 struct wl_resource *resource;
463 uint32_t serial;
464
Quentin Glidiccde13452016-08-12 10:41:32 +0200465 if (!weston_pointer_has_focus_resource(pointer))
Jonas Ådahlc02ac112016-07-22 17:55:43 +0800466 return;
467
468 resource_list = &pointer->focus_client->pointer_resources;
Quentin Glidiccde13452016-08-12 10:41:32 +0200469 serial = wl_display_next_serial(display);
470 wl_resource_for_each(resource, resource_list)
471 wl_pointer_send_button(resource, serial, time, button, state);
Jonas Ådahlc02ac112016-07-22 17:55:43 +0800472}
473
474static void
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700475default_grab_pointer_button(struct weston_pointer_grab *grab,
Quentin Glidiccde13452016-08-12 10:41:32 +0200476 uint32_t time, uint32_t button,
477 enum wl_pointer_button_state state)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400478{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400479 struct weston_pointer *pointer = grab->pointer;
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400480 struct weston_compositor *compositor = pointer->seat->compositor;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500481 struct weston_view *view;
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400482 wl_fixed_t sx, sy;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400483
Quentin Glidiccde13452016-08-12 10:41:32 +0200484 weston_pointer_send_button(pointer, time, button, state);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400485
486 if (pointer->button_count == 0 &&
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400487 state == WL_POINTER_BUTTON_STATE_RELEASED) {
Jason Ekstranda7af7042013-10-12 22:38:11 -0500488 view = weston_compositor_pick_view(compositor,
489 pointer->x, pointer->y,
490 &sx, &sy);
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400491
Jason Ekstranda7af7042013-10-12 22:38:11 -0500492 weston_pointer_set_focus(pointer, view, sx, sy);
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400493 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400494}
495
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200496/** Send wl_pointer.axis events to focused resources.
497 *
498 * \param pointer The pointer where the axis events originates from.
499 * \param time The timestamp of the event
500 * \param axis The axis enum value of the event
501 * \param value The axis value of the event
502 *
503 * For every resource that is currently in focus, send a wl_pointer.axis event
504 * with the passed parameters. The focused resources are the wl_pointer
505 * resources of the client which currently has the surface with pointer focus.
506 */
507WL_EXPORT void
508weston_pointer_send_axis(struct weston_pointer *pointer,
Peter Hutterer89b6a492016-01-18 15:58:17 +1000509 uint32_t time,
510 struct weston_pointer_axis_event *event)
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200511{
512 struct wl_resource *resource;
513 struct wl_list *resource_list;
514
Quentin Glidiccde13452016-08-12 10:41:32 +0200515 if (!weston_pointer_has_focus_resource(pointer))
Jonas Ådahl2cbf2932015-07-22 12:05:38 +0800516 return;
517
518 resource_list = &pointer->focus_client->pointer_resources;
Peter Hutterer87743e92016-01-18 16:38:22 +1000519 wl_resource_for_each(resource, resource_list) {
520 if (event->has_discrete &&
521 wl_resource_get_version(resource) >=
522 WL_POINTER_AXIS_DISCRETE_SINCE_VERSION)
523 wl_pointer_send_axis_discrete(resource, event->axis,
524 event->discrete);
525
526 if (event->value)
527 wl_pointer_send_axis(resource, time,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +0200528 event->axis,
529 wl_fixed_from_double(event->value));
Peter Hutterer87743e92016-01-18 16:38:22 +1000530 else if (wl_resource_get_version(resource) >=
531 WL_POINTER_AXIS_STOP_SINCE_VERSION)
532 wl_pointer_send_axis_stop(resource, time,
533 event->axis);
534 }
535}
536
Quentin Glidiccde13452016-08-12 10:41:32 +0200537/** Send wl_pointer.axis_source events to focused resources.
538 *
539 * \param pointer The pointer where the axis_source events originates from.
540 * \param source The axis_source enum value of the event
541 *
542 * For every resource that is currently in focus, send a wl_pointer.axis_source
543 * event with the passed parameter. The focused resources are the wl_pointer
544 * resources of the client which currently has the surface with pointer focus.
545 */
Peter Hutterer87743e92016-01-18 16:38:22 +1000546WL_EXPORT void
Quentin Glidiccde13452016-08-12 10:41:32 +0200547weston_pointer_send_axis_source(struct weston_pointer *pointer,
548 enum wl_pointer_axis_source source)
Peter Hutterer87743e92016-01-18 16:38:22 +1000549{
550 struct wl_resource *resource;
551 struct wl_list *resource_list;
552
Quentin Glidiccde13452016-08-12 10:41:32 +0200553 if (!weston_pointer_has_focus_resource(pointer))
Jonas Ådahled6014a2016-04-21 10:21:48 +0800554 return;
555
Peter Hutterer87743e92016-01-18 16:38:22 +1000556 resource_list = &pointer->focus_client->pointer_resources;
557 wl_resource_for_each(resource, resource_list) {
558 if (wl_resource_get_version(resource) >=
559 WL_POINTER_AXIS_SOURCE_SINCE_VERSION) {
560 wl_pointer_send_axis_source(resource, source);
561 }
562 }
563}
564
565static void
566pointer_send_frame(struct wl_resource *resource)
567{
568 if (wl_resource_get_version(resource) >=
569 WL_POINTER_FRAME_SINCE_VERSION) {
570 wl_pointer_send_frame(resource);
571 }
572}
573
Quentin Glidiccde13452016-08-12 10:41:32 +0200574/** Send wl_pointer.frame events to focused resources.
575 *
576 * \param pointer The pointer where the frame events originates from.
577 *
578 * For every resource that is currently in focus, send a wl_pointer.frame event.
579 * The focused resources are the wl_pointer resources of the client which
580 * currently has the surface with pointer focus.
581 */
Peter Hutterer87743e92016-01-18 16:38:22 +1000582WL_EXPORT void
583weston_pointer_send_frame(struct weston_pointer *pointer)
584{
585 struct wl_resource *resource;
586 struct wl_list *resource_list;
587
Quentin Glidiccde13452016-08-12 10:41:32 +0200588 if (!weston_pointer_has_focus_resource(pointer))
Derek Foreman8efa31b2016-01-29 10:29:46 -0600589 return;
590
Peter Hutterer87743e92016-01-18 16:38:22 +1000591 resource_list = &pointer->focus_client->pointer_resources;
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200592 wl_resource_for_each(resource, resource_list)
Peter Hutterer87743e92016-01-18 16:38:22 +1000593 pointer_send_frame(resource);
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200594}
595
596static void
597default_grab_pointer_axis(struct weston_pointer_grab *grab,
Peter Hutterer89b6a492016-01-18 15:58:17 +1000598 uint32_t time,
599 struct weston_pointer_axis_event *event)
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200600{
Peter Hutterer89b6a492016-01-18 15:58:17 +1000601 weston_pointer_send_axis(grab->pointer, time, event);
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200602}
603
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200604static void
Peter Hutterer87743e92016-01-18 16:38:22 +1000605default_grab_pointer_axis_source(struct weston_pointer_grab *grab,
Quentin Glidiccde13452016-08-12 10:41:32 +0200606 enum wl_pointer_axis_source source)
Peter Hutterer87743e92016-01-18 16:38:22 +1000607{
608 weston_pointer_send_axis_source(grab->pointer, source);
609}
610
611static void
612default_grab_pointer_frame(struct weston_pointer_grab *grab)
613{
614 weston_pointer_send_frame(grab->pointer);
615}
616
617static void
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200618default_grab_pointer_cancel(struct weston_pointer_grab *grab)
619{
620}
621
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400622static const struct weston_pointer_grab_interface
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400623 default_pointer_grab_interface = {
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700624 default_grab_pointer_focus,
625 default_grab_pointer_motion,
626 default_grab_pointer_button,
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200627 default_grab_pointer_axis,
Peter Hutterer87743e92016-01-18 16:38:22 +1000628 default_grab_pointer_axis_source,
629 default_grab_pointer_frame,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200630 default_grab_pointer_cancel,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400631};
632
Quentin Glidiccde13452016-08-12 10:41:32 +0200633/** Check if the touch has focused resources.
634 *
635 * \param touch The touch to check for focused resources.
636 * \return Whether or not this touch has focused resources
637 */
638WL_EXPORT bool
639weston_touch_has_focus_resource(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400640{
Quentin Glidiccde13452016-08-12 10:41:32 +0200641 if (!touch->focus)
642 return false;
643
644 if (wl_list_empty(&touch->focus_resource_list))
645 return false;
646
647 return true;
648}
649
650/** Send wl_touch.down events to focused resources.
651 *
652 * \param touch The touch where the down events originates from.
653 * \param time The timestamp of the event
654 * \param touch_id The touch_id value of the event
655 * \param x The x value of the event
656 * \param y The y value of the event
657 *
658 * For every resource that is currently in focus, send a wl_touch.down event
659 * with the passed parameters. The focused resources are the wl_touch
660 * resources of the client which currently has the surface with touch focus.
661 */
662WL_EXPORT void
663weston_touch_send_down(struct weston_touch *touch, uint32_t time,
664 int touch_id, wl_fixed_t x, wl_fixed_t y)
665{
Rob Bradford880ebc72013-07-22 17:31:38 +0100666 struct wl_display *display = touch->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400667 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +0100668 struct wl_resource *resource;
669 struct wl_list *resource_list;
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300670 wl_fixed_t sx, sy;
671
Quentin Glidiccde13452016-08-12 10:41:32 +0200672 if (!weston_touch_has_focus_resource(touch))
Bryce Harrington2c40d1d2016-02-02 10:18:48 -0800673 return;
674
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300675 weston_view_from_global_fixed(touch->focus, x, y, &sx, &sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400676
Neil Roberts96d790e2013-09-19 17:32:00 +0100677 resource_list = &touch->focus_resource_list;
Quentin Glidiccde13452016-08-12 10:41:32 +0200678 serial = wl_display_next_serial(display);
679 wl_resource_for_each(resource, resource_list)
680 wl_touch_send_down(resource, serial, time,
681 touch->focus->surface->resource,
682 touch_id, sx, sy);
683}
Neil Roberts96d790e2013-09-19 17:32:00 +0100684
Quentin Glidiccde13452016-08-12 10:41:32 +0200685static void
686default_grab_touch_down(struct weston_touch_grab *grab, uint32_t time,
687 int touch_id, wl_fixed_t x, wl_fixed_t y)
688{
689 weston_touch_send_down(grab->touch, time, touch_id, x, y);
690}
691
692/** Send wl_touch.up events to focused resources.
693 *
694 * \param touch The touch where the up events originates from.
695 * \param time The timestamp of the event
696 * \param touch_id The touch_id value of the event
697 *
698 * For every resource that is currently in focus, send a wl_touch.up event
699 * with the passed parameters. The focused resources are the wl_touch
700 * resources of the client which currently has the surface with touch focus.
701 */
702WL_EXPORT void
703weston_touch_send_up(struct weston_touch *touch, uint32_t time, int touch_id)
704{
705 struct wl_display *display = touch->seat->compositor->wl_display;
706 uint32_t serial;
707 struct wl_resource *resource;
708 struct wl_list *resource_list;
709
710 if (!weston_touch_has_focus_resource(touch))
711 return;
712
713 resource_list = &touch->focus_resource_list;
714 serial = wl_display_next_serial(display);
715 wl_resource_for_each(resource, resource_list)
716 wl_touch_send_up(resource, serial, time, touch_id);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400717}
718
Kristian Høgsberge329f362013-05-06 22:19:57 -0400719static void
720default_grab_touch_up(struct weston_touch_grab *grab,
721 uint32_t time, int touch_id)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400722{
Quentin Glidiccde13452016-08-12 10:41:32 +0200723 weston_touch_send_up(grab->touch, time, touch_id);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400724}
725
Quentin Glidiccde13452016-08-12 10:41:32 +0200726/** Send wl_touch.motion events to focused resources.
727 *
728 * \param touch The touch where the motion events originates from.
729 * \param time The timestamp of the event
730 * \param touch_id The touch_id value of the event
731 * \param x The x value of the event
732 * \param y The y value of the event
733 *
734 * For every resource that is currently in focus, send a wl_touch.motion event
735 * with the passed parameters. The focused resources are the wl_touch
736 * resources of the client which currently has the surface with touch focus.
737 */
738WL_EXPORT void
739weston_touch_send_motion(struct weston_touch *touch, uint32_t time,
740 int touch_id, wl_fixed_t x, wl_fixed_t y)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400741{
Neil Roberts96d790e2013-09-19 17:32:00 +0100742 struct wl_resource *resource;
743 struct wl_list *resource_list;
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300744 wl_fixed_t sx, sy;
745
Quentin Glidiccde13452016-08-12 10:41:32 +0200746 if (!weston_touch_has_focus_resource(touch))
747 return;
748
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300749 weston_view_from_global_fixed(touch->focus, x, y, &sx, &sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400750
Neil Roberts96d790e2013-09-19 17:32:00 +0100751 resource_list = &touch->focus_resource_list;
Neil Roberts96d790e2013-09-19 17:32:00 +0100752 wl_resource_for_each(resource, resource_list) {
753 wl_touch_send_motion(resource, time,
Kristian Høgsberge329f362013-05-06 22:19:57 -0400754 touch_id, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400755 }
756}
757
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200758static void
Quentin Glidiccde13452016-08-12 10:41:32 +0200759default_grab_touch_motion(struct weston_touch_grab *grab, uint32_t time,
760 int touch_id, wl_fixed_t x, wl_fixed_t y)
761{
762 weston_touch_send_motion(grab->touch, time, touch_id, x, y);
763}
764
765
766/** Send wl_touch.frame events to focused resources.
767 *
768 * \param touch The touch where the frame events originates from.
769 *
770 * For every resource that is currently in focus, send a wl_touch.frame event.
771 * The focused resources are the wl_touch resources of the client which
772 * currently has the surface with touch focus.
773 */
774WL_EXPORT void
775weston_touch_send_frame(struct weston_touch *touch)
Jonas Ådahl1679f232014-04-12 09:39:51 +0200776{
777 struct wl_resource *resource;
778
Quentin Glidiccde13452016-08-12 10:41:32 +0200779 if (!weston_touch_has_focus_resource(touch))
780 return;
781
782 wl_resource_for_each(resource, &touch->focus_resource_list)
Jonas Ådahl1679f232014-04-12 09:39:51 +0200783 wl_touch_send_frame(resource);
784}
785
786static void
Quentin Glidiccde13452016-08-12 10:41:32 +0200787default_grab_touch_frame(struct weston_touch_grab *grab)
788{
789 weston_touch_send_frame(grab->touch);
790}
791
792static void
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200793default_grab_touch_cancel(struct weston_touch_grab *grab)
794{
795}
796
Kristian Høgsberge329f362013-05-06 22:19:57 -0400797static const struct weston_touch_grab_interface default_touch_grab_interface = {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400798 default_grab_touch_down,
799 default_grab_touch_up,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200800 default_grab_touch_motion,
Jonas Ådahl1679f232014-04-12 09:39:51 +0200801 default_grab_touch_frame,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200802 default_grab_touch_cancel,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400803};
804
Quentin Glidiccde13452016-08-12 10:41:32 +0200805/** Check if the keyboard has focused resources.
806 *
807 * \param keyboard The keyboard to check for focused resources.
808 * \return Whether or not this keyboard has focused resources
809 */
810WL_EXPORT bool
811weston_keyboard_has_focus_resource(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400812{
Quentin Glidiccde13452016-08-12 10:41:32 +0200813 if (!keyboard->focus)
814 return false;
815
816 if (wl_list_empty(&keyboard->focus_resource_list))
817 return false;
818
819 return true;
820}
821
822/** Send wl_keyboard.key events to focused resources.
823 *
824 * \param keyboard The keyboard where the key events originates from.
825 * \param time The timestamp of the event
826 * \param key The key value of the event
827 * \param state The state enum value of the event
828 *
829 * For every resource that is currently in focus, send a wl_keyboard.key event
830 * with the passed parameters. The focused resources are the wl_keyboard
831 * resources of the client which currently has the surface with keyboard focus.
832 */
833WL_EXPORT void
834weston_keyboard_send_key(struct weston_keyboard *keyboard,
835 uint32_t time, uint32_t key,
836 enum wl_keyboard_key_state state)
837{
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400838 struct wl_resource *resource;
Rob Bradford880ebc72013-07-22 17:31:38 +0100839 struct wl_display *display = keyboard->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400840 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +0100841 struct wl_list *resource_list;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400842
Quentin Glidiccde13452016-08-12 10:41:32 +0200843 if (!weston_keyboard_has_focus_resource(keyboard))
844 return;
845
Neil Roberts96d790e2013-09-19 17:32:00 +0100846 resource_list = &keyboard->focus_resource_list;
Quentin Glidiccde13452016-08-12 10:41:32 +0200847 serial = wl_display_next_serial(display);
848 wl_resource_for_each(resource, resource_list)
849 wl_keyboard_send_key(resource, serial, time, key, state);
850};
851
852static void
853default_grab_keyboard_key(struct weston_keyboard_grab *grab,
854 uint32_t time, uint32_t key, uint32_t state)
855{
856 weston_keyboard_send_key(grab->keyboard, time, key, state);
Neil Roberts96d790e2013-09-19 17:32:00 +0100857}
858
859static void
860send_modifiers_to_resource(struct weston_keyboard *keyboard,
861 struct wl_resource *resource,
862 uint32_t serial)
863{
864 wl_keyboard_send_modifiers(resource,
865 serial,
866 keyboard->modifiers.mods_depressed,
867 keyboard->modifiers.mods_latched,
868 keyboard->modifiers.mods_locked,
869 keyboard->modifiers.group);
870}
871
872static void
873send_modifiers_to_client_in_list(struct wl_client *client,
874 struct wl_list *list,
875 uint32_t serial,
876 struct weston_keyboard *keyboard)
877{
878 struct wl_resource *resource;
879
880 wl_resource_for_each(resource, list) {
881 if (wl_resource_get_client(resource) == client)
882 send_modifiers_to_resource(keyboard,
883 resource,
884 serial);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400885 }
886}
887
Jonas Ådahl2cbf2932015-07-22 12:05:38 +0800888static struct weston_pointer_client *
889find_pointer_client_for_surface(struct weston_pointer *pointer,
890 struct weston_surface *surface)
891{
892 struct wl_client *client;
893
894 if (!surface)
895 return NULL;
896
897 if (!surface->resource)
898 return NULL;
899
900 client = wl_resource_get_client(surface->resource);
901 return weston_pointer_get_pointer_client(pointer, client);
902}
903
904static struct weston_pointer_client *
905find_pointer_client_for_view(struct weston_pointer *pointer, struct weston_view *view)
906{
907 if (!view)
908 return NULL;
909
910 return find_pointer_client_for_surface(pointer, view->surface);
911}
912
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400913static struct wl_resource *
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400914find_resource_for_surface(struct wl_list *list, struct weston_surface *surface)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400915{
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400916 if (!surface)
917 return NULL;
918
Jason Ekstrand44a38632013-06-14 10:08:00 -0500919 if (!surface->resource)
920 return NULL;
Stefan Schmidtfda26522013-09-17 10:54:09 +0100921
Jason Ekstrand44a38632013-06-14 10:08:00 -0500922 return wl_resource_find_for_client(list, wl_resource_get_client(surface->resource));
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400923}
924
Quentin Glidiccde13452016-08-12 10:41:32 +0200925/** Send wl_keyboard.modifiers events to focused resources and pointer
926 * focused resources.
927 *
928 * \param keyboard The keyboard where the modifiers events originates from.
929 * \param serial The serial of the event
930 * \param mods_depressed The mods_depressed value of the event
931 * \param mods_latched The mods_latched value of the event
932 * \param mods_locked The mods_locked value of the event
933 * \param group The group value of the event
934 *
935 * For every resource that is currently in focus, send a wl_keyboard.modifiers
936 * event with the passed parameters. The focused resources are the wl_keyboard
937 * resources of the client which currently has the surface with keyboard focus.
938 * This also sends wl_keyboard.modifiers events to the wl_keyboard resources of
939 * the client having pointer focus (if different from the keyboard focus client).
940 */
941WL_EXPORT void
942weston_keyboard_send_modifiers(struct weston_keyboard *keyboard,
943 uint32_t serial, uint32_t mods_depressed,
944 uint32_t mods_latched,
945 uint32_t mods_locked, uint32_t group)
946{
947 struct weston_pointer *pointer =
948 weston_seat_get_pointer(keyboard->seat);
949
950 if (weston_keyboard_has_focus_resource(keyboard)) {
951 struct wl_list *resource_list;
952 struct wl_resource *resource;
953
954 resource_list = &keyboard->focus_resource_list;
955 wl_resource_for_each(resource, resource_list) {
956 wl_keyboard_send_modifiers(resource, serial,
957 mods_depressed, mods_latched,
958 mods_locked, group);
959 }
960 }
961
962 if (pointer && pointer->focus && pointer->focus->surface->resource &&
963 pointer->focus->surface != keyboard->focus) {
964 struct wl_client *pointer_client =
965 wl_resource_get_client(pointer->focus->surface->resource);
966
967 send_modifiers_to_client_in_list(pointer_client,
968 &keyboard->resource_list,
969 serial,
970 keyboard);
971 }
972}
973
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400974static void
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700975default_grab_keyboard_modifiers(struct weston_keyboard_grab *grab,
976 uint32_t serial, uint32_t mods_depressed,
977 uint32_t mods_latched,
978 uint32_t mods_locked, uint32_t group)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400979{
Quentin Glidiccde13452016-08-12 10:41:32 +0200980 weston_keyboard_send_modifiers(grab->keyboard, serial, mods_depressed,
981 mods_latched, mods_locked, group);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400982}
983
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200984static void
985default_grab_keyboard_cancel(struct weston_keyboard_grab *grab)
986{
987}
988
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400989static const struct weston_keyboard_grab_interface
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400990 default_keyboard_grab_interface = {
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700991 default_grab_keyboard_key,
992 default_grab_keyboard_modifiers,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200993 default_grab_keyboard_cancel,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400994};
995
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400996static void
997pointer_unmap_sprite(struct weston_pointer *pointer)
998{
Pekka Paalanenc557ff72014-11-12 16:42:52 +0200999 struct weston_surface *surface = pointer->sprite->surface;
1000
1001 if (weston_surface_is_mapped(surface))
1002 weston_surface_unmap(surface);
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001003
1004 wl_list_remove(&pointer->sprite_destroy_listener.link);
Quentin Glidic2edc3d52016-08-12 10:41:33 +02001005 surface->committed = NULL;
1006 surface->committed_private = NULL;
Pekka Paalanen8274d902014-08-06 19:36:51 +03001007 weston_surface_set_label_func(surface, NULL);
Jason Ekstranda7af7042013-10-12 22:38:11 -05001008 weston_view_destroy(pointer->sprite);
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001009 pointer->sprite = NULL;
1010}
1011
1012static void
1013pointer_handle_sprite_destroy(struct wl_listener *listener, void *data)
1014{
1015 struct weston_pointer *pointer =
1016 container_of(listener, struct weston_pointer,
1017 sprite_destroy_listener);
1018
1019 pointer->sprite = NULL;
1020}
1021
Jonas Ådahl3e12e632013-12-02 22:05:05 +01001022static void
1023weston_pointer_reset_state(struct weston_pointer *pointer)
1024{
1025 pointer->button_count = 0;
1026}
1027
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001028static void
1029weston_pointer_handle_output_destroy(struct wl_listener *listener, void *data);
1030
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001031WL_EXPORT struct weston_pointer *
Giulio Camuffocdb4d292013-11-14 23:42:53 +01001032weston_pointer_create(struct weston_seat *seat)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001033{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001034 struct weston_pointer *pointer;
1035
Peter Huttererf3d62272013-08-08 11:57:05 +10001036 pointer = zalloc(sizeof *pointer);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001037 if (pointer == NULL)
1038 return NULL;
1039
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001040 wl_list_init(&pointer->pointer_clients);
Giulio Camuffocdb4d292013-11-14 23:42:53 +01001041 weston_pointer_set_default_grab(pointer,
1042 seat->compositor->default_pointer_grab);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001043 wl_list_init(&pointer->focus_resource_listener.link);
1044 pointer->focus_resource_listener.notify = pointer_focus_resource_destroyed;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001045 pointer->default_grab.pointer = pointer;
1046 pointer->grab = &pointer->default_grab;
Giulio Camuffo6fcb3782013-11-14 23:42:50 +01001047 wl_signal_init(&pointer->motion_signal);
Emilio Pozuelo Monfortaa7a4762013-11-19 11:37:15 +01001048 wl_signal_init(&pointer->focus_signal);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001049 wl_list_init(&pointer->focus_view_listener.link);
Jonas Ådahl3eb4ddd2016-07-22 17:52:58 +08001050 wl_signal_init(&pointer->destroy_signal);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001051
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001052 pointer->sprite_destroy_listener.notify = pointer_handle_sprite_destroy;
1053
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001054 /* FIXME: Pick better co-ords. */
1055 pointer->x = wl_fixed_from_int(100);
1056 pointer->y = wl_fixed_from_int(100);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001057
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001058 pointer->output_destroy_listener.notify =
1059 weston_pointer_handle_output_destroy;
1060 wl_signal_add(&seat->compositor->output_destroyed_signal,
1061 &pointer->output_destroy_listener);
1062
Derek Foremanf9318d12015-05-11 15:40:11 -05001063 pointer->sx = wl_fixed_from_int(-1000000);
1064 pointer->sy = wl_fixed_from_int(-1000000);
1065
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001066 return pointer;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001067}
1068
1069WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001070weston_pointer_destroy(struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001071{
Jonas Ådahl3eb4ddd2016-07-22 17:52:58 +08001072 wl_signal_emit(&pointer->destroy_signal, pointer);
1073
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001074 if (pointer->sprite)
1075 pointer_unmap_sprite(pointer);
1076
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001077 /* XXX: What about pointer->resource_list? */
Neil Roberts96d790e2013-09-19 17:32:00 +01001078
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001079 wl_list_remove(&pointer->focus_resource_listener.link);
1080 wl_list_remove(&pointer->focus_view_listener.link);
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001081 wl_list_remove(&pointer->output_destroy_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001082 free(pointer);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001083}
1084
Giulio Camuffocdb4d292013-11-14 23:42:53 +01001085void
1086weston_pointer_set_default_grab(struct weston_pointer *pointer,
1087 const struct weston_pointer_grab_interface *interface)
1088{
1089 if (interface)
1090 pointer->default_grab.interface = interface;
1091 else
1092 pointer->default_grab.interface =
1093 &default_pointer_grab_interface;
1094}
1095
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001096WL_EXPORT struct weston_keyboard *
1097weston_keyboard_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001098{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001099 struct weston_keyboard *keyboard;
1100
Peter Huttererf3d62272013-08-08 11:57:05 +10001101 keyboard = zalloc(sizeof *keyboard);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001102 if (keyboard == NULL)
Neil Roberts96d790e2013-09-19 17:32:00 +01001103 return NULL;
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001104
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001105 wl_list_init(&keyboard->resource_list);
Neil Roberts96d790e2013-09-19 17:32:00 +01001106 wl_list_init(&keyboard->focus_resource_list);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001107 wl_list_init(&keyboard->focus_resource_listener.link);
1108 keyboard->focus_resource_listener.notify = keyboard_focus_resource_destroyed;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001109 wl_array_init(&keyboard->keys);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001110 keyboard->default_grab.interface = &default_keyboard_grab_interface;
1111 keyboard->default_grab.keyboard = keyboard;
1112 keyboard->grab = &keyboard->default_grab;
1113 wl_signal_init(&keyboard->focus_signal);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001114
1115 return keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001116}
1117
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001118static void
1119weston_xkb_info_destroy(struct weston_xkb_info *xkb_info);
1120
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001121WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001122weston_keyboard_destroy(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001123{
1124 /* XXX: What about keyboard->resource_list? */
Neil Roberts96d790e2013-09-19 17:32:00 +01001125
Derek Foreman185d1582017-06-28 11:17:23 -05001126 xkb_state_unref(keyboard->xkb_state.state);
1127 if (keyboard->xkb_info)
1128 weston_xkb_info_destroy(keyboard->xkb_info);
1129 xkb_keymap_unref(keyboard->pending_keymap);
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001130
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001131 wl_array_release(&keyboard->keys);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001132 wl_list_remove(&keyboard->focus_resource_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001133 free(keyboard);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001134}
1135
Jonas Ådahlcbfa7f72013-12-02 22:05:04 +01001136static void
1137weston_touch_reset_state(struct weston_touch *touch)
1138{
1139 touch->num_tp = 0;
1140}
1141
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001142WL_EXPORT struct weston_touch *
1143weston_touch_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001144{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001145 struct weston_touch *touch;
1146
Peter Huttererf3d62272013-08-08 11:57:05 +10001147 touch = zalloc(sizeof *touch);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001148 if (touch == NULL)
1149 return NULL;
1150
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001151 wl_list_init(&touch->resource_list);
Neil Roberts96d790e2013-09-19 17:32:00 +01001152 wl_list_init(&touch->focus_resource_list);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001153 wl_list_init(&touch->focus_view_listener.link);
1154 touch->focus_view_listener.notify = touch_focus_view_destroyed;
1155 wl_list_init(&touch->focus_resource_listener.link);
1156 touch->focus_resource_listener.notify = touch_focus_resource_destroyed;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001157 touch->default_grab.interface = &default_touch_grab_interface;
1158 touch->default_grab.touch = touch;
1159 touch->grab = &touch->default_grab;
1160 wl_signal_init(&touch->focus_signal);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001161
1162 return touch;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001163}
1164
1165WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001166weston_touch_destroy(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001167{
1168 /* XXX: What about touch->resource_list? */
Neil Roberts96d790e2013-09-19 17:32:00 +01001169
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001170 wl_list_remove(&touch->focus_view_listener.link);
1171 wl_list_remove(&touch->focus_resource_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001172 free(touch);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001173}
1174
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001175static void
Kristian Høgsberge3148752013-05-06 23:19:49 -04001176seat_send_updated_caps(struct weston_seat *seat)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001177{
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001178 enum wl_seat_capability caps = 0;
Rob Bradford6e737f52013-09-06 17:48:19 +01001179 struct wl_resource *resource;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001180
Jonas Ådahld6e1c342013-10-17 23:04:05 +02001181 if (seat->pointer_device_count > 0)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001182 caps |= WL_SEAT_CAPABILITY_POINTER;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02001183 if (seat->keyboard_device_count > 0)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001184 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02001185 if (seat->touch_device_count > 0)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001186 caps |= WL_SEAT_CAPABILITY_TOUCH;
1187
Rob Bradford6e737f52013-09-06 17:48:19 +01001188 wl_resource_for_each(resource, &seat->base_resource_list) {
1189 wl_seat_send_capabilities(resource, caps);
Jason Ekstrand44a38632013-06-14 10:08:00 -05001190 }
Jason Ekstranda4ab5422014-04-02 19:53:45 -05001191 wl_signal_emit(&seat->updated_caps_signal, seat);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001192}
1193
Derek Foremanf9318d12015-05-11 15:40:11 -05001194
1195/** Clear the pointer focus
1196 *
1197 * \param pointer the pointer to clear focus for.
1198 *
1199 * This can be used to unset pointer focus and set the co-ordinates to the
1200 * arbitrary values we use for the no focus case.
1201 *
1202 * There's no requirement to use this function. For example, passing the
1203 * results of a weston_compositor_pick_view() directly to
1204 * weston_pointer_set_focus() will do the right thing when no view is found.
1205 */
1206WL_EXPORT void
1207weston_pointer_clear_focus(struct weston_pointer *pointer)
1208{
1209 weston_pointer_set_focus(pointer, NULL,
1210 wl_fixed_from_int(-1000000),
1211 wl_fixed_from_int(-1000000));
1212}
1213
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001214WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001215weston_pointer_set_focus(struct weston_pointer *pointer,
Jason Ekstranda7af7042013-10-12 22:38:11 -05001216 struct weston_view *view,
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001217 wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001218{
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001219 struct weston_pointer_client *pointer_client;
Derek Foreman1281a362015-07-31 16:55:32 -05001220 struct weston_keyboard *kbd = weston_seat_get_keyboard(pointer->seat);
Neil Roberts96d790e2013-09-19 17:32:00 +01001221 struct wl_resource *resource;
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001222 struct wl_resource *surface_resource;
Rob Bradford880ebc72013-07-22 17:31:38 +01001223 struct wl_display *display = pointer->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001224 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +01001225 struct wl_list *focus_resource_list;
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -08001226 int refocus = 0;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001227
1228 if ((!pointer->focus && view) ||
1229 (pointer->focus && !view) ||
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -08001230 (pointer->focus && pointer->focus->surface != view->surface) ||
1231 pointer->sx != sx || pointer->sy != sy)
1232 refocus = 1;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001233
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001234 if (pointer->focus_client && refocus) {
1235 focus_resource_list = &pointer->focus_client->pointer_resources;
1236 if (!wl_list_empty(focus_resource_list)) {
1237 serial = wl_display_next_serial(display);
1238 surface_resource = pointer->focus->surface->resource;
1239 wl_resource_for_each(resource, focus_resource_list) {
1240 wl_pointer_send_leave(resource, serial,
1241 surface_resource);
Peter Hutterer87743e92016-01-18 16:38:22 +10001242 pointer_send_frame(resource);
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001243 }
Neil Roberts96d790e2013-09-19 17:32:00 +01001244 }
1245
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001246 pointer->focus_client = NULL;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001247 }
1248
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001249 pointer_client = find_pointer_client_for_view(pointer, view);
1250 if (pointer_client && refocus) {
1251 struct wl_client *surface_client = pointer_client->client;
Neil Roberts96d790e2013-09-19 17:32:00 +01001252
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001253 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +01001254
Jason Ekstranda7af7042013-10-12 22:38:11 -05001255 if (kbd && kbd->focus != view->surface)
Kristian Høgsbergcb406f12013-10-09 10:54:03 -07001256 send_modifiers_to_client_in_list(surface_client,
1257 &kbd->resource_list,
1258 serial,
1259 kbd);
1260
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001261 pointer->focus_client = pointer_client;
Neil Roberts96d790e2013-09-19 17:32:00 +01001262
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001263 focus_resource_list = &pointer->focus_client->pointer_resources;
Neil Roberts96d790e2013-09-19 17:32:00 +01001264 wl_resource_for_each(resource, focus_resource_list) {
1265 wl_pointer_send_enter(resource,
1266 serial,
Jason Ekstranda7af7042013-10-12 22:38:11 -05001267 view->surface->resource,
Neil Roberts96d790e2013-09-19 17:32:00 +01001268 sx, sy);
Peter Hutterer87743e92016-01-18 16:38:22 +10001269 pointer_send_frame(resource);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001270 }
Neil Roberts96d790e2013-09-19 17:32:00 +01001271
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001272 pointer->focus_serial = serial;
1273 }
1274
Giulio Camuffo65a07f82013-12-06 12:46:27 +01001275 wl_list_remove(&pointer->focus_view_listener.link);
1276 wl_list_init(&pointer->focus_view_listener.link);
1277 wl_list_remove(&pointer->focus_resource_listener.link);
1278 wl_list_init(&pointer->focus_resource_listener.link);
Emilio Pozuelo Monfortaa7a4762013-11-19 11:37:15 +01001279 if (view)
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001280 wl_signal_add(&view->destroy_signal, &pointer->focus_view_listener);
Giulio Camuffo65a07f82013-12-06 12:46:27 +01001281 if (view && view->surface->resource)
1282 wl_resource_add_destroy_listener(view->surface->resource,
1283 &pointer->focus_resource_listener);
1284
1285 pointer->focus = view;
1286 pointer->focus_view_listener.notify = pointer_focus_view_destroyed;
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -08001287 pointer->sx = sx;
1288 pointer->sy = sy;
1289
Derek Foremanf9318d12015-05-11 15:40:11 -05001290 assert(view || sx == wl_fixed_from_int(-1000000));
1291 assert(view || sy == wl_fixed_from_int(-1000000));
1292
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001293 wl_signal_emit(&pointer->focus_signal, pointer);
1294}
1295
Neil Roberts96d790e2013-09-19 17:32:00 +01001296static void
1297send_enter_to_resource_list(struct wl_list *list,
1298 struct weston_keyboard *keyboard,
1299 struct weston_surface *surface,
1300 uint32_t serial)
1301{
1302 struct wl_resource *resource;
1303
1304 wl_resource_for_each(resource, list) {
1305 send_modifiers_to_resource(keyboard, resource, serial);
1306 wl_keyboard_send_enter(resource, serial,
1307 surface->resource,
1308 &keyboard->keys);
1309 }
1310}
1311
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001312WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -04001313weston_keyboard_set_focus(struct weston_keyboard *keyboard,
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -04001314 struct weston_surface *surface)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001315{
1316 struct wl_resource *resource;
Rob Bradford880ebc72013-07-22 17:31:38 +01001317 struct wl_display *display = keyboard->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001318 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +01001319 struct wl_list *focus_resource_list;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001320
Neil Roberts96d790e2013-09-19 17:32:00 +01001321 focus_resource_list = &keyboard->focus_resource_list;
1322
1323 if (!wl_list_empty(focus_resource_list) && keyboard->focus != surface) {
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001324 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +01001325 wl_resource_for_each(resource, focus_resource_list) {
1326 wl_keyboard_send_leave(resource, serial,
1327 keyboard->focus->resource);
1328 }
1329 move_resources(&keyboard->resource_list, focus_resource_list);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001330 }
1331
Neil Roberts96d790e2013-09-19 17:32:00 +01001332 if (find_resource_for_surface(&keyboard->resource_list, surface) &&
1333 keyboard->focus != surface) {
1334 struct wl_client *surface_client =
1335 wl_resource_get_client(surface->resource);
1336
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001337 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +01001338
1339 move_resources_for_client(focus_resource_list,
1340 &keyboard->resource_list,
1341 surface_client);
1342 send_enter_to_resource_list(focus_resource_list,
1343 keyboard,
1344 surface,
1345 serial);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001346 keyboard->focus_serial = serial;
Giulio Camuffo65a07f82013-12-06 12:46:27 +01001347 }
1348
1349 wl_list_remove(&keyboard->focus_resource_listener.link);
1350 wl_list_init(&keyboard->focus_resource_listener.link);
1351 if (surface && surface->resource)
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001352 wl_resource_add_destroy_listener(surface->resource,
1353 &keyboard->focus_resource_listener);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001354
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001355 keyboard->focus = surface;
1356 wl_signal_emit(&keyboard->focus_signal, keyboard);
1357}
1358
Giulio Camuffoa20ca812014-11-22 11:16:56 +02001359/* Users of this function must manually manage the keyboard focus */
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001360WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -04001361weston_keyboard_start_grab(struct weston_keyboard *keyboard,
1362 struct weston_keyboard_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001363{
1364 keyboard->grab = grab;
1365 grab->keyboard = keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001366}
1367
1368WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -04001369weston_keyboard_end_grab(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001370{
1371 keyboard->grab = &keyboard->default_grab;
1372}
1373
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02001374static void
1375weston_keyboard_cancel_grab(struct weston_keyboard *keyboard)
1376{
1377 keyboard->grab->interface->cancel(keyboard->grab);
1378}
1379
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001380WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001381weston_pointer_start_grab(struct weston_pointer *pointer,
1382 struct weston_pointer_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001383{
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001384 pointer->grab = grab;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001385 grab->pointer = pointer;
Kristian Høgsbergda751b82013-07-04 00:58:07 -04001386 pointer->grab->interface->focus(pointer->grab);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001387}
1388
1389WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001390weston_pointer_end_grab(struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001391{
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001392 pointer->grab = &pointer->default_grab;
Kristian Høgsbergda751b82013-07-04 00:58:07 -04001393 pointer->grab->interface->focus(pointer->grab);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001394}
1395
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02001396static void
1397weston_pointer_cancel_grab(struct weston_pointer *pointer)
1398{
1399 pointer->grab->interface->cancel(pointer->grab);
1400}
1401
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001402WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -04001403weston_touch_start_grab(struct weston_touch *touch, struct weston_touch_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001404{
1405 touch->grab = grab;
1406 grab->touch = touch;
1407}
1408
1409WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -04001410weston_touch_end_grab(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001411{
1412 touch->grab = &touch->default_grab;
1413}
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001414
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02001415static void
1416weston_touch_cancel_grab(struct weston_touch *touch)
1417{
1418 touch->grab->interface->cancel(touch->grab);
1419}
1420
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001421static void
1422weston_pointer_clamp_for_output(struct weston_pointer *pointer,
1423 struct weston_output *output,
1424 wl_fixed_t *fx, wl_fixed_t *fy)
1425{
1426 int x, y;
1427
1428 x = wl_fixed_to_int(*fx);
1429 y = wl_fixed_to_int(*fy);
1430
1431 if (x < output->x)
1432 *fx = wl_fixed_from_int(output->x);
1433 else if (x >= output->x + output->width)
1434 *fx = wl_fixed_from_int(output->x +
1435 output->width - 1);
1436 if (y < output->y)
1437 *fy = wl_fixed_from_int(output->y);
1438 else if (y >= output->y + output->height)
1439 *fy = wl_fixed_from_int(output->y +
1440 output->height - 1);
1441}
1442
Rob Bradford806d8c02013-06-25 18:56:41 +01001443WL_EXPORT void
1444weston_pointer_clamp(struct weston_pointer *pointer, wl_fixed_t *fx, wl_fixed_t *fy)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001445{
Rob Bradford806d8c02013-06-25 18:56:41 +01001446 struct weston_compositor *ec = pointer->seat->compositor;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001447 struct weston_output *output, *prev = NULL;
1448 int x, y, old_x, old_y, valid = 0;
1449
1450 x = wl_fixed_to_int(*fx);
1451 y = wl_fixed_to_int(*fy);
Rob Bradford806d8c02013-06-25 18:56:41 +01001452 old_x = wl_fixed_to_int(pointer->x);
1453 old_y = wl_fixed_to_int(pointer->y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001454
1455 wl_list_for_each(output, &ec->output_list, link) {
Rob Bradford66bd9f52013-06-25 18:56:42 +01001456 if (pointer->seat->output && pointer->seat->output != output)
1457 continue;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001458 if (pixman_region32_contains_point(&output->region,
1459 x, y, NULL))
1460 valid = 1;
1461 if (pixman_region32_contains_point(&output->region,
1462 old_x, old_y, NULL))
1463 prev = output;
1464 }
1465
Rob Bradford66bd9f52013-06-25 18:56:42 +01001466 if (!prev)
1467 prev = pointer->seat->output;
1468
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001469 if (prev && !valid)
1470 weston_pointer_clamp_for_output(pointer, prev, fx, fy);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001471}
1472
Jonas Ådahld2510102014-10-05 21:39:14 +02001473static void
1474weston_pointer_move_to(struct weston_pointer *pointer,
1475 wl_fixed_t x, wl_fixed_t y)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001476{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001477 int32_t ix, iy;
1478
Rob Bradford806d8c02013-06-25 18:56:41 +01001479 weston_pointer_clamp (pointer, &x, &y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001480
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001481 pointer->x = x;
1482 pointer->y = y;
1483
1484 ix = wl_fixed_to_int(x);
1485 iy = wl_fixed_to_int(y);
1486
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001487 if (pointer->sprite) {
Jason Ekstranda7af7042013-10-12 22:38:11 -05001488 weston_view_set_position(pointer->sprite,
1489 ix - pointer->hotspot_x,
1490 iy - pointer->hotspot_y);
1491 weston_view_schedule_repaint(pointer->sprite);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001492 }
Giulio Camuffo6fcb3782013-11-14 23:42:50 +01001493
Giulio Camuffo1959ab82013-11-14 23:42:52 +01001494 pointer->grab->interface->focus(pointer->grab);
Giulio Camuffo6fcb3782013-11-14 23:42:50 +01001495 wl_signal_emit(&pointer->motion_signal, pointer);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001496}
1497
Jonas Ådahld2510102014-10-05 21:39:14 +02001498WL_EXPORT void
Jonas Ådahld2510102014-10-05 21:39:14 +02001499weston_pointer_move(struct weston_pointer *pointer,
1500 struct weston_pointer_motion_event *event)
1501{
1502 wl_fixed_t x, y;
1503
1504 weston_pointer_motion_to_abs(pointer, event, &x, &y);
1505 weston_pointer_move_to(pointer, x, y);
1506}
1507
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001508/** Verify if the pointer is in a valid position and move it if it isn't.
1509 */
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001510static void
1511weston_pointer_handle_output_destroy(struct wl_listener *listener, void *data)
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001512{
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001513 struct weston_pointer *pointer;
1514 struct weston_compositor *ec;
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001515 struct weston_output *output, *closest = NULL;
1516 int x, y, distance, min = INT_MAX;
1517 wl_fixed_t fx, fy;
1518
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001519 pointer = container_of(listener, struct weston_pointer,
1520 output_destroy_listener);
1521 ec = pointer->seat->compositor;
1522
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001523 x = wl_fixed_to_int(pointer->x);
1524 y = wl_fixed_to_int(pointer->y);
1525
1526 wl_list_for_each(output, &ec->output_list, link) {
1527 if (pixman_region32_contains_point(&output->region,
1528 x, y, NULL))
1529 return;
1530
1531 /* Aproximante the distance from the pointer to the center of
1532 * the output. */
1533 distance = abs(output->x + output->width / 2 - x) +
1534 abs(output->y + output->height / 2 - y);
1535 if (distance < min) {
1536 min = distance;
1537 closest = output;
1538 }
1539 }
1540
1541 /* Nothing to do if there's no output left. */
1542 if (!closest)
1543 return;
1544
1545 fx = pointer->x;
1546 fy = pointer->y;
1547
1548 weston_pointer_clamp_for_output(pointer, closest, &fx, &fy);
Jonas Ådahld2510102014-10-05 21:39:14 +02001549 weston_pointer_move_to(pointer, fx, fy);
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001550}
1551
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001552WL_EXPORT void
1553notify_motion(struct weston_seat *seat,
Jonas Ådahld2510102014-10-05 21:39:14 +02001554 uint32_t time,
1555 struct weston_pointer_motion_event *event)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001556{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001557 struct weston_compositor *ec = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001558 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001559
1560 weston_compositor_wake(ec);
Jonas Ådahld2510102014-10-05 21:39:14 +02001561 pointer->grab->interface->motion(pointer->grab, time, event);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001562}
1563
Daniel Stone96d47c02013-11-19 11:37:12 +01001564static void
1565run_modifier_bindings(struct weston_seat *seat, uint32_t old, uint32_t new)
1566{
1567 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001568 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Daniel Stone96d47c02013-11-19 11:37:12 +01001569 uint32_t diff;
1570 unsigned int i;
1571 struct {
1572 uint32_t xkb;
1573 enum weston_keyboard_modifier weston;
1574 } mods[] = {
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001575 { keyboard->xkb_info->ctrl_mod, MODIFIER_CTRL },
1576 { keyboard->xkb_info->alt_mod, MODIFIER_ALT },
1577 { keyboard->xkb_info->super_mod, MODIFIER_SUPER },
1578 { keyboard->xkb_info->shift_mod, MODIFIER_SHIFT },
Daniel Stone96d47c02013-11-19 11:37:12 +01001579 };
1580
1581 diff = new & ~old;
1582 for (i = 0; i < ARRAY_LENGTH(mods); i++) {
1583 if (diff & (1 << mods[i].xkb))
1584 weston_compositor_run_modifier_binding(compositor,
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001585 keyboard,
Daniel Stone96d47c02013-11-19 11:37:12 +01001586 mods[i].weston,
1587 WL_KEYBOARD_KEY_STATE_PRESSED);
1588 }
1589
1590 diff = old & ~new;
1591 for (i = 0; i < ARRAY_LENGTH(mods); i++) {
1592 if (diff & (1 << mods[i].xkb))
1593 weston_compositor_run_modifier_binding(compositor,
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001594 keyboard,
Daniel Stone96d47c02013-11-19 11:37:12 +01001595 mods[i].weston,
1596 WL_KEYBOARD_KEY_STATE_RELEASED);
1597 }
1598}
1599
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001600WL_EXPORT void
1601notify_motion_absolute(struct weston_seat *seat,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001602 uint32_t time, double x, double y)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001603{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001604 struct weston_compositor *ec = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001605 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Jonas Ådahld2510102014-10-05 21:39:14 +02001606 struct weston_pointer_motion_event event = { 0 };
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001607
1608 weston_compositor_wake(ec);
Jonas Ådahld2510102014-10-05 21:39:14 +02001609
1610 event = (struct weston_pointer_motion_event) {
1611 .mask = WESTON_POINTER_MOTION_ABS,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001612 .x = x,
1613 .y = y,
Jonas Ådahld2510102014-10-05 21:39:14 +02001614 };
1615
1616 pointer->grab->interface->motion(pointer->grab, time, &event);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001617}
1618
Jonas Ådahl94e2e2d2014-10-18 18:42:19 +02001619static unsigned int
1620peek_next_activate_serial(struct weston_compositor *c)
1621{
1622 unsigned serial = c->activate_serial + 1;
1623
1624 return serial == 0 ? 1 : serial;
1625}
1626
1627static void
1628inc_activate_serial(struct weston_compositor *c)
1629{
1630 c->activate_serial = peek_next_activate_serial (c);
1631}
1632
1633WL_EXPORT void
1634weston_view_activate(struct weston_view *view,
1635 struct weston_seat *seat,
1636 uint32_t flags)
1637{
1638 struct weston_compositor *compositor = seat->compositor;
1639
1640 if (flags & WESTON_ACTIVATE_FLAG_CLICKED) {
1641 view->click_to_activate_serial =
1642 peek_next_activate_serial(compositor);
1643 }
1644
1645 weston_seat_set_keyboard_focus(seat, view->surface);
1646}
1647
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001648WL_EXPORT void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001649notify_button(struct weston_seat *seat, uint32_t time, int32_t button,
1650 enum wl_pointer_button_state state)
1651{
1652 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001653 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001654
1655 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001656 weston_compositor_idle_inhibit(compositor);
1657 if (pointer->button_count == 0) {
1658 pointer->grab_button = button;
1659 pointer->grab_time = time;
1660 pointer->grab_x = pointer->x;
1661 pointer->grab_y = pointer->y;
1662 }
1663 pointer->button_count++;
1664 } else {
1665 weston_compositor_idle_release(compositor);
1666 pointer->button_count--;
1667 }
1668
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001669 weston_compositor_run_button_binding(compositor, pointer, time, button,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001670 state);
1671
1672 pointer->grab->interface->button(pointer->grab, time, button, state);
1673
1674 if (pointer->button_count == 1)
1675 pointer->grab_serial =
1676 wl_display_get_serial(compositor->wl_display);
1677}
1678
1679WL_EXPORT void
Peter Hutterer89b6a492016-01-18 15:58:17 +10001680notify_axis(struct weston_seat *seat, uint32_t time,
1681 struct weston_pointer_axis_event *event)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001682{
1683 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001684 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001685
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001686 weston_compositor_wake(compositor);
1687
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001688 if (weston_compositor_run_axis_binding(compositor, pointer,
Peter Hutterer89b6a492016-01-18 15:58:17 +10001689 time, event))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001690 return;
1691
Peter Hutterer89b6a492016-01-18 15:58:17 +10001692 pointer->grab->interface->axis(pointer->grab, time, event);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001693}
1694
Peter Hutterer87743e92016-01-18 16:38:22 +10001695WL_EXPORT void
1696notify_axis_source(struct weston_seat *seat, uint32_t source)
1697{
1698 struct weston_compositor *compositor = seat->compositor;
1699 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1700
1701 weston_compositor_wake(compositor);
1702
1703 pointer->grab->interface->axis_source(pointer->grab, source);
1704}
1705
1706WL_EXPORT void
1707notify_pointer_frame(struct weston_seat *seat)
1708{
1709 struct weston_compositor *compositor = seat->compositor;
1710 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1711
1712 weston_compositor_wake(compositor);
1713
1714 pointer->grab->interface->frame(pointer->grab);
1715}
1716
Giulio Camuffo6ef444d2014-08-28 19:44:09 +03001717WL_EXPORT int
1718weston_keyboard_set_locks(struct weston_keyboard *keyboard,
1719 uint32_t mask, uint32_t value)
1720{
Giulio Camuffo6ef444d2014-08-28 19:44:09 +03001721 uint32_t serial;
1722 xkb_mod_mask_t mods_depressed, mods_latched, mods_locked, group;
1723 xkb_mod_mask_t num, caps;
1724
1725 /* We don't want the leds to go out of sync with the actual state
1726 * so if the backend has no way to change the leds don't try to
1727 * change the state */
1728 if (!keyboard->seat->led_update)
1729 return -1;
1730
1731 mods_depressed = xkb_state_serialize_mods(keyboard->xkb_state.state,
1732 XKB_STATE_DEPRESSED);
1733 mods_latched = xkb_state_serialize_mods(keyboard->xkb_state.state,
1734 XKB_STATE_LATCHED);
1735 mods_locked = xkb_state_serialize_mods(keyboard->xkb_state.state,
1736 XKB_STATE_LOCKED);
1737 group = xkb_state_serialize_group(keyboard->xkb_state.state,
1738 XKB_STATE_EFFECTIVE);
1739
1740 num = (1 << keyboard->xkb_info->mod2_mod);
1741 caps = (1 << keyboard->xkb_info->caps_mod);
1742 if (mask & WESTON_NUM_LOCK) {
1743 if (value & WESTON_NUM_LOCK)
1744 mods_locked |= num;
1745 else
1746 mods_locked &= ~num;
1747 }
1748 if (mask & WESTON_CAPS_LOCK) {
1749 if (value & WESTON_CAPS_LOCK)
1750 mods_locked |= caps;
1751 else
1752 mods_locked &= ~caps;
1753 }
1754
1755 xkb_state_update_mask(keyboard->xkb_state.state, mods_depressed,
1756 mods_latched, mods_locked, 0, 0, group);
1757
1758 serial = wl_display_next_serial(
1759 keyboard->seat->compositor->wl_display);
1760 notify_modifiers(keyboard->seat, serial);
1761
1762 return 0;
Giulio Camuffo6ef444d2014-08-28 19:44:09 +03001763}
1764
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001765WL_EXPORT void
1766notify_modifiers(struct weston_seat *seat, uint32_t serial)
1767{
Derek Foreman1281a362015-07-31 16:55:32 -05001768 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001769 struct weston_keyboard_grab *grab = keyboard->grab;
1770 uint32_t mods_depressed, mods_latched, mods_locked, group;
1771 uint32_t mods_lookup;
1772 enum weston_led leds = 0;
1773 int changed = 0;
1774
1775 /* Serialize and update our internal state, checking to see if it's
1776 * different to the previous state. */
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001777 mods_depressed = xkb_state_serialize_mods(keyboard->xkb_state.state,
Ran Benita2e1968f2014-08-19 23:59:51 +03001778 XKB_STATE_MODS_DEPRESSED);
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001779 mods_latched = xkb_state_serialize_mods(keyboard->xkb_state.state,
Ran Benita2e1968f2014-08-19 23:59:51 +03001780 XKB_STATE_MODS_LATCHED);
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001781 mods_locked = xkb_state_serialize_mods(keyboard->xkb_state.state,
Ran Benita2e1968f2014-08-19 23:59:51 +03001782 XKB_STATE_MODS_LOCKED);
1783 group = xkb_state_serialize_layout(keyboard->xkb_state.state,
1784 XKB_STATE_LAYOUT_EFFECTIVE);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001785
Derek Foreman244e99e2015-06-03 15:53:26 -05001786 if (mods_depressed != keyboard->modifiers.mods_depressed ||
1787 mods_latched != keyboard->modifiers.mods_latched ||
1788 mods_locked != keyboard->modifiers.mods_locked ||
1789 group != keyboard->modifiers.group)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001790 changed = 1;
1791
Derek Foreman244e99e2015-06-03 15:53:26 -05001792 run_modifier_bindings(seat, keyboard->modifiers.mods_depressed,
Daniel Stone96d47c02013-11-19 11:37:12 +01001793 mods_depressed);
1794
Derek Foreman244e99e2015-06-03 15:53:26 -05001795 keyboard->modifiers.mods_depressed = mods_depressed;
1796 keyboard->modifiers.mods_latched = mods_latched;
1797 keyboard->modifiers.mods_locked = mods_locked;
1798 keyboard->modifiers.group = group;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001799
1800 /* And update the modifier_state for bindings. */
1801 mods_lookup = mods_depressed | mods_latched;
1802 seat->modifier_state = 0;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001803 if (mods_lookup & (1 << keyboard->xkb_info->ctrl_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001804 seat->modifier_state |= MODIFIER_CTRL;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001805 if (mods_lookup & (1 << keyboard->xkb_info->alt_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001806 seat->modifier_state |= MODIFIER_ALT;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001807 if (mods_lookup & (1 << keyboard->xkb_info->super_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001808 seat->modifier_state |= MODIFIER_SUPER;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001809 if (mods_lookup & (1 << keyboard->xkb_info->shift_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001810 seat->modifier_state |= MODIFIER_SHIFT;
1811
1812 /* Finally, notify the compositor that LEDs have changed. */
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001813 if (xkb_state_led_index_is_active(keyboard->xkb_state.state,
1814 keyboard->xkb_info->num_led))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001815 leds |= LED_NUM_LOCK;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001816 if (xkb_state_led_index_is_active(keyboard->xkb_state.state,
1817 keyboard->xkb_info->caps_led))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001818 leds |= LED_CAPS_LOCK;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001819 if (xkb_state_led_index_is_active(keyboard->xkb_state.state,
1820 keyboard->xkb_info->scroll_led))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001821 leds |= LED_SCROLL_LOCK;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001822 if (leds != keyboard->xkb_state.leds && seat->led_update)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001823 seat->led_update(seat, leds);
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001824 keyboard->xkb_state.leds = leds;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001825
1826 if (changed) {
1827 grab->interface->modifiers(grab,
1828 serial,
1829 keyboard->modifiers.mods_depressed,
1830 keyboard->modifiers.mods_latched,
1831 keyboard->modifiers.mods_locked,
1832 keyboard->modifiers.group);
1833 }
1834}
1835
1836static void
1837update_modifier_state(struct weston_seat *seat, uint32_t serial, uint32_t key,
1838 enum wl_keyboard_key_state state)
1839{
Derek Foreman1281a362015-07-31 16:55:32 -05001840 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001841 enum xkb_key_direction direction;
1842
1843 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
1844 direction = XKB_KEY_DOWN;
1845 else
1846 direction = XKB_KEY_UP;
1847
1848 /* Offset the keycode by 8, as the evdev XKB rules reflect X's
1849 * broken keycode system, which starts at 8. */
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001850 xkb_state_update_key(keyboard->xkb_state.state, key + 8, direction);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001851
1852 notify_modifiers(seat, serial);
1853}
Rui Matos65196bc2013-10-10 19:44:19 +02001854
1855static void
1856send_keymap(struct wl_resource *resource, struct weston_xkb_info *xkb_info)
1857{
1858 wl_keyboard_send_keymap(resource,
1859 WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
1860 xkb_info->keymap_fd,
1861 xkb_info->keymap_size);
1862}
1863
1864static void
1865send_modifiers(struct wl_resource *resource, uint32_t serial, struct weston_keyboard *keyboard)
1866{
1867 wl_keyboard_send_modifiers(resource, serial,
1868 keyboard->modifiers.mods_depressed,
1869 keyboard->modifiers.mods_latched,
1870 keyboard->modifiers.mods_locked,
1871 keyboard->modifiers.group);
1872}
1873
1874static struct weston_xkb_info *
1875weston_xkb_info_create(struct xkb_keymap *keymap);
Rui Matos65196bc2013-10-10 19:44:19 +02001876
1877static void
1878update_keymap(struct weston_seat *seat)
1879{
Derek Foreman1281a362015-07-31 16:55:32 -05001880 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Rui Matos65196bc2013-10-10 19:44:19 +02001881 struct wl_resource *resource;
1882 struct weston_xkb_info *xkb_info;
1883 struct xkb_state *state;
1884 xkb_mod_mask_t latched_mods;
1885 xkb_mod_mask_t locked_mods;
1886
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001887 xkb_info = weston_xkb_info_create(keyboard->pending_keymap);
Rui Matos65196bc2013-10-10 19:44:19 +02001888
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001889 xkb_keymap_unref(keyboard->pending_keymap);
1890 keyboard->pending_keymap = NULL;
Rui Matos65196bc2013-10-10 19:44:19 +02001891
1892 if (!xkb_info) {
1893 weston_log("failed to create XKB info\n");
1894 return;
1895 }
1896
1897 state = xkb_state_new(xkb_info->keymap);
1898 if (!state) {
1899 weston_log("failed to initialise XKB state\n");
1900 weston_xkb_info_destroy(xkb_info);
1901 return;
1902 }
1903
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001904 latched_mods = xkb_state_serialize_mods(keyboard->xkb_state.state,
1905 XKB_STATE_MODS_LATCHED);
1906 locked_mods = xkb_state_serialize_mods(keyboard->xkb_state.state,
1907 XKB_STATE_MODS_LOCKED);
Rui Matos65196bc2013-10-10 19:44:19 +02001908 xkb_state_update_mask(state,
1909 0, /* depressed */
1910 latched_mods,
1911 locked_mods,
1912 0, 0, 0);
1913
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001914 weston_xkb_info_destroy(keyboard->xkb_info);
1915 keyboard->xkb_info = xkb_info;
Rui Matos65196bc2013-10-10 19:44:19 +02001916
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001917 xkb_state_unref(keyboard->xkb_state.state);
1918 keyboard->xkb_state.state = state;
Rui Matos65196bc2013-10-10 19:44:19 +02001919
Derek Foremanbc91e542015-06-03 15:53:27 -05001920 wl_resource_for_each(resource, &keyboard->resource_list)
Rui Matos65196bc2013-10-10 19:44:19 +02001921 send_keymap(resource, xkb_info);
Derek Foremanbc91e542015-06-03 15:53:27 -05001922 wl_resource_for_each(resource, &keyboard->focus_resource_list)
Rui Matos65196bc2013-10-10 19:44:19 +02001923 send_keymap(resource, xkb_info);
1924
1925 notify_modifiers(seat, wl_display_next_serial(seat->compositor->wl_display));
1926
1927 if (!latched_mods && !locked_mods)
1928 return;
1929
Derek Foremanbc91e542015-06-03 15:53:27 -05001930 wl_resource_for_each(resource, &keyboard->resource_list)
1931 send_modifiers(resource, wl_display_get_serial(seat->compositor->wl_display), keyboard);
1932 wl_resource_for_each(resource, &keyboard->focus_resource_list)
1933 send_modifiers(resource, wl_display_get_serial(seat->compositor->wl_display), keyboard);
Rui Matos65196bc2013-10-10 19:44:19 +02001934}
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001935
1936WL_EXPORT void
1937notify_key(struct weston_seat *seat, uint32_t time, uint32_t key,
1938 enum wl_keyboard_key_state state,
1939 enum weston_key_state_update update_state)
1940{
1941 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001942 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001943 struct weston_keyboard_grab *grab = keyboard->grab;
Pekka Paalanen86b53962014-11-19 13:43:32 +02001944 uint32_t *k, *end;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001945
1946 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001947 weston_compositor_idle_inhibit(compositor);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001948 } else {
1949 weston_compositor_idle_release(compositor);
1950 }
1951
Pekka Paalanen86b53962014-11-19 13:43:32 +02001952 end = keyboard->keys.data + keyboard->keys.size;
1953 for (k = keyboard->keys.data; k < end; k++) {
1954 if (*k == key) {
1955 /* Ignore server-generated repeats. */
1956 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
1957 return;
1958 *k = *--end;
1959 }
1960 }
1961 keyboard->keys.size = (void *) end - keyboard->keys.data;
1962 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
1963 k = wl_array_add(&keyboard->keys, sizeof *k);
1964 *k = key;
1965 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001966
1967 if (grab == &keyboard->default_grab ||
1968 grab == &keyboard->input_method_grab) {
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001969 weston_compositor_run_key_binding(compositor, keyboard, time,
1970 key, state);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001971 grab = keyboard->grab;
1972 }
1973
1974 grab->interface->key(grab, time, key, state);
1975
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001976 if (keyboard->pending_keymap &&
Pekka Paalanen86b53962014-11-19 13:43:32 +02001977 keyboard->keys.size == 0)
Rui Matos65196bc2013-10-10 19:44:19 +02001978 update_keymap(seat);
1979
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001980 if (update_state == STATE_UPDATE_AUTOMATIC) {
1981 update_modifier_state(seat,
1982 wl_display_get_serial(compositor->wl_display),
1983 key,
1984 state);
1985 }
Giulio Camuffob6ddf6c2015-02-06 19:06:54 +02001986
Olivier Fourdandf84dbe2016-06-30 16:01:56 +02001987 keyboard->grab_serial = wl_display_get_serial(compositor->wl_display);
Giulio Camuffob6ddf6c2015-02-06 19:06:54 +02001988 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
Giulio Camuffob6ddf6c2015-02-06 19:06:54 +02001989 keyboard->grab_time = time;
1990 keyboard->grab_key = key;
1991 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001992}
1993
1994WL_EXPORT void
1995notify_pointer_focus(struct weston_seat *seat, struct weston_output *output,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001996 double x, double y)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001997{
Derek Foreman1281a362015-07-31 16:55:32 -05001998 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1999
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002000 if (output) {
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02002001 weston_pointer_move_to(pointer,
2002 wl_fixed_from_double(x),
2003 wl_fixed_from_double(y));
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002004 } else {
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04002005 /* FIXME: We should call weston_pointer_set_focus(seat,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002006 * NULL) here, but somehow that breaks re-entry... */
2007 }
2008}
2009
2010static void
2011destroy_device_saved_kbd_focus(struct wl_listener *listener, void *data)
2012{
2013 struct weston_seat *ws;
2014
2015 ws = container_of(listener, struct weston_seat,
2016 saved_kbd_focus_listener);
2017
2018 ws->saved_kbd_focus = NULL;
2019}
2020
2021WL_EXPORT void
2022notify_keyboard_focus_in(struct weston_seat *seat, struct wl_array *keys,
2023 enum weston_key_state_update update_state)
2024{
2025 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05002026 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -04002027 struct weston_surface *surface;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002028 uint32_t *k, serial;
2029
2030 serial = wl_display_next_serial(compositor->wl_display);
2031 wl_array_copy(&keyboard->keys, keys);
2032 wl_array_for_each(k, &keyboard->keys) {
2033 weston_compositor_idle_inhibit(compositor);
2034 if (update_state == STATE_UPDATE_AUTOMATIC)
2035 update_modifier_state(seat, serial, *k,
2036 WL_KEYBOARD_KEY_STATE_PRESSED);
2037 }
2038
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002039 surface = seat->saved_kbd_focus;
2040
2041 if (surface) {
2042 wl_list_remove(&seat->saved_kbd_focus_listener.link);
2043 weston_keyboard_set_focus(keyboard, surface);
2044 seat->saved_kbd_focus = NULL;
2045 }
2046}
2047
2048WL_EXPORT void
2049notify_keyboard_focus_out(struct weston_seat *seat)
2050{
2051 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05002052 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
2053 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002054 uint32_t *k, serial;
2055
2056 serial = wl_display_next_serial(compositor->wl_display);
2057 wl_array_for_each(k, &keyboard->keys) {
2058 weston_compositor_idle_release(compositor);
2059 update_modifier_state(seat, serial, *k,
2060 WL_KEYBOARD_KEY_STATE_RELEASED);
2061 }
2062
2063 seat->modifier_state = 0;
2064
2065 if (keyboard->focus) {
2066 seat->saved_kbd_focus = keyboard->focus;
2067 seat->saved_kbd_focus_listener.notify =
2068 destroy_device_saved_kbd_focus;
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05002069 wl_signal_add(&keyboard->focus->destroy_signal,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002070 &seat->saved_kbd_focus_listener);
2071 }
2072
2073 weston_keyboard_set_focus(keyboard, NULL);
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02002074 weston_keyboard_cancel_grab(keyboard);
Derek Foreman1281a362015-07-31 16:55:32 -05002075 if (pointer)
2076 weston_pointer_cancel_grab(pointer);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002077}
2078
Michael Fua2bb7912013-07-23 15:51:06 +08002079WL_EXPORT void
Derek Foreman4c93c082015-04-30 16:45:41 -05002080weston_touch_set_focus(struct weston_touch *touch, struct weston_view *view)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002081{
Neil Roberts96d790e2013-09-19 17:32:00 +01002082 struct wl_list *focus_resource_list;
2083
Derek Foreman4c93c082015-04-30 16:45:41 -05002084 focus_resource_list = &touch->focus_resource_list;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002085
Derek Foreman4c93c082015-04-30 16:45:41 -05002086 if (view && touch->focus &&
2087 touch->focus->surface == view->surface) {
2088 touch->focus = view;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002089 return;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002090 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002091
Derek Foreman4c93c082015-04-30 16:45:41 -05002092 wl_list_remove(&touch->focus_resource_listener.link);
2093 wl_list_init(&touch->focus_resource_listener.link);
2094 wl_list_remove(&touch->focus_view_listener.link);
2095 wl_list_init(&touch->focus_view_listener.link);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01002096
Neil Roberts96d790e2013-09-19 17:32:00 +01002097 if (!wl_list_empty(focus_resource_list)) {
Derek Foreman4c93c082015-04-30 16:45:41 -05002098 move_resources(&touch->resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01002099 focus_resource_list);
2100 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002101
Jason Ekstranda7af7042013-10-12 22:38:11 -05002102 if (view) {
Derek Foreman362656b2014-09-04 10:23:05 -05002103 struct wl_client *surface_client;
2104
2105 if (!view->surface->resource) {
Derek Foreman4c93c082015-04-30 16:45:41 -05002106 touch->focus = NULL;
Derek Foreman362656b2014-09-04 10:23:05 -05002107 return;
2108 }
2109
2110 surface_client = wl_resource_get_client(view->surface->resource);
Neil Roberts96d790e2013-09-19 17:32:00 +01002111 move_resources_for_client(focus_resource_list,
Derek Foreman4c93c082015-04-30 16:45:41 -05002112 &touch->resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01002113 surface_client);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01002114 wl_resource_add_destroy_listener(view->surface->resource,
Derek Foreman4c93c082015-04-30 16:45:41 -05002115 &touch->focus_resource_listener);
2116 wl_signal_add(&view->destroy_signal, &touch->focus_view_listener);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002117 }
Derek Foreman4c93c082015-04-30 16:45:41 -05002118 touch->focus = view;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002119}
2120
2121/**
2122 * notify_touch - emulates button touches and notifies surfaces accordingly.
2123 *
2124 * It assumes always the correct cycle sequence until it gets here: touch_down
2125 * → touch_update → ... → touch_update → touch_end. The driver is responsible
2126 * for sending along such order.
2127 *
2128 */
2129WL_EXPORT void
2130notify_touch(struct weston_seat *seat, uint32_t time, int touch_id,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02002131 double double_x, double double_y, int touch_type)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002132{
2133 struct weston_compositor *ec = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05002134 struct weston_touch *touch = weston_seat_get_touch(seat);
Kristian Høgsberge329f362013-05-06 22:19:57 -04002135 struct weston_touch_grab *grab = touch->grab;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002136 struct weston_view *ev;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002137 wl_fixed_t sx, sy;
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02002138 wl_fixed_t x = wl_fixed_from_double(double_x);
2139 wl_fixed_t y = wl_fixed_from_double(double_y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002140
2141 /* Update grab's global coordinates. */
Neil Roberts306fe082013-10-03 16:43:06 +01002142 if (touch_id == touch->grab_touch_id && touch_type != WL_TOUCH_UP) {
2143 touch->grab_x = x;
2144 touch->grab_y = y;
2145 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002146
2147 switch (touch_type) {
2148 case WL_TOUCH_DOWN:
2149 weston_compositor_idle_inhibit(ec);
2150
Jonas Ådahl9484b692013-12-02 22:05:03 +01002151 touch->num_tp++;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002152
Jason Ekstranda7af7042013-10-12 22:38:11 -05002153 /* the first finger down picks the view, and all further go
2154 * to that view for the remainder of the touch session i.e.
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002155 * until all touch points are up again. */
Jonas Ådahl9484b692013-12-02 22:05:03 +01002156 if (touch->num_tp == 1) {
Jason Ekstranda7af7042013-10-12 22:38:11 -05002157 ev = weston_compositor_pick_view(ec, x, y, &sx, &sy);
Derek Foreman4c93c082015-04-30 16:45:41 -05002158 weston_touch_set_focus(touch, ev);
Giulio Camuffo61ed7b62015-07-08 11:55:28 +03002159 } else if (!touch->focus) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002160 /* Unexpected condition: We have non-initial touch but
2161 * there is no focused surface.
2162 */
Chris Michael3f607d32015-10-07 11:59:49 -04002163 weston_log("touch event received with %d points down "
Jonas Ådahl9484b692013-12-02 22:05:03 +01002164 "but no surface focused\n", touch->num_tp);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002165 return;
2166 }
2167
Derek Foreman99a6a2d2015-07-15 13:00:43 -05002168 weston_compositor_run_touch_binding(ec, touch,
Kristian Høgsbergc8964012014-02-05 14:25:18 -08002169 time, touch_type);
2170
Giulio Camuffo61ed7b62015-07-08 11:55:28 +03002171 grab->interface->down(grab, time, touch_id, x, y);
Jonas Ådahl9484b692013-12-02 22:05:03 +01002172 if (touch->num_tp == 1) {
Rusty Lynchf1407ff2013-08-08 21:13:57 -07002173 touch->grab_serial =
2174 wl_display_get_serial(ec->wl_display);
Neil Roberts306fe082013-10-03 16:43:06 +01002175 touch->grab_touch_id = touch_id;
Rusty Lynchf1407ff2013-08-08 21:13:57 -07002176 touch->grab_time = time;
2177 touch->grab_x = x;
2178 touch->grab_y = y;
2179 }
2180
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002181 break;
2182 case WL_TOUCH_MOTION:
Jason Ekstranda7af7042013-10-12 22:38:11 -05002183 ev = touch->focus;
2184 if (!ev)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002185 break;
2186
Giulio Camuffo61ed7b62015-07-08 11:55:28 +03002187 grab->interface->motion(grab, time, touch_id, x, y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002188 break;
2189 case WL_TOUCH_UP:
Kristian Høgsberga30e29a2014-01-08 22:29:20 -08002190 if (touch->num_tp == 0) {
2191 /* This can happen if we start out with one or
2192 * more fingers on the touch screen, in which
2193 * case we didn't get the corresponding down
2194 * event. */
2195 weston_log("unmatched touch up event\n");
2196 break;
2197 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002198 weston_compositor_idle_release(ec);
Jonas Ådahl9484b692013-12-02 22:05:03 +01002199 touch->num_tp--;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002200
2201 grab->interface->up(grab, time, touch_id);
Jonas Ådahl9484b692013-12-02 22:05:03 +01002202 if (touch->num_tp == 0)
Derek Foreman4c93c082015-04-30 16:45:41 -05002203 weston_touch_set_focus(touch, NULL);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002204 break;
2205 }
2206}
2207
Jonas Ådahl1679f232014-04-12 09:39:51 +02002208WL_EXPORT void
2209notify_touch_frame(struct weston_seat *seat)
2210{
Derek Foreman1281a362015-07-31 16:55:32 -05002211 struct weston_touch *touch = weston_seat_get_touch(seat);
Jonas Ådahl1679f232014-04-12 09:39:51 +02002212 struct weston_touch_grab *grab = touch->grab;
2213
2214 grab->interface->frame(grab);
2215}
2216
Derek Foreman3cc004a2015-11-06 15:56:09 -06002217WL_EXPORT void
2218notify_touch_cancel(struct weston_seat *seat)
2219{
2220 struct weston_touch *touch = weston_seat_get_touch(seat);
2221 struct weston_touch_grab *grab = touch->grab;
2222
2223 grab->interface->cancel(grab);
2224}
2225
Pekka Paalanen8274d902014-08-06 19:36:51 +03002226static int
2227pointer_cursor_surface_get_label(struct weston_surface *surface,
2228 char *buf, size_t len)
2229{
2230 return snprintf(buf, len, "cursor");
2231}
2232
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002233static void
Quentin Glidic2edc3d52016-08-12 10:41:33 +02002234pointer_cursor_surface_committed(struct weston_surface *es,
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06002235 int32_t dx, int32_t dy)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002236{
Quentin Glidic2edc3d52016-08-12 10:41:33 +02002237 struct weston_pointer *pointer = es->committed_private;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002238 int x, y;
2239
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06002240 if (es->width == 0)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002241 return;
2242
Jason Ekstranda7af7042013-10-12 22:38:11 -05002243 assert(es == pointer->sprite->surface);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002244
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002245 pointer->hotspot_x -= dx;
2246 pointer->hotspot_y -= dy;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002247
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002248 x = wl_fixed_to_int(pointer->x) - pointer->hotspot_x;
2249 y = wl_fixed_to_int(pointer->y) - pointer->hotspot_y;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002250
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06002251 weston_view_set_position(pointer->sprite, x, y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002252
2253 empty_region(&es->pending.input);
Ander Conselvan de Oliveira23900f72014-01-31 16:07:51 +02002254 empty_region(&es->input);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002255
2256 if (!weston_surface_is_mapped(es)) {
Giulio Camuffo412e6a52014-07-09 22:12:56 +03002257 weston_layer_entry_insert(&es->compositor->cursor_layer.view_list,
2258 &pointer->sprite->layer_link);
Jason Ekstranda7af7042013-10-12 22:38:11 -05002259 weston_view_update_transform(pointer->sprite);
Armin Krezovićf8486c32016-06-30 06:04:28 +02002260 es->is_mapped = true;
2261 pointer->sprite->is_mapped = true;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002262 }
2263}
2264
2265static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002266pointer_set_cursor(struct wl_client *client, struct wl_resource *resource,
2267 uint32_t serial, struct wl_resource *surface_resource,
2268 int32_t x, int32_t y)
2269{
Jason Ekstrand44a38632013-06-14 10:08:00 -05002270 struct weston_pointer *pointer = wl_resource_get_user_data(resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002271 struct weston_surface *surface = NULL;
2272
2273 if (surface_resource)
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05002274 surface = wl_resource_get_user_data(surface_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002275
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002276 if (pointer->focus == NULL)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002277 return;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002278 /* pointer->focus->surface->resource can be NULL. Surfaces like the
Giulio Camuffo1fd4b012013-06-20 18:13:07 +02002279 black_surface used in shell.c for fullscreen don't have
2280 a resource, but can still have focus */
Jason Ekstranda7af7042013-10-12 22:38:11 -05002281 if (pointer->focus->surface->resource == NULL)
Giulio Camuffo1fd4b012013-06-20 18:13:07 +02002282 return;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002283 if (wl_resource_get_client(pointer->focus->surface->resource) != client)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002284 return;
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002285 if (pointer->focus_serial - serial > UINT32_MAX / 2)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002286 return;
2287
Derek Foreman4e53c532015-03-23 10:55:32 -05002288 if (!surface) {
2289 if (pointer->sprite)
2290 pointer_unmap_sprite(pointer);
2291 return;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002292 }
2293
Jonas Ådahlb4070242015-03-18 15:08:03 +08002294 if (pointer->sprite && pointer->sprite->surface == surface &&
2295 pointer->hotspot_x == x && pointer->hotspot_y == y)
2296 return;
2297
Derek Foreman4e53c532015-03-23 10:55:32 -05002298 if (!pointer->sprite || pointer->sprite->surface != surface) {
2299 if (weston_surface_set_role(surface, "wl_pointer-cursor",
2300 resource,
2301 WL_POINTER_ERROR_ROLE) < 0)
2302 return;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002303
Derek Foreman4e53c532015-03-23 10:55:32 -05002304 if (pointer->sprite)
2305 pointer_unmap_sprite(pointer);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002306
Derek Foreman4e53c532015-03-23 10:55:32 -05002307 wl_signal_add(&surface->destroy_signal,
2308 &pointer->sprite_destroy_listener);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002309
Quentin Glidic2edc3d52016-08-12 10:41:33 +02002310 surface->committed = pointer_cursor_surface_committed;
2311 surface->committed_private = pointer;
Derek Foreman4e53c532015-03-23 10:55:32 -05002312 weston_surface_set_label_func(surface,
2313 pointer_cursor_surface_get_label);
2314 pointer->sprite = weston_view_create(surface);
2315 }
2316
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002317 pointer->hotspot_x = x;
2318 pointer->hotspot_y = y;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002319
Jonas Ådahl16fe4dc2014-09-08 19:33:41 +02002320 if (surface->buffer_ref.buffer) {
Quentin Glidic2edc3d52016-08-12 10:41:33 +02002321 pointer_cursor_surface_committed(surface, 0, 0);
Jonas Ådahl16fe4dc2014-09-08 19:33:41 +02002322 weston_view_schedule_repaint(pointer->sprite);
2323 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002324}
2325
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002326static void
2327pointer_release(struct wl_client *client, struct wl_resource *resource)
2328{
2329 wl_resource_destroy(resource);
2330}
2331
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002332static const struct wl_pointer_interface pointer_interface = {
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002333 pointer_set_cursor,
2334 pointer_release
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002335};
2336
2337static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002338seat_get_pointer(struct wl_client *client, struct wl_resource *resource,
2339 uint32_t id)
2340{
Jason Ekstrand44a38632013-06-14 10:08:00 -05002341 struct weston_seat *seat = wl_resource_get_user_data(resource);
Derek Foreman1281a362015-07-31 16:55:32 -05002342 /* We use the pointer_state directly, which means we'll
2343 * give a wl_pointer if the seat has ever had one - even though
2344 * the spec explicitly states that this request only takes effect
2345 * if the seat has the pointer capability.
2346 *
2347 * This prevents a race between the compositor sending new
2348 * capabilities and the client trying to use the old ones.
2349 */
2350 struct weston_pointer *pointer = seat->pointer_state;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002351 struct wl_resource *cr;
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08002352 struct weston_pointer_client *pointer_client;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002353
Derek Foreman1281a362015-07-31 16:55:32 -05002354 if (!pointer)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002355 return;
2356
Jason Ekstranda85118c2013-06-27 20:17:02 -05002357 cr = wl_resource_create(client, &wl_pointer_interface,
2358 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07002359 if (cr == NULL) {
2360 wl_client_post_no_memory(client);
2361 return;
2362 }
2363
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08002364 pointer_client = weston_pointer_ensure_pointer_client(pointer, client);
2365 if (!pointer_client) {
2366 wl_client_post_no_memory(client);
2367 return;
2368 }
2369
2370 wl_list_insert(&pointer_client->pointer_resources,
2371 wl_resource_get_link(cr));
Derek Foreman1281a362015-07-31 16:55:32 -05002372 wl_resource_set_implementation(cr, &pointer_interface, pointer,
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08002373 unbind_pointer_client_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002374
Derek Foreman1281a362015-07-31 16:55:32 -05002375 if (pointer->focus && pointer->focus->surface->resource &&
2376 wl_resource_get_client(pointer->focus->surface->resource) == client) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002377 wl_fixed_t sx, sy;
2378
Derek Foreman1281a362015-07-31 16:55:32 -05002379 weston_view_from_global_fixed(pointer->focus,
2380 pointer->x,
2381 pointer->y,
Jason Ekstranda7af7042013-10-12 22:38:11 -05002382 &sx, &sy);
Neil Roberts96d790e2013-09-19 17:32:00 +01002383
Neil Roberts96d790e2013-09-19 17:32:00 +01002384 wl_pointer_send_enter(cr,
Derek Foreman1281a362015-07-31 16:55:32 -05002385 pointer->focus_serial,
2386 pointer->focus->surface->resource,
Neil Roberts96d790e2013-09-19 17:32:00 +01002387 sx, sy);
Peter Hutterer87743e92016-01-18 16:38:22 +10002388 pointer_send_frame(cr);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002389 }
2390}
2391
2392static void
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002393keyboard_release(struct wl_client *client, struct wl_resource *resource)
2394{
2395 wl_resource_destroy(resource);
2396}
2397
2398static const struct wl_keyboard_interface keyboard_interface = {
2399 keyboard_release
2400};
2401
Derek Foreman280e7dd2014-10-03 13:13:42 -05002402static bool
Neil Roberts96d790e2013-09-19 17:32:00 +01002403should_send_modifiers_to_client(struct weston_seat *seat,
2404 struct wl_client *client)
2405{
Derek Foreman1281a362015-07-31 16:55:32 -05002406 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
2407 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
2408
2409 if (keyboard &&
2410 keyboard->focus &&
2411 keyboard->focus->resource &&
2412 wl_resource_get_client(keyboard->focus->resource) == client)
Derek Foreman280e7dd2014-10-03 13:13:42 -05002413 return true;
Neil Roberts96d790e2013-09-19 17:32:00 +01002414
Derek Foreman1281a362015-07-31 16:55:32 -05002415 if (pointer &&
2416 pointer->focus &&
2417 pointer->focus->surface->resource &&
2418 wl_resource_get_client(pointer->focus->surface->resource) == client)
Derek Foreman280e7dd2014-10-03 13:13:42 -05002419 return true;
Neil Roberts96d790e2013-09-19 17:32:00 +01002420
Derek Foreman280e7dd2014-10-03 13:13:42 -05002421 return false;
Neil Roberts96d790e2013-09-19 17:32:00 +01002422}
2423
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002424static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002425seat_get_keyboard(struct wl_client *client, struct wl_resource *resource,
2426 uint32_t id)
2427{
Jason Ekstrand44a38632013-06-14 10:08:00 -05002428 struct weston_seat *seat = wl_resource_get_user_data(resource);
Derek Foreman1281a362015-07-31 16:55:32 -05002429 /* We use the keyboard_state directly, which means we'll
2430 * give a wl_keyboard if the seat has ever had one - even though
2431 * the spec explicitly states that this request only takes effect
2432 * if the seat has the keyboard capability.
2433 *
2434 * This prevents a race between the compositor sending new
2435 * capabilities and the client trying to use the old ones.
2436 */
2437 struct weston_keyboard *keyboard = seat->keyboard_state;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002438 struct wl_resource *cr;
2439
Derek Foreman345c9f32015-06-03 15:53:28 -05002440 if (!keyboard)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002441 return;
2442
Jason Ekstranda85118c2013-06-27 20:17:02 -05002443 cr = wl_resource_create(client, &wl_keyboard_interface,
2444 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07002445 if (cr == NULL) {
2446 wl_client_post_no_memory(client);
2447 return;
2448 }
2449
Neil Roberts96d790e2013-09-19 17:32:00 +01002450 /* May be moved to focused list later by either
2451 * weston_keyboard_set_focus or directly if this client is already
2452 * focused */
Derek Foreman345c9f32015-06-03 15:53:28 -05002453 wl_list_insert(&keyboard->resource_list, wl_resource_get_link(cr));
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002454 wl_resource_set_implementation(cr, &keyboard_interface,
2455 seat, unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002456
Jonny Lamb66a41a02014-08-12 14:58:25 +02002457 if (wl_resource_get_version(cr) >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) {
2458 wl_keyboard_send_repeat_info(cr,
2459 seat->compositor->kb_repeat_rate,
2460 seat->compositor->kb_repeat_delay);
2461 }
Jasper St. Pierred8c6aeb2014-08-04 13:43:24 -04002462
Derek Foreman185d1582017-06-28 11:17:23 -05002463 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
2464 keyboard->xkb_info->keymap_fd,
2465 keyboard->xkb_info->keymap_size);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002466
Neil Roberts96d790e2013-09-19 17:32:00 +01002467 if (should_send_modifiers_to_client(seat, client)) {
Derek Foreman345c9f32015-06-03 15:53:28 -05002468 send_modifiers_to_resource(keyboard,
Neil Roberts96d790e2013-09-19 17:32:00 +01002469 cr,
Derek Foreman345c9f32015-06-03 15:53:28 -05002470 keyboard->focus_serial);
Neil Roberts96d790e2013-09-19 17:32:00 +01002471 }
2472
Derek Foreman345c9f32015-06-03 15:53:28 -05002473 if (keyboard->focus && keyboard->focus->resource &&
2474 wl_resource_get_client(keyboard->focus->resource) == client) {
Neil Roberts96d790e2013-09-19 17:32:00 +01002475 struct weston_surface *surface =
Derek Foreman345c9f32015-06-03 15:53:28 -05002476 (struct weston_surface *)keyboard->focus;
Neil Roberts96d790e2013-09-19 17:32:00 +01002477
2478 wl_list_remove(wl_resource_get_link(cr));
Derek Foreman345c9f32015-06-03 15:53:28 -05002479 wl_list_insert(&keyboard->focus_resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01002480 wl_resource_get_link(cr));
2481 wl_keyboard_send_enter(cr,
Derek Foreman345c9f32015-06-03 15:53:28 -05002482 keyboard->focus_serial,
Neil Roberts96d790e2013-09-19 17:32:00 +01002483 surface->resource,
Derek Foreman345c9f32015-06-03 15:53:28 -05002484 &keyboard->keys);
Neil Roberts96d790e2013-09-19 17:32:00 +01002485
2486 /* If this is the first keyboard resource for this
2487 * client... */
Derek Foreman345c9f32015-06-03 15:53:28 -05002488 if (keyboard->focus_resource_list.prev ==
Neil Roberts96d790e2013-09-19 17:32:00 +01002489 wl_resource_get_link(cr))
2490 wl_data_device_set_keyboard_focus(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002491 }
2492}
2493
2494static void
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002495touch_release(struct wl_client *client, struct wl_resource *resource)
2496{
2497 wl_resource_destroy(resource);
2498}
2499
2500static const struct wl_touch_interface touch_interface = {
2501 touch_release
2502};
2503
2504static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002505seat_get_touch(struct wl_client *client, struct wl_resource *resource,
2506 uint32_t id)
2507{
Jason Ekstrand44a38632013-06-14 10:08:00 -05002508 struct weston_seat *seat = wl_resource_get_user_data(resource);
Derek Foreman1281a362015-07-31 16:55:32 -05002509 /* We use the touch_state directly, which means we'll
2510 * give a wl_touch if the seat has ever had one - even though
2511 * the spec explicitly states that this request only takes effect
2512 * if the seat has the touch capability.
2513 *
2514 * This prevents a race between the compositor sending new
2515 * capabilities and the client trying to use the old ones.
2516 */
2517 struct weston_touch *touch = seat->touch_state;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002518 struct wl_resource *cr;
2519
Derek Foreman1281a362015-07-31 16:55:32 -05002520 if (!touch)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002521 return;
2522
Jason Ekstranda85118c2013-06-27 20:17:02 -05002523 cr = wl_resource_create(client, &wl_touch_interface,
2524 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07002525 if (cr == NULL) {
2526 wl_client_post_no_memory(client);
2527 return;
2528 }
2529
Derek Foreman1281a362015-07-31 16:55:32 -05002530 if (touch->focus &&
2531 wl_resource_get_client(touch->focus->surface->resource) == client) {
Chokshi, Mituld6697142015-10-09 08:28:47 +00002532 wl_list_insert(&touch->focus_resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01002533 wl_resource_get_link(cr));
2534 } else {
Chokshi, Mituld6697142015-10-09 08:28:47 +00002535 wl_list_insert(&touch->resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01002536 wl_resource_get_link(cr));
2537 }
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002538 wl_resource_set_implementation(cr, &touch_interface,
2539 seat, unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002540}
2541
Quentin Glidicaab1d362016-03-13 17:49:08 +01002542static void
2543seat_release(struct wl_client *client, struct wl_resource *resource)
2544{
2545 wl_resource_destroy(resource);
2546}
2547
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002548static const struct wl_seat_interface seat_interface = {
2549 seat_get_pointer,
2550 seat_get_keyboard,
2551 seat_get_touch,
Quentin Glidicaab1d362016-03-13 17:49:08 +01002552 seat_release,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002553};
2554
2555static void
2556bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
2557{
Kristian Høgsberge3148752013-05-06 23:19:49 -04002558 struct weston_seat *seat = data;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002559 struct wl_resource *resource;
2560 enum wl_seat_capability caps = 0;
2561
Jason Ekstranda85118c2013-06-27 20:17:02 -05002562 resource = wl_resource_create(client,
Derek Foreman1909c102015-11-26 14:17:47 -06002563 &wl_seat_interface, version, id);
Jason Ekstrand44a38632013-06-14 10:08:00 -05002564 wl_list_insert(&seat->base_resource_list, wl_resource_get_link(resource));
Jason Ekstranda85118c2013-06-27 20:17:02 -05002565 wl_resource_set_implementation(resource, &seat_interface, data,
2566 unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002567
Derek Foreman1281a362015-07-31 16:55:32 -05002568 if (weston_seat_get_pointer(seat))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002569 caps |= WL_SEAT_CAPABILITY_POINTER;
Derek Foreman1281a362015-07-31 16:55:32 -05002570 if (weston_seat_get_keyboard(seat))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002571 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
Derek Foreman1281a362015-07-31 16:55:32 -05002572 if (weston_seat_get_touch(seat))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002573 caps |= WL_SEAT_CAPABILITY_TOUCH;
2574
2575 wl_seat_send_capabilities(resource, caps);
Jasper St. Pierre0013a292014-08-07 16:43:11 -04002576 if (version >= WL_SEAT_NAME_SINCE_VERSION)
Rob Bradforde445ae62013-05-31 18:09:51 +01002577 wl_seat_send_name(resource, seat->seat_name);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002578}
2579
Jonas Ådahl30d61d82014-10-22 21:21:17 +02002580static void
2581relative_pointer_destroy(struct wl_client *client,
2582 struct wl_resource *resource)
2583{
2584 wl_resource_destroy(resource);
2585}
2586
2587static const struct zwp_relative_pointer_v1_interface relative_pointer_interface = {
2588 relative_pointer_destroy
2589};
2590
2591static void
2592relative_pointer_manager_destroy(struct wl_client *client,
2593 struct wl_resource *resource)
2594{
2595 wl_resource_destroy(resource);
2596}
2597
2598static void
2599relative_pointer_manager_get_relative_pointer(struct wl_client *client,
2600 struct wl_resource *resource,
2601 uint32_t id,
2602 struct wl_resource *pointer_resource)
2603{
2604 struct weston_pointer *pointer =
2605 wl_resource_get_user_data(pointer_resource);
2606 struct weston_pointer_client *pointer_client;
2607 struct wl_resource *cr;
2608
2609 cr = wl_resource_create(client, &zwp_relative_pointer_v1_interface,
2610 wl_resource_get_version(resource), id);
2611 if (cr == NULL) {
2612 wl_client_post_no_memory(client);
2613 return;
2614 }
2615
2616 pointer_client = weston_pointer_ensure_pointer_client(pointer, client);
2617 if (!pointer_client) {
2618 wl_client_post_no_memory(client);
2619 return;
2620 }
2621
2622 wl_list_insert(&pointer_client->relative_pointer_resources,
2623 wl_resource_get_link(cr));
2624 wl_resource_set_implementation(cr, &relative_pointer_interface,
2625 pointer,
2626 unbind_pointer_client_resource);
2627}
2628
2629static const struct zwp_relative_pointer_manager_v1_interface relative_pointer_manager = {
2630 relative_pointer_manager_destroy,
2631 relative_pointer_manager_get_relative_pointer,
2632};
2633
2634static void
2635bind_relative_pointer_manager(struct wl_client *client, void *data,
2636 uint32_t version, uint32_t id)
2637{
2638 struct weston_compositor *compositor = data;
2639 struct wl_resource *resource;
2640
2641 resource = wl_resource_create(client,
2642 &zwp_relative_pointer_manager_v1_interface,
2643 1, id);
2644
2645 wl_resource_set_implementation(resource, &relative_pointer_manager,
2646 compositor,
2647 NULL);
2648}
2649
Giulio Camuffo0358af42016-06-02 21:48:08 +03002650WL_EXPORT int
2651weston_compositor_set_xkb_rule_names(struct weston_compositor *ec,
2652 struct xkb_rule_names *names)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002653{
2654 if (ec->xkb_context == NULL) {
2655 ec->xkb_context = xkb_context_new(0);
2656 if (ec->xkb_context == NULL) {
2657 weston_log("failed to create XKB context\n");
2658 return -1;
2659 }
2660 }
2661
2662 if (names)
2663 ec->xkb_names = *names;
2664 if (!ec->xkb_names.rules)
2665 ec->xkb_names.rules = strdup("evdev");
2666 if (!ec->xkb_names.model)
2667 ec->xkb_names.model = strdup("pc105");
2668 if (!ec->xkb_names.layout)
2669 ec->xkb_names.layout = strdup("us");
2670
2671 return 0;
2672}
2673
Stefan Schmidtfda26522013-09-17 10:54:09 +01002674static void
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002675weston_xkb_info_destroy(struct weston_xkb_info *xkb_info)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002676{
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002677 if (--xkb_info->ref_count > 0)
2678 return;
2679
Ran Benitac9c74152014-08-19 23:59:52 +03002680 xkb_keymap_unref(xkb_info->keymap);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002681
2682 if (xkb_info->keymap_area)
2683 munmap(xkb_info->keymap_area, xkb_info->keymap_size);
2684 if (xkb_info->keymap_fd >= 0)
2685 close(xkb_info->keymap_fd);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002686 free(xkb_info);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002687}
2688
2689void
2690weston_compositor_xkb_destroy(struct weston_compositor *ec)
2691{
2692 free((char *) ec->xkb_names.rules);
2693 free((char *) ec->xkb_names.model);
2694 free((char *) ec->xkb_names.layout);
2695 free((char *) ec->xkb_names.variant);
2696 free((char *) ec->xkb_names.options);
Stefan Schmidtfda26522013-09-17 10:54:09 +01002697
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002698 if (ec->xkb_info)
2699 weston_xkb_info_destroy(ec->xkb_info);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002700 xkb_context_unref(ec->xkb_context);
2701}
2702
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002703static struct weston_xkb_info *
2704weston_xkb_info_create(struct xkb_keymap *keymap)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002705{
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002706 struct weston_xkb_info *xkb_info = zalloc(sizeof *xkb_info);
2707 if (xkb_info == NULL)
2708 return NULL;
2709
Ran Benita2e1968f2014-08-19 23:59:51 +03002710 xkb_info->keymap = xkb_keymap_ref(keymap);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002711 xkb_info->ref_count = 1;
2712
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002713 char *keymap_str;
2714
Ran Benita2e1968f2014-08-19 23:59:51 +03002715 xkb_info->shift_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2716 XKB_MOD_NAME_SHIFT);
2717 xkb_info->caps_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2718 XKB_MOD_NAME_CAPS);
2719 xkb_info->ctrl_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2720 XKB_MOD_NAME_CTRL);
2721 xkb_info->alt_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2722 XKB_MOD_NAME_ALT);
2723 xkb_info->mod2_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2724 "Mod2");
2725 xkb_info->mod3_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2726 "Mod3");
2727 xkb_info->super_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2728 XKB_MOD_NAME_LOGO);
2729 xkb_info->mod5_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2730 "Mod5");
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002731
Ran Benita2e1968f2014-08-19 23:59:51 +03002732 xkb_info->num_led = xkb_keymap_led_get_index(xkb_info->keymap,
2733 XKB_LED_NAME_NUM);
2734 xkb_info->caps_led = xkb_keymap_led_get_index(xkb_info->keymap,
2735 XKB_LED_NAME_CAPS);
2736 xkb_info->scroll_led = xkb_keymap_led_get_index(xkb_info->keymap,
2737 XKB_LED_NAME_SCROLL);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002738
Ran Benita2e1968f2014-08-19 23:59:51 +03002739 keymap_str = xkb_keymap_get_as_string(xkb_info->keymap,
2740 XKB_KEYMAP_FORMAT_TEXT_V1);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002741 if (keymap_str == NULL) {
2742 weston_log("failed to get string version of keymap\n");
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002743 goto err_keymap;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002744 }
2745 xkb_info->keymap_size = strlen(keymap_str) + 1;
2746
2747 xkb_info->keymap_fd = os_create_anonymous_file(xkb_info->keymap_size);
2748 if (xkb_info->keymap_fd < 0) {
2749 weston_log("creating a keymap file for %lu bytes failed: %m\n",
2750 (unsigned long) xkb_info->keymap_size);
2751 goto err_keymap_str;
2752 }
2753
2754 xkb_info->keymap_area = mmap(NULL, xkb_info->keymap_size,
2755 PROT_READ | PROT_WRITE,
2756 MAP_SHARED, xkb_info->keymap_fd, 0);
2757 if (xkb_info->keymap_area == MAP_FAILED) {
2758 weston_log("failed to mmap() %lu bytes\n",
2759 (unsigned long) xkb_info->keymap_size);
2760 goto err_dev_zero;
2761 }
2762 strcpy(xkb_info->keymap_area, keymap_str);
2763 free(keymap_str);
2764
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002765 return xkb_info;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002766
2767err_dev_zero:
2768 close(xkb_info->keymap_fd);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002769err_keymap_str:
2770 free(keymap_str);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002771err_keymap:
Ran Benita2e1968f2014-08-19 23:59:51 +03002772 xkb_keymap_unref(xkb_info->keymap);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002773 free(xkb_info);
2774 return NULL;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002775}
2776
2777static int
2778weston_compositor_build_global_keymap(struct weston_compositor *ec)
2779{
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002780 struct xkb_keymap *keymap;
2781
2782 if (ec->xkb_info != NULL)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002783 return 0;
2784
Ran Benita2e1968f2014-08-19 23:59:51 +03002785 keymap = xkb_keymap_new_from_names(ec->xkb_context,
2786 &ec->xkb_names,
2787 0);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002788 if (keymap == NULL) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002789 weston_log("failed to compile global XKB keymap\n");
2790 weston_log(" tried rules %s, model %s, layout %s, variant %s, "
2791 "options %s\n",
2792 ec->xkb_names.rules, ec->xkb_names.model,
2793 ec->xkb_names.layout, ec->xkb_names.variant,
2794 ec->xkb_names.options);
2795 return -1;
2796 }
2797
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002798 ec->xkb_info = weston_xkb_info_create(keymap);
Rui Matos73d93952013-10-24 19:28:41 +02002799 xkb_keymap_unref(keymap);
Stefan Schmidtfda26522013-09-17 10:54:09 +01002800 if (ec->xkb_info == NULL)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002801 return -1;
2802
2803 return 0;
2804}
2805
Rui Matos65196bc2013-10-10 19:44:19 +02002806WL_EXPORT void
2807weston_seat_update_keymap(struct weston_seat *seat, struct xkb_keymap *keymap)
2808{
Derek Foreman1281a362015-07-31 16:55:32 -05002809 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
2810
2811 if (!keyboard || !keymap)
Rui Matos65196bc2013-10-10 19:44:19 +02002812 return;
2813
Derek Foreman1281a362015-07-31 16:55:32 -05002814 xkb_keymap_unref(keyboard->pending_keymap);
2815 keyboard->pending_keymap = xkb_keymap_ref(keymap);
Rui Matos65196bc2013-10-10 19:44:19 +02002816
Derek Foreman1281a362015-07-31 16:55:32 -05002817 if (keyboard->keys.size == 0)
Rui Matos65196bc2013-10-10 19:44:19 +02002818 update_keymap(seat);
Rui Matos65196bc2013-10-10 19:44:19 +02002819}
2820
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002821WL_EXPORT int
2822weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap)
2823{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002824 struct weston_keyboard *keyboard;
2825
Derek Foreman1281a362015-07-31 16:55:32 -05002826 if (seat->keyboard_state) {
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002827 seat->keyboard_device_count += 1;
2828 if (seat->keyboard_device_count == 1)
2829 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002830 return 0;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002831 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002832
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002833 keyboard = weston_keyboard_create();
2834 if (keyboard == NULL) {
2835 weston_log("failed to allocate weston keyboard struct\n");
2836 return -1;
2837 }
2838
Derek Foreman185d1582017-06-28 11:17:23 -05002839 if (keymap != NULL) {
2840 keyboard->xkb_info = weston_xkb_info_create(keymap);
2841 if (keyboard->xkb_info == NULL)
Ander Conselvan de Oliveira4d363cf2014-01-31 17:35:45 +02002842 goto err;
Derek Foreman185d1582017-06-28 11:17:23 -05002843 } else {
2844 if (weston_compositor_build_global_keymap(seat->compositor) < 0)
2845 goto err;
2846 keyboard->xkb_info = seat->compositor->xkb_info;
2847 keyboard->xkb_info->ref_count++;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002848 }
Derek Foreman185d1582017-06-28 11:17:23 -05002849
2850 keyboard->xkb_state.state = xkb_state_new(keyboard->xkb_info->keymap);
2851 if (keyboard->xkb_state.state == NULL) {
2852 weston_log("failed to initialise XKB state\n");
2853 goto err;
2854 }
2855
2856 keyboard->xkb_state.leds = 0;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002857
Derek Foreman1281a362015-07-31 16:55:32 -05002858 seat->keyboard_state = keyboard;
Ander Conselvan de Oliveira4d363cf2014-01-31 17:35:45 +02002859 seat->keyboard_device_count = 1;
2860 keyboard->seat = seat;
2861
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002862 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002863
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002864 return 0;
Ander Conselvan de Oliveira4d363cf2014-01-31 17:35:45 +02002865
2866err:
2867 if (keyboard->xkb_info)
2868 weston_xkb_info_destroy(keyboard->xkb_info);
2869 free(keyboard);
2870
2871 return -1;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002872}
2873
Jonas Ådahl91fed542013-12-03 09:14:27 +01002874static void
2875weston_keyboard_reset_state(struct weston_keyboard *keyboard)
2876{
2877 struct weston_seat *seat = keyboard->seat;
2878 struct xkb_state *state;
2879
Derek Foreman185d1582017-06-28 11:17:23 -05002880 state = xkb_state_new(keyboard->xkb_info->keymap);
2881 if (!state) {
2882 weston_log("failed to reset XKB state\n");
2883 return;
Jonas Ådahl91fed542013-12-03 09:14:27 +01002884 }
Derek Foreman185d1582017-06-28 11:17:23 -05002885 xkb_state_unref(keyboard->xkb_state.state);
2886 keyboard->xkb_state.state = state;
2887
2888 keyboard->xkb_state.leds = 0;
Jonas Ådahl91fed542013-12-03 09:14:27 +01002889
2890 seat->modifier_state = 0;
2891}
2892
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002893WL_EXPORT void
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002894weston_seat_release_keyboard(struct weston_seat *seat)
2895{
2896 seat->keyboard_device_count--;
Derek Foremand621df22014-11-19 11:04:12 -06002897 assert(seat->keyboard_device_count >= 0);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002898 if (seat->keyboard_device_count == 0) {
Derek Foreman1281a362015-07-31 16:55:32 -05002899 weston_keyboard_set_focus(seat->keyboard_state, NULL);
2900 weston_keyboard_cancel_grab(seat->keyboard_state);
2901 weston_keyboard_reset_state(seat->keyboard_state);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002902 seat_send_updated_caps(seat);
2903 }
2904}
2905
2906WL_EXPORT void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002907weston_seat_init_pointer(struct weston_seat *seat)
2908{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002909 struct weston_pointer *pointer;
2910
Derek Foreman1281a362015-07-31 16:55:32 -05002911 if (seat->pointer_state) {
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002912 seat->pointer_device_count += 1;
2913 if (seat->pointer_device_count == 1)
2914 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002915 return;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002916 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002917
Giulio Camuffocdb4d292013-11-14 23:42:53 +01002918 pointer = weston_pointer_create(seat);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002919 if (pointer == NULL)
2920 return;
2921
Derek Foreman1281a362015-07-31 16:55:32 -05002922 seat->pointer_state = pointer;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002923 seat->pointer_device_count = 1;
2924 pointer->seat = seat;
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002925
2926 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002927}
2928
2929WL_EXPORT void
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002930weston_seat_release_pointer(struct weston_seat *seat)
2931{
Derek Foreman1281a362015-07-31 16:55:32 -05002932 struct weston_pointer *pointer = seat->pointer_state;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002933
2934 seat->pointer_device_count--;
2935 if (seat->pointer_device_count == 0) {
Derek Foremanf9318d12015-05-11 15:40:11 -05002936 weston_pointer_clear_focus(pointer);
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02002937 weston_pointer_cancel_grab(pointer);
Jonas Ådahl630bae82013-10-17 23:04:06 +02002938
Jonas Ådahla4932742013-10-17 23:04:07 +02002939 if (pointer->sprite)
2940 pointer_unmap_sprite(pointer);
2941
Jonas Ådahl3e12e632013-12-02 22:05:05 +01002942 weston_pointer_reset_state(pointer);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002943 seat_send_updated_caps(seat);
Derek Foremanfd5ca512015-01-07 15:00:25 -06002944
2945 /* seat->pointer is intentionally not destroyed so that
2946 * a newly attached pointer on this seat will retain
2947 * the previous cursor co-ordinates.
2948 */
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002949 }
2950}
2951
2952WL_EXPORT void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002953weston_seat_init_touch(struct weston_seat *seat)
2954{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002955 struct weston_touch *touch;
2956
Derek Foreman1281a362015-07-31 16:55:32 -05002957 if (seat->touch_state) {
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002958 seat->touch_device_count += 1;
2959 if (seat->touch_device_count == 1)
2960 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002961 return;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002962 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002963
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002964 touch = weston_touch_create();
2965 if (touch == NULL)
2966 return;
2967
Derek Foreman1281a362015-07-31 16:55:32 -05002968 seat->touch_state = touch;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002969 seat->touch_device_count = 1;
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002970 touch->seat = seat;
2971
2972 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002973}
2974
2975WL_EXPORT void
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002976weston_seat_release_touch(struct weston_seat *seat)
2977{
2978 seat->touch_device_count--;
2979 if (seat->touch_device_count == 0) {
Derek Foreman1281a362015-07-31 16:55:32 -05002980 weston_touch_set_focus(seat->touch_state, NULL);
2981 weston_touch_cancel_grab(seat->touch_state);
2982 weston_touch_reset_state(seat->touch_state);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002983 seat_send_updated_caps(seat);
2984 }
2985}
2986
2987WL_EXPORT void
Rob Bradford9af5f9e2013-05-31 18:09:50 +01002988weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec,
2989 const char *seat_name)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002990{
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04002991 memset(seat, 0, sizeof *seat);
2992
Kristian Høgsberge3148752013-05-06 23:19:49 -04002993 seat->selection_data_source = NULL;
2994 wl_list_init(&seat->base_resource_list);
2995 wl_signal_init(&seat->selection_signal);
2996 wl_list_init(&seat->drag_resource_list);
Kristian Høgsberge3148752013-05-06 23:19:49 -04002997 wl_signal_init(&seat->destroy_signal);
Jason Ekstranda4ab5422014-04-02 19:53:45 -05002998 wl_signal_init(&seat->updated_caps_signal);
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04002999
Peter Hutterer87743e92016-01-18 16:38:22 +10003000 seat->global = wl_global_create(ec->wl_display, &wl_seat_interface, 5,
Kristian Høgsberg919cddb2013-07-08 19:03:57 -04003001 seat, bind_seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003002
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003003 seat->compositor = ec;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003004 seat->modifier_state = 0;
Rob Bradford9af5f9e2013-05-31 18:09:50 +01003005 seat->seat_name = strdup(seat_name);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003006
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003007 wl_list_insert(ec->seat_list.prev, &seat->link);
3008
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003009 clipboard_create(seat);
3010
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003011 wl_signal_emit(&ec->seat_created_signal, seat);
3012}
3013
3014WL_EXPORT void
3015weston_seat_release(struct weston_seat *seat)
3016{
3017 wl_list_remove(&seat->link);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003018
Jonas Ådahl1afb2382014-01-03 19:46:51 +01003019 if (seat->saved_kbd_focus)
3020 wl_list_remove(&seat->saved_kbd_focus_listener.link);
3021
Derek Foreman1281a362015-07-31 16:55:32 -05003022 if (seat->pointer_state)
3023 weston_pointer_destroy(seat->pointer_state);
3024 if (seat->keyboard_state)
3025 weston_keyboard_destroy(seat->keyboard_state);
3026 if (seat->touch_state)
3027 weston_touch_destroy(seat->touch_state);
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04003028
Rob Bradford9af5f9e2013-05-31 18:09:50 +01003029 free (seat->seat_name);
3030
Kristian Høgsberg919cddb2013-07-08 19:03:57 -04003031 wl_global_destroy(seat->global);
Kristian Høgsbergaaadc772013-07-08 16:20:31 -04003032
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04003033 wl_signal_emit(&seat->destroy_signal, seat);
3034}
Derek Foreman1281a362015-07-31 16:55:32 -05003035
3036/** Get a seat's keyboard pointer
3037 *
3038 * \param seat The seat to query
3039 * \return The seat's keyboard pointer, or NULL if no keyboard is present
3040 *
3041 * The keyboard pointer for a seat isn't freed when all keyboards are removed,
3042 * so it should only be used when the seat's keyboard_device_count is greater
3043 * than zero. This function does that test and only returns a pointer
3044 * when a keyboard is present.
3045 */
3046WL_EXPORT struct weston_keyboard *
3047weston_seat_get_keyboard(struct weston_seat *seat)
3048{
3049 if (!seat)
3050 return NULL;
3051
3052 if (seat->keyboard_device_count)
3053 return seat->keyboard_state;
3054
3055 return NULL;
3056}
3057
3058/** Get a seat's pointer pointer
3059 *
3060 * \param seat The seat to query
3061 * \return The seat's pointer pointer, or NULL if no pointer device is present
3062 *
3063 * The pointer pointer for a seat isn't freed when all mice are removed,
3064 * so it should only be used when the seat's pointer_device_count is greater
3065 * than zero. This function does that test and only returns a pointer
3066 * when a pointing device is present.
3067 */
3068WL_EXPORT struct weston_pointer *
3069weston_seat_get_pointer(struct weston_seat *seat)
3070{
3071 if (!seat)
3072 return NULL;
3073
3074 if (seat->pointer_device_count)
3075 return seat->pointer_state;
3076
3077 return NULL;
3078}
3079
Jonas Ådahld3414f22016-07-22 17:56:31 +08003080static const struct zwp_locked_pointer_v1_interface locked_pointer_interface;
3081static const struct zwp_confined_pointer_v1_interface confined_pointer_interface;
3082
3083static enum pointer_constraint_type
3084pointer_constraint_get_type(struct weston_pointer_constraint *constraint)
3085{
3086 if (wl_resource_instance_of(constraint->resource,
3087 &zwp_locked_pointer_v1_interface,
3088 &locked_pointer_interface)) {
3089 return POINTER_CONSTRAINT_TYPE_LOCK;
3090 } else if (wl_resource_instance_of(constraint->resource,
3091 &zwp_confined_pointer_v1_interface,
3092 &confined_pointer_interface)) {
3093 return POINTER_CONSTRAINT_TYPE_CONFINE;
3094 }
3095
3096 abort();
3097 return 0;
3098}
3099
3100static void
3101pointer_constraint_notify_activated(struct weston_pointer_constraint *constraint)
3102{
3103 struct wl_resource *resource = constraint->resource;
3104
3105 switch (pointer_constraint_get_type(constraint)) {
3106 case POINTER_CONSTRAINT_TYPE_LOCK:
3107 zwp_locked_pointer_v1_send_locked(resource);
3108 break;
3109 case POINTER_CONSTRAINT_TYPE_CONFINE:
3110 zwp_confined_pointer_v1_send_confined(resource);
3111 break;
3112 }
3113}
3114
3115static void
3116pointer_constraint_notify_deactivated(struct weston_pointer_constraint *constraint)
3117{
3118 struct wl_resource *resource = constraint->resource;
3119
3120 switch (pointer_constraint_get_type(constraint)) {
3121 case POINTER_CONSTRAINT_TYPE_LOCK:
3122 zwp_locked_pointer_v1_send_unlocked(resource);
3123 break;
3124 case POINTER_CONSTRAINT_TYPE_CONFINE:
3125 zwp_confined_pointer_v1_send_unconfined(resource);
3126 break;
3127 }
3128}
3129
3130static struct weston_pointer_constraint *
3131get_pointer_constraint_for_pointer(struct weston_surface *surface,
3132 struct weston_pointer *pointer)
3133{
3134 struct weston_pointer_constraint *constraint;
3135
3136 wl_list_for_each(constraint, &surface->pointer_constraints, link) {
3137 if (constraint->pointer == pointer)
3138 return constraint;
3139 }
3140
3141 return NULL;
3142}
3143
Derek Foreman1281a362015-07-31 16:55:32 -05003144/** Get a seat's touch pointer
3145 *
3146 * \param seat The seat to query
3147 * \return The seat's touch pointer, or NULL if no touch device is present
3148 *
3149 * The touch pointer for a seat isn't freed when all touch devices are removed,
3150 * so it should only be used when the seat's touch_device_count is greater
3151 * than zero. This function does that test and only returns a pointer
3152 * when a touch device is present.
3153 */
3154WL_EXPORT struct weston_touch *
3155weston_seat_get_touch(struct weston_seat *seat)
3156{
3157 if (!seat)
3158 return NULL;
3159
3160 if (seat->touch_device_count)
3161 return seat->touch_state;
3162
3163 return NULL;
3164}
Bryce Harrington24f917e2016-06-29 19:04:07 -07003165
3166/** Sets the keyboard focus to the given surface
3167 *
3168 * \param seat The seat to query
3169 */
3170WL_EXPORT void
3171weston_seat_set_keyboard_focus(struct weston_seat *seat,
3172 struct weston_surface *surface)
3173{
3174 struct weston_compositor *compositor = seat->compositor;
3175 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Jonas Ådahlf7deb6a2016-07-22 17:50:26 +08003176 struct weston_surface_activation_data activation_data;
Bryce Harrington24f917e2016-06-29 19:04:07 -07003177
Jonas Ådahlef8e1c32016-03-15 20:28:51 +08003178 if (keyboard && keyboard->focus != surface) {
Bryce Harrington24f917e2016-06-29 19:04:07 -07003179 weston_keyboard_set_focus(keyboard, surface);
3180 wl_data_device_set_keyboard_focus(seat);
3181 }
3182
Jonas Ådahl94e2e2d2014-10-18 18:42:19 +02003183 inc_activate_serial(compositor);
Jonas Ådahlf7deb6a2016-07-22 17:50:26 +08003184
3185 activation_data = (struct weston_surface_activation_data) {
3186 .surface = surface,
3187 .seat = seat,
3188 };
3189 wl_signal_emit(&compositor->activate_signal, &activation_data);
Bryce Harrington24f917e2016-06-29 19:04:07 -07003190}
Jonas Ådahl30d61d82014-10-22 21:21:17 +02003191
Jonas Ådahld3414f22016-07-22 17:56:31 +08003192static void
3193enable_pointer_constraint(struct weston_pointer_constraint *constraint,
3194 struct weston_view *view)
3195{
3196 assert(constraint->view == NULL);
3197 constraint->view = view;
3198 pointer_constraint_notify_activated(constraint);
3199 weston_pointer_start_grab(constraint->pointer, &constraint->grab);
3200 wl_list_remove(&constraint->surface_destroy_listener.link);
3201 wl_list_init(&constraint->surface_destroy_listener.link);
3202}
3203
3204static bool
3205is_pointer_constraint_enabled(struct weston_pointer_constraint *constraint)
3206{
3207 return constraint->view != NULL;
3208}
3209
3210static void
3211weston_pointer_constraint_disable(struct weston_pointer_constraint *constraint)
3212{
3213 constraint->view = NULL;
3214 pointer_constraint_notify_deactivated(constraint);
3215 weston_pointer_end_grab(constraint->grab.pointer);
3216}
3217
3218void
3219weston_pointer_constraint_destroy(struct weston_pointer_constraint *constraint)
3220{
3221 if (is_pointer_constraint_enabled(constraint))
3222 weston_pointer_constraint_disable(constraint);
3223
3224 wl_list_remove(&constraint->pointer_destroy_listener.link);
3225 wl_list_remove(&constraint->surface_destroy_listener.link);
3226 wl_list_remove(&constraint->surface_commit_listener.link);
3227 wl_list_remove(&constraint->surface_activate_listener.link);
3228
3229 wl_resource_set_user_data(constraint->resource, NULL);
3230 pixman_region32_fini(&constraint->region);
3231 wl_list_remove(&constraint->link);
3232 free(constraint);
3233}
3234
3235static void
3236disable_pointer_constraint(struct weston_pointer_constraint *constraint)
3237{
3238 switch (constraint->lifetime) {
3239 case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT:
3240 weston_pointer_constraint_destroy(constraint);
3241 break;
3242 case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT:
3243 weston_pointer_constraint_disable(constraint);
3244 break;
3245 }
3246}
3247
3248static bool
3249is_within_constraint_region(struct weston_pointer_constraint *constraint,
3250 wl_fixed_t sx, wl_fixed_t sy)
3251{
3252 struct weston_surface *surface = constraint->surface;
3253 pixman_region32_t constraint_region;
3254 bool result;
3255
3256 pixman_region32_init(&constraint_region);
3257 pixman_region32_intersect(&constraint_region,
3258 &surface->input,
3259 &constraint->region);
3260 result = pixman_region32_contains_point(&constraint_region,
3261 wl_fixed_to_int(sx),
3262 wl_fixed_to_int(sy),
3263 NULL);
3264 pixman_region32_fini(&constraint_region);
3265
3266 return result;
3267}
3268
3269static void
3270maybe_enable_pointer_constraint(struct weston_pointer_constraint *constraint)
3271{
3272 struct weston_surface *surface = constraint->surface;
3273 struct weston_view *vit;
3274 struct weston_view *view = NULL;
3275 struct weston_pointer *pointer = constraint->pointer;
3276 struct weston_keyboard *keyboard;
3277 struct weston_seat *seat = pointer->seat;
3278 int32_t x, y;
3279
3280 /* Postpone if no view of the surface was most recently clicked. */
3281 wl_list_for_each(vit, &surface->views, surface_link) {
3282 if (vit->click_to_activate_serial ==
3283 surface->compositor->activate_serial) {
3284 view = vit;
3285 }
3286 }
3287 if (view == NULL)
3288 return;
3289
3290 /* Postpone if surface doesn't have keyboard focus. */
3291 keyboard = weston_seat_get_keyboard(seat);
3292 if (!keyboard || keyboard->focus != surface)
3293 return;
3294
3295 /* Postpone constraint if the pointer is not within the
3296 * constraint region.
3297 */
3298 weston_view_from_global(view,
3299 wl_fixed_to_int(pointer->x),
3300 wl_fixed_to_int(pointer->y),
3301 &x, &y);
3302 if (!is_within_constraint_region(constraint,
3303 wl_fixed_from_int(x),
3304 wl_fixed_from_int(y)))
3305 return;
3306
3307 enable_pointer_constraint(constraint, view);
3308}
3309
3310static void
3311locked_pointer_grab_pointer_focus(struct weston_pointer_grab *grab)
3312{
3313}
3314
3315static void
3316locked_pointer_grab_pointer_motion(struct weston_pointer_grab *grab,
3317 uint32_t time,
3318 struct weston_pointer_motion_event *event)
3319{
Quentin Glidiccde13452016-08-12 10:41:32 +02003320 pointer_send_relative_motion(grab->pointer, time, event);
Jonas Ådahld3414f22016-07-22 17:56:31 +08003321}
3322
3323static void
3324locked_pointer_grab_pointer_button(struct weston_pointer_grab *grab,
3325 uint32_t time,
3326 uint32_t button,
3327 uint32_t state_w)
3328{
3329 weston_pointer_send_button(grab->pointer, time, button, state_w);
3330}
3331
3332static void
3333locked_pointer_grab_pointer_axis(struct weston_pointer_grab *grab,
3334 uint32_t time,
3335 struct weston_pointer_axis_event *event)
3336{
3337 weston_pointer_send_axis(grab->pointer, time, event);
3338}
3339
3340static void
3341locked_pointer_grab_pointer_axis_source(struct weston_pointer_grab *grab,
3342 uint32_t source)
3343{
3344 weston_pointer_send_axis_source(grab->pointer, source);
3345}
3346
3347static void
3348locked_pointer_grab_pointer_frame(struct weston_pointer_grab *grab)
3349{
3350 weston_pointer_send_frame(grab->pointer);
3351}
3352
3353static void
3354locked_pointer_grab_pointer_cancel(struct weston_pointer_grab *grab)
3355{
3356 struct weston_pointer_constraint *constraint =
3357 container_of(grab, struct weston_pointer_constraint, grab);
3358
3359 disable_pointer_constraint(constraint);
3360}
3361
3362static const struct weston_pointer_grab_interface
3363 locked_pointer_grab_interface = {
3364 locked_pointer_grab_pointer_focus,
3365 locked_pointer_grab_pointer_motion,
3366 locked_pointer_grab_pointer_button,
3367 locked_pointer_grab_pointer_axis,
3368 locked_pointer_grab_pointer_axis_source,
3369 locked_pointer_grab_pointer_frame,
3370 locked_pointer_grab_pointer_cancel,
3371};
3372
3373static void
3374pointer_constraint_constrain_resource_destroyed(struct wl_resource *resource)
3375{
3376 struct weston_pointer_constraint *constraint =
3377 wl_resource_get_user_data(resource);
3378
3379 if (!constraint)
3380 return;
3381
3382 weston_pointer_constraint_destroy(constraint);
3383}
3384
3385static void
3386pointer_constraint_surface_activate(struct wl_listener *listener, void *data)
3387{
3388 struct weston_surface_activation_data *activation = data;
3389 struct weston_pointer *pointer;
3390 struct weston_surface *focus = activation->surface;
3391 struct weston_pointer_constraint *constraint =
3392 container_of(listener, struct weston_pointer_constraint,
3393 surface_activate_listener);
3394 bool is_constraint_surface;
3395
3396 pointer = weston_seat_get_pointer(activation->seat);
3397 if (!pointer)
3398 return;
3399
3400 is_constraint_surface =
3401 get_pointer_constraint_for_pointer(focus, pointer) == constraint;
3402
3403 if (is_constraint_surface &&
3404 !is_pointer_constraint_enabled(constraint))
3405 maybe_enable_pointer_constraint(constraint);
3406 else if (!is_constraint_surface &&
3407 is_pointer_constraint_enabled(constraint))
3408 disable_pointer_constraint(constraint);
3409}
3410
3411static void
3412pointer_constraint_pointer_destroyed(struct wl_listener *listener, void *data)
3413{
3414 struct weston_pointer_constraint *constraint =
3415 container_of(listener, struct weston_pointer_constraint,
3416 pointer_destroy_listener);
3417
3418 weston_pointer_constraint_destroy(constraint);
3419}
3420
3421static void
3422pointer_constraint_surface_destroyed(struct wl_listener *listener, void *data)
3423{
3424 struct weston_pointer_constraint *constraint =
3425 container_of(listener, struct weston_pointer_constraint,
3426 surface_destroy_listener);
3427
3428 weston_pointer_constraint_destroy(constraint);
3429}
3430
3431static void
3432pointer_constraint_surface_committed(struct wl_listener *listener, void *data)
3433{
3434 struct weston_pointer_constraint *constraint =
3435 container_of(listener, struct weston_pointer_constraint,
3436 surface_commit_listener);
3437
3438 if (constraint->region_is_pending) {
3439 constraint->region_is_pending = false;
3440 pixman_region32_copy(&constraint->region,
3441 &constraint->region_pending);
3442 pixman_region32_fini(&constraint->region_pending);
3443 pixman_region32_init(&constraint->region_pending);
3444 }
3445
3446 if (constraint->hint_is_pending) {
3447 constraint->hint_is_pending = false;
3448
3449 constraint->hint_is_pending = true;
3450 constraint->hint_x = constraint->hint_x_pending;
3451 constraint->hint_y = constraint->hint_y_pending;
3452 }
3453
3454 if (pointer_constraint_get_type(constraint) ==
3455 POINTER_CONSTRAINT_TYPE_CONFINE &&
3456 is_pointer_constraint_enabled(constraint))
3457 maybe_warp_confined_pointer(constraint);
3458}
3459
3460static struct weston_pointer_constraint *
3461weston_pointer_constraint_create(struct weston_surface *surface,
3462 struct weston_pointer *pointer,
3463 struct weston_region *region,
3464 enum zwp_pointer_constraints_v1_lifetime lifetime,
3465 struct wl_resource *cr,
3466 const struct weston_pointer_grab_interface *grab_interface)
3467{
3468 struct weston_pointer_constraint *constraint;
3469
3470 constraint = zalloc(sizeof *constraint);
3471 if (!constraint)
3472 return NULL;
3473
3474 constraint->lifetime = lifetime;
3475 pixman_region32_init(&constraint->region);
3476 pixman_region32_init(&constraint->region_pending);
3477 wl_list_insert(&surface->pointer_constraints, &constraint->link);
3478 constraint->surface = surface;
3479 constraint->pointer = pointer;
3480 constraint->resource = cr;
3481 constraint->grab.interface = grab_interface;
3482 if (region) {
3483 pixman_region32_copy(&constraint->region,
3484 &region->region);
3485 } else {
3486 pixman_region32_fini(&constraint->region);
3487 region_init_infinite(&constraint->region);
3488 }
3489
3490 constraint->surface_activate_listener.notify =
3491 pointer_constraint_surface_activate;
3492 constraint->surface_destroy_listener.notify =
3493 pointer_constraint_surface_destroyed;
3494 constraint->surface_commit_listener.notify =
3495 pointer_constraint_surface_committed;
3496 constraint->pointer_destroy_listener.notify =
3497 pointer_constraint_pointer_destroyed;
3498
3499 wl_signal_add(&surface->compositor->activate_signal,
3500 &constraint->surface_activate_listener);
3501 wl_signal_add(&pointer->destroy_signal,
3502 &constraint->pointer_destroy_listener);
3503 wl_signal_add(&surface->destroy_signal,
3504 &constraint->surface_destroy_listener);
3505 wl_signal_add(&surface->commit_signal,
3506 &constraint->surface_commit_listener);
3507
3508 return constraint;
3509}
3510
3511static void
3512init_pointer_constraint(struct wl_resource *pointer_constraints_resource,
3513 uint32_t id,
3514 struct weston_surface *surface,
3515 struct weston_pointer *pointer,
3516 struct weston_region *region,
3517 enum zwp_pointer_constraints_v1_lifetime lifetime,
3518 const struct wl_interface *interface,
3519 const void *implementation,
3520 const struct weston_pointer_grab_interface *grab_interface)
3521{
3522 struct wl_client *client =
3523 wl_resource_get_client(pointer_constraints_resource);
3524 struct wl_resource *cr;
3525 struct weston_pointer_constraint *constraint;
3526
3527 if (get_pointer_constraint_for_pointer(surface, pointer)) {
3528 wl_resource_post_error(pointer_constraints_resource,
3529 ZWP_POINTER_CONSTRAINTS_V1_ERROR_ALREADY_CONSTRAINED,
3530 "the pointer has a lock/confine request on this surface");
3531 return;
3532 }
3533
3534 cr = wl_resource_create(client, interface,
3535 wl_resource_get_version(pointer_constraints_resource),
3536 id);
3537 if (cr == NULL) {
3538 wl_client_post_no_memory(client);
3539 return;
3540 }
3541
3542 constraint = weston_pointer_constraint_create(surface, pointer,
3543 region, lifetime,
3544 cr, grab_interface);
3545 if (constraint == NULL) {
3546 wl_client_post_no_memory(client);
3547 return;
3548 }
3549
3550 wl_resource_set_implementation(cr, implementation, constraint,
3551 pointer_constraint_constrain_resource_destroyed);
3552
3553 maybe_enable_pointer_constraint(constraint);
3554}
3555
3556static void
3557pointer_constraints_destroy(struct wl_client *client,
3558 struct wl_resource *resource)
3559{
3560 wl_resource_destroy(resource);
3561}
3562
3563static void
3564locked_pointer_destroy(struct wl_client *client,
3565 struct wl_resource *resource)
3566{
3567 struct weston_pointer_constraint *constraint =
3568 wl_resource_get_user_data(resource);
3569 wl_fixed_t x, y;
3570
3571 if (constraint && constraint->view && constraint->hint_is_pending &&
3572 is_within_constraint_region(constraint,
3573 constraint->hint_x,
3574 constraint->hint_y)) {
3575 weston_view_to_global_fixed(constraint->view,
3576 constraint->hint_x,
3577 constraint->hint_y,
3578 &x, &y);
3579 weston_pointer_move_to(constraint->pointer, x, y);
3580 }
3581 wl_resource_destroy(resource);
3582}
3583
3584static void
3585locked_pointer_set_cursor_position_hint(struct wl_client *client,
3586 struct wl_resource *resource,
3587 wl_fixed_t surface_x,
3588 wl_fixed_t surface_y)
3589{
3590 struct weston_pointer_constraint *constraint =
3591 wl_resource_get_user_data(resource);
3592
3593 /* Ignore a set cursor hint that was sent after the lock was cancelled.
3594 */
3595 if (!constraint ||
3596 !constraint->resource ||
3597 constraint->resource != resource)
3598 return;
3599
3600 constraint->hint_is_pending = true;
3601 constraint->hint_x_pending = surface_x;
3602 constraint->hint_y_pending = surface_y;
3603}
3604
3605static void
3606locked_pointer_set_region(struct wl_client *client,
3607 struct wl_resource *resource,
3608 struct wl_resource *region_resource)
3609{
3610 struct weston_pointer_constraint *constraint =
3611 wl_resource_get_user_data(resource);
3612 struct weston_region *region = region_resource ?
3613 wl_resource_get_user_data(region_resource) : NULL;
3614
3615 if (!constraint)
3616 return;
3617
3618 if (region) {
3619 pixman_region32_copy(&constraint->region_pending,
3620 &region->region);
3621 } else {
3622 pixman_region32_fini(&constraint->region_pending);
3623 region_init_infinite(&constraint->region_pending);
3624 }
3625 constraint->region_is_pending = true;
3626}
3627
3628
3629static const struct zwp_locked_pointer_v1_interface locked_pointer_interface = {
3630 locked_pointer_destroy,
3631 locked_pointer_set_cursor_position_hint,
3632 locked_pointer_set_region,
3633};
3634
3635static void
3636pointer_constraints_lock_pointer(struct wl_client *client,
3637 struct wl_resource *resource,
3638 uint32_t id,
3639 struct wl_resource *surface_resource,
3640 struct wl_resource *pointer_resource,
3641 struct wl_resource *region_resource,
3642 uint32_t lifetime)
3643{
3644 struct weston_surface *surface =
3645 wl_resource_get_user_data(surface_resource);
3646 struct weston_pointer *pointer = wl_resource_get_user_data(pointer_resource);
3647 struct weston_region *region = region_resource ?
3648 wl_resource_get_user_data(region_resource) : NULL;
3649
3650 init_pointer_constraint(resource, id, surface, pointer, region, lifetime,
3651 &zwp_locked_pointer_v1_interface,
3652 &locked_pointer_interface,
3653 &locked_pointer_grab_interface);
3654}
3655
3656static void
3657confined_pointer_grab_pointer_focus(struct weston_pointer_grab *grab)
3658{
3659}
3660
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08003661static double
3662vec2d_cross_product(struct vec2d a, struct vec2d b)
3663{
3664 return a.x * b.y - a.y * b.x;
3665}
3666
3667static struct vec2d
3668vec2d_add(struct vec2d a, struct vec2d b)
3669{
3670 return (struct vec2d) {
3671 .x = a.x + b.x,
3672 .y = a.y + b.y,
3673 };
3674}
3675
3676static struct vec2d
3677vec2d_subtract(struct vec2d a, struct vec2d b)
3678{
3679 return (struct vec2d) {
3680 .x = a.x - b.x,
3681 .y = a.y - b.y,
3682 };
3683}
3684
3685static struct vec2d
3686vec2d_multiply_constant(double c, struct vec2d a)
3687{
3688 return (struct vec2d) {
3689 .x = c * a.x,
3690 .y = c * a.y,
3691 };
3692}
3693
3694static bool
3695lines_intersect(struct line *line1, struct line *line2,
3696 struct vec2d *intersection)
3697{
3698 struct vec2d p = line1->a;
3699 struct vec2d r = vec2d_subtract(line1->b, line1->a);
3700 struct vec2d q = line2->a;
3701 struct vec2d s = vec2d_subtract(line2->b, line2->a);
3702 double rxs;
3703 double sxr;
3704 double t;
3705 double u;
3706
3707 /*
3708 * The line (p, r) and (q, s) intersects where
3709 *
3710 * p + t r = q + u s
3711 *
3712 * Calculate t:
3713 *
3714 * (p + t r) × s = (q + u s) × s
3715 * p × s + t (r × s) = q × s + u (s × s)
3716 * p × s + t (r × s) = q × s
3717 * t (r × s) = q × s - p × s
3718 * t (r × s) = (q - p) × s
3719 * t = ((q - p) × s) / (r × s)
3720 *
3721 * Using the same method, for u we get:
3722 *
3723 * u = ((p - q) × r) / (s × r)
3724 */
3725
3726 rxs = vec2d_cross_product(r, s);
3727 sxr = vec2d_cross_product(s, r);
3728
3729 /* If r × s = 0 then the lines are either parallel or collinear. */
3730 if (fabs(rxs) < DBL_MIN)
3731 return false;
3732
3733 t = vec2d_cross_product(vec2d_subtract(q, p), s) / rxs;
3734 u = vec2d_cross_product(vec2d_subtract(p, q), r) / sxr;
3735
3736 /* The lines only intersect if 0 ≤ t ≤ 1 and 0 ≤ u ≤ 1. */
3737 if (t < 0.0 || t > 1.0 || u < 0.0 || u > 1.0)
3738 return false;
3739
3740 *intersection = vec2d_add(p, vec2d_multiply_constant(t, r));
3741 return true;
3742}
3743
3744static struct border *
3745add_border(struct wl_array *array,
3746 double x1, double y1,
3747 double x2, double y2,
3748 enum motion_direction blocking_dir)
3749{
3750 struct border *border = wl_array_add(array, sizeof *border);
3751
3752 *border = (struct border) {
3753 .line = (struct line) {
3754 .a = (struct vec2d) {
3755 .x = x1,
3756 .y = y1,
3757 },
3758 .b = (struct vec2d) {
3759 .x = x2,
3760 .y = y2,
3761 },
3762 },
3763 .blocking_dir = blocking_dir,
3764 };
3765
3766 return border;
3767}
3768
3769static int
3770compare_lines_x(const void *a, const void *b)
3771{
3772 const struct border *border_a = a;
3773 const struct border *border_b = b;
3774
3775
3776 if (border_a->line.a.x == border_b->line.a.x)
3777 return border_a->line.b.x < border_b->line.b.x;
3778 else
3779 return border_a->line.a.x > border_b->line.a.x;
3780}
3781
3782static void
3783add_non_overlapping_edges(pixman_box32_t *boxes,
3784 int band_above_start,
3785 int band_below_start,
3786 int band_below_end,
3787 struct wl_array *borders)
3788{
3789 int i;
3790 struct wl_array band_merge;
3791 struct border *border;
3792 struct border *prev_border;
3793 struct border *new_border;
3794
3795 wl_array_init(&band_merge);
3796
3797 /* Add bottom band of previous row, and top band of current row, and
3798 * sort them so lower left x coordinate comes first. If there are two
3799 * borders with the same left x coordinate, the wider one comes first.
3800 */
3801 for (i = band_above_start; i < band_below_start; i++) {
3802 pixman_box32_t *box = &boxes[i];
3803 add_border(&band_merge, box->x1, box->y2, box->x2, box->y2,
3804 MOTION_DIRECTION_POSITIVE_Y);
3805 }
3806 for (i = band_below_start; i < band_below_end; i++) {
3807 pixman_box32_t *box= &boxes[i];
3808 add_border(&band_merge, box->x1, box->y1, box->x2, box->y1,
3809 MOTION_DIRECTION_NEGATIVE_Y);
3810 }
3811 qsort(band_merge.data,
3812 band_merge.size / sizeof *border,
3813 sizeof *border,
3814 compare_lines_x);
3815
3816 /* Combine the two combined bands so that any overlapping border is
3817 * eliminated. */
3818 prev_border = NULL;
3819 wl_array_for_each(border, &band_merge) {
3820 assert(border->line.a.y == border->line.b.y);
3821 assert(!prev_border ||
3822 prev_border->line.a.y == border->line.a.y);
3823 assert(!prev_border ||
3824 (prev_border->line.a.x != border->line.a.x ||
3825 prev_border->line.b.x != border->line.b.x));
3826 assert(!prev_border ||
3827 prev_border->line.a.x <= border->line.a.x);
3828
3829 if (prev_border &&
3830 prev_border->line.a.x == border->line.a.x) {
3831 /*
3832 * ------------ +
3833 * ------- =
3834 * [ ]-----
3835 */
3836 prev_border->line.a.x = border->line.b.x;
3837 } else if (prev_border &&
3838 prev_border->line.b.x == border->line.b.x) {
3839 /*
3840 * ------------ +
3841 * ------ =
3842 * ------[ ]
3843 */
3844 prev_border->line.b.x = border->line.a.x;
3845 } else if (prev_border &&
3846 prev_border->line.b.x == border->line.a.x) {
3847 /*
3848 * -------- +
3849 * ------ =
3850 * --------------
3851 */
3852 prev_border->line.b.x = border->line.b.x;
3853 } else if (prev_border &&
3854 prev_border->line.b.x >= border->line.a.x) {
3855 /*
3856 * --------------- +
3857 * ------ =
3858 * -----[ ]----
3859 */
3860 new_border = add_border(borders,
3861 border->line.b.x,
3862 border->line.b.y,
3863 prev_border->line.b.x,
3864 prev_border->line.b.y,
3865 prev_border->blocking_dir);
3866 prev_border->line.b.x = border->line.a.x;
3867 prev_border = new_border;
3868 } else {
3869 assert(!prev_border ||
3870 prev_border->line.b.x < border->line.a.x);
3871 /*
3872 * First border or non-overlapping.
3873 *
3874 * ----- +
3875 * ----- =
3876 * ----- -----
3877 */
3878 new_border = wl_array_add(borders, sizeof *border);
3879 *new_border = *border;
3880 prev_border = new_border;
3881 }
3882 }
3883
3884 wl_array_release(&band_merge);
3885}
3886
3887static void
3888add_band_bottom_edges(pixman_box32_t *boxes,
3889 int band_start,
3890 int band_end,
3891 struct wl_array *borders)
3892{
3893 int i;
3894
3895 for (i = band_start; i < band_end; i++) {
3896 add_border(borders,
3897 boxes[i].x1, boxes[i].y2,
3898 boxes[i].x2, boxes[i].y2,
3899 MOTION_DIRECTION_POSITIVE_Y);
3900 }
3901}
3902
3903static void
3904region_to_outline(pixman_region32_t *region, struct wl_array *borders)
3905{
3906 pixman_box32_t *boxes;
3907 int num_boxes;
3908 int i;
3909 int top_most, bottom_most;
3910 int current_roof;
3911 int prev_top;
3912 int band_start, prev_band_start;
3913
3914 /*
3915 * Remove any overlapping lines from the set of rectangles. Note that
3916 * pixman regions are grouped as rows of rectangles, where rectangles
3917 * in one row never touch or overlap and are all of the same height.
3918 *
3919 * -------- --- -------- ---
3920 * | | | | | | | |
3921 * ----------====---- --- ----------- ----- ---
3922 * | | => | |
3923 * ----==========--------- ----- ----------
3924 * | | | |
3925 * ------------------- -------------------
3926 *
3927 */
3928
3929 boxes = pixman_region32_rectangles(region, &num_boxes);
3930 prev_top = 0;
3931 top_most = boxes[0].y1;
3932 current_roof = top_most;
3933 bottom_most = boxes[num_boxes - 1].y2;
3934 band_start = 0;
3935 prev_band_start = 0;
3936 for (i = 0; i < num_boxes; i++) {
3937 /* Detect if there is a vertical empty space, and add the lower
3938 * level of the previous band if so was the case. */
3939 if (i > 0 &&
3940 boxes[i].y1 != prev_top &&
3941 boxes[i].y1 != boxes[i - 1].y2) {
3942 current_roof = boxes[i].y1;
3943 add_band_bottom_edges(boxes,
3944 band_start,
3945 i,
3946 borders);
3947 }
3948
3949 /* Special case adding the last band, since it won't be handled
3950 * by the band change detection below. */
3951 if (boxes[i].y1 != current_roof && i == num_boxes - 1) {
3952 if (boxes[i].y1 != prev_top) {
3953 /* The last band is a single box, so we don't
3954 * have a prev_band_start to tell us when the
3955 * previous band started. */
3956 add_non_overlapping_edges(boxes,
3957 band_start,
3958 i,
3959 i + 1,
3960 borders);
3961 } else {
3962 add_non_overlapping_edges(boxes,
3963 prev_band_start,
3964 band_start,
3965 i + 1,
3966 borders);
3967 }
3968 }
3969
3970 /* Detect when passing a band and combine the top border of the
3971 * just passed band with the bottom band of the previous band.
3972 */
3973 if (boxes[i].y1 != top_most && boxes[i].y1 != prev_top) {
3974 /* Combine the two passed bands. */
3975 if (prev_top != current_roof) {
3976 add_non_overlapping_edges(boxes,
3977 prev_band_start,
3978 band_start,
3979 i,
3980 borders);
3981 }
3982
3983 prev_band_start = band_start;
3984 band_start = i;
3985 }
3986
3987 /* Add the top border if the box is part of the current roof. */
3988 if (boxes[i].y1 == current_roof) {
3989 add_border(borders,
3990 boxes[i].x1, boxes[i].y1,
3991 boxes[i].x2, boxes[i].y1,
3992 MOTION_DIRECTION_NEGATIVE_Y);
3993 }
3994
3995 /* Add the bottom border of the last band. */
3996 if (boxes[i].y2 == bottom_most) {
3997 add_border(borders,
3998 boxes[i].x1, boxes[i].y2,
3999 boxes[i].x2, boxes[i].y2,
4000 MOTION_DIRECTION_POSITIVE_Y);
4001 }
4002
4003 /* Always add the left border. */
4004 add_border(borders,
4005 boxes[i].x1, boxes[i].y1,
4006 boxes[i].x1, boxes[i].y2,
4007 MOTION_DIRECTION_NEGATIVE_X);
4008
4009 /* Always add the right border. */
4010 add_border(borders,
4011 boxes[i].x2, boxes[i].y1,
4012 boxes[i].x2, boxes[i].y2,
4013 MOTION_DIRECTION_POSITIVE_X);
4014
4015 prev_top = boxes[i].y1;
4016 }
4017}
4018
4019static bool
4020is_border_horizontal (struct border *border)
4021{
4022 return border->line.a.y == border->line.b.y;
4023}
4024
4025static bool
4026is_border_blocking_directions(struct border *border,
4027 uint32_t directions)
4028{
4029 /* Don't block parallel motions. */
4030 if (is_border_horizontal(border)) {
4031 if ((directions & (MOTION_DIRECTION_POSITIVE_Y |
4032 MOTION_DIRECTION_NEGATIVE_Y)) == 0)
4033 return false;
4034 } else {
4035 if ((directions & (MOTION_DIRECTION_POSITIVE_X |
4036 MOTION_DIRECTION_NEGATIVE_X)) == 0)
4037 return false;
4038 }
4039
4040 return (~border->blocking_dir & directions) != directions;
4041}
4042
4043static struct border *
4044get_closest_border(struct wl_array *borders,
4045 struct line *motion,
4046 uint32_t directions)
4047{
4048 struct border *border;
4049 struct vec2d intersection;
4050 struct vec2d delta;
4051 double distance_2;
4052 struct border *closest_border = NULL;
4053 double closest_distance_2 = DBL_MAX;
4054
4055 wl_array_for_each(border, borders) {
4056 if (!is_border_blocking_directions(border, directions))
4057 continue;
4058
4059 if (!lines_intersect(&border->line, motion, &intersection))
4060 continue;
4061
4062 delta = vec2d_subtract(intersection, motion->a);
4063 distance_2 = delta.x*delta.x + delta.y*delta.y;
4064 if (distance_2 < closest_distance_2) {
4065 closest_border = border;
4066 closest_distance_2 = distance_2;
4067 }
4068 }
4069
4070 return closest_border;
4071}
4072
4073static void
4074clamp_to_border(struct border *border,
4075 struct line *motion,
4076 uint32_t *motion_dir)
4077{
4078 /*
4079 * When clamping either rightward or downward motions, the motion needs
4080 * to be clamped so that the destination coordinate does not end up on
4081 * the border (see weston_pointer_clamp_event_to_region). Do this by
4082 * clamping such motions to the border minus the smallest possible
4083 * wl_fixed_t value.
4084 */
4085 if (is_border_horizontal(border)) {
4086 if (*motion_dir & MOTION_DIRECTION_POSITIVE_Y)
4087 motion->b.y = border->line.a.y - wl_fixed_to_double(1);
4088 else
4089 motion->b.y = border->line.a.y;
4090 *motion_dir &= ~(MOTION_DIRECTION_POSITIVE_Y |
4091 MOTION_DIRECTION_NEGATIVE_Y);
4092 } else {
4093 if (*motion_dir & MOTION_DIRECTION_POSITIVE_X)
4094 motion->b.x = border->line.a.x - wl_fixed_to_double(1);
4095 else
4096 motion->b.x = border->line.a.x;
4097 *motion_dir &= ~(MOTION_DIRECTION_POSITIVE_X |
4098 MOTION_DIRECTION_NEGATIVE_X);
4099 }
4100}
4101
4102static uint32_t
4103get_motion_directions(struct line *motion)
4104{
4105 uint32_t directions = 0;
4106
4107 if (motion->a.x < motion->b.x)
4108 directions |= MOTION_DIRECTION_POSITIVE_X;
4109 else if (motion->a.x > motion->b.x)
4110 directions |= MOTION_DIRECTION_NEGATIVE_X;
4111 if (motion->a.y < motion->b.y)
4112 directions |= MOTION_DIRECTION_POSITIVE_Y;
4113 else if (motion->a.y > motion->b.y)
4114 directions |= MOTION_DIRECTION_NEGATIVE_Y;
4115
4116 return directions;
4117}
4118
Jonas Ådahld3414f22016-07-22 17:56:31 +08004119static void
4120weston_pointer_clamp_event_to_region(struct weston_pointer *pointer,
4121 struct weston_pointer_motion_event *event,
4122 pixman_region32_t *region,
4123 wl_fixed_t *clamped_x,
4124 wl_fixed_t *clamped_y)
4125{
4126 wl_fixed_t x, y;
4127 wl_fixed_t sx, sy;
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004128 wl_fixed_t old_sx = pointer->sx;
4129 wl_fixed_t old_sy = pointer->sy;
4130 struct wl_array borders;
4131 struct line motion;
4132 struct border *closest_border;
4133 float new_x_f, new_y_f;
4134 uint32_t directions;
Jonas Ådahld3414f22016-07-22 17:56:31 +08004135
4136 weston_pointer_motion_to_abs(pointer, event, &x, &y);
4137 weston_view_from_global_fixed(pointer->focus, x, y, &sx, &sy);
4138
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004139 wl_array_init(&borders);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004140
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004141 /*
4142 * Generate borders given the confine region we are to use. The borders
4143 * are defined to be the outer region of the allowed area. This means
4144 * top/left borders are "within" the allowed area, while bottom/right
4145 * borders are outside. This needs to be considered when clamping
4146 * confined motion vectors.
4147 */
4148 region_to_outline(region, &borders);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004149
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004150 motion = (struct line) {
4151 .a = (struct vec2d) {
4152 .x = wl_fixed_to_double(old_sx),
4153 .y = wl_fixed_to_double(old_sy),
4154 },
4155 .b = (struct vec2d) {
4156 .x = wl_fixed_to_double(sx),
4157 .y = wl_fixed_to_double(sy),
4158 },
4159 };
4160 directions = get_motion_directions(&motion);
4161
4162 while (directions) {
4163 closest_border = get_closest_border(&borders,
4164 &motion,
4165 directions);
4166 if (closest_border)
4167 clamp_to_border(closest_border, &motion, &directions);
4168 else
4169 break;
4170 }
4171
4172 weston_view_to_global_float(pointer->focus,
4173 (float) motion.b.x, (float) motion.b.y,
4174 &new_x_f, &new_y_f);
4175 *clamped_x = wl_fixed_from_double(new_x_f);
4176 *clamped_y = wl_fixed_from_double(new_y_f);
4177
4178 wl_array_release(&borders);
4179}
4180
4181static double
4182point_to_border_distance_2(struct border *border, double x, double y)
4183{
4184 double orig_x, orig_y;
4185 double dx, dy;
4186
4187 if (is_border_horizontal(border)) {
4188 if (x < border->line.a.x)
4189 orig_x = border->line.a.x;
4190 else if (x > border->line.b.x)
4191 orig_x = border->line.b.x;
4192 else
4193 orig_x = x;
4194 orig_y = border->line.a.y;
4195 } else {
4196 if (y < border->line.a.y)
4197 orig_y = border->line.a.y;
4198 else if (y > border->line.b.y)
4199 orig_y = border->line.b.y;
4200 else
4201 orig_y = y;
4202 orig_x = border->line.a.x;
4203 }
4204
4205
4206 dx = fabs(orig_x - x);
4207 dy = fabs(orig_y - y);
4208 return dx*dx + dy*dy;
4209}
4210
4211static void
4212warp_to_behind_border(struct border *border, wl_fixed_t *sx, wl_fixed_t *sy)
4213{
4214 switch (border->blocking_dir) {
4215 case MOTION_DIRECTION_POSITIVE_X:
4216 case MOTION_DIRECTION_NEGATIVE_X:
4217 if (border->blocking_dir == MOTION_DIRECTION_POSITIVE_X)
4218 *sx = wl_fixed_from_double(border->line.a.x) - 1;
4219 else
4220 *sx = wl_fixed_from_double(border->line.a.x) + 1;
4221 if (*sy < wl_fixed_from_double(border->line.a.y))
4222 *sy = wl_fixed_from_double(border->line.a.y) + 1;
4223 else if (*sy > wl_fixed_from_double(border->line.b.y))
4224 *sy = wl_fixed_from_double(border->line.b.y) - 1;
4225 break;
4226 case MOTION_DIRECTION_POSITIVE_Y:
4227 case MOTION_DIRECTION_NEGATIVE_Y:
4228 if (border->blocking_dir == MOTION_DIRECTION_POSITIVE_Y)
4229 *sy = wl_fixed_from_double(border->line.a.y) - 1;
4230 else
4231 *sy = wl_fixed_from_double(border->line.a.y) + 1;
4232 if (*sx < wl_fixed_from_double(border->line.a.x))
4233 *sx = wl_fixed_from_double(border->line.a.x) + 1;
4234 else if (*sx > wl_fixed_from_double(border->line.b.x))
4235 *sx = wl_fixed_from_double(border->line.b.x) - 1;
4236 break;
4237 }
Jonas Ådahld3414f22016-07-22 17:56:31 +08004238}
4239
4240static void
4241maybe_warp_confined_pointer(struct weston_pointer_constraint *constraint)
4242{
4243 wl_fixed_t x;
4244 wl_fixed_t y;
4245 wl_fixed_t sx;
4246 wl_fixed_t sy;
4247
4248 weston_view_from_global_fixed(constraint->view,
4249 constraint->pointer->x,
4250 constraint->pointer->y,
4251 &sx,
4252 &sy);
4253
4254 if (!is_within_constraint_region(constraint, sx, sy)) {
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004255 double xf = wl_fixed_to_double(sx);
4256 double yf = wl_fixed_to_double(sy);
4257 pixman_region32_t confine_region;
4258 struct wl_array borders;
4259 struct border *border;
4260 double closest_distance_2 = DBL_MAX;
4261 struct border *closest_border = NULL;
Jonas Ådahld3414f22016-07-22 17:56:31 +08004262
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004263 wl_array_init(&borders);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004264
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004265 pixman_region32_init(&confine_region);
4266 pixman_region32_intersect(&confine_region,
4267 &constraint->view->surface->input,
4268 &constraint->region);
4269 region_to_outline(&confine_region, &borders);
4270 pixman_region32_fini(&confine_region);
4271
4272 wl_array_for_each(border, &borders) {
4273 double distance_2;
4274
4275 distance_2 = point_to_border_distance_2(border, xf, yf);
4276 if (distance_2 < closest_distance_2) {
4277 closest_border = border;
4278 closest_distance_2 = distance_2;
4279 }
4280 }
4281 assert(closest_border);
4282
4283 warp_to_behind_border(closest_border, &sx, &sy);
4284
4285 wl_array_release(&borders);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004286
4287 weston_view_to_global_fixed(constraint->view, sx, sy, &x, &y);
4288 weston_pointer_move_to(constraint->pointer, x, y);
4289 }
4290}
4291
4292static void
4293confined_pointer_grab_pointer_motion(struct weston_pointer_grab *grab,
4294 uint32_t time,
4295 struct weston_pointer_motion_event *event)
4296{
4297 struct weston_pointer_constraint *constraint =
4298 container_of(grab, struct weston_pointer_constraint, grab);
4299 struct weston_pointer *pointer = grab->pointer;
4300 struct weston_surface *surface;
4301 wl_fixed_t x, y;
4302 wl_fixed_t old_sx = pointer->sx;
4303 wl_fixed_t old_sy = pointer->sy;
4304 pixman_region32_t confine_region;
4305
4306 assert(pointer->focus);
4307 assert(pointer->focus->surface == constraint->surface);
4308
4309 surface = pointer->focus->surface;
4310
4311 pixman_region32_init(&confine_region);
4312 pixman_region32_intersect(&confine_region,
4313 &surface->input,
4314 &constraint->region);
4315 weston_pointer_clamp_event_to_region(pointer, event,
4316 &confine_region, &x, &y);
4317 weston_pointer_move_to(pointer, x, y);
4318 pixman_region32_fini(&confine_region);
4319
4320 weston_view_from_global_fixed(pointer->focus, x, y,
4321 &pointer->sx, &pointer->sy);
4322
4323 if (old_sx != pointer->sx || old_sy != pointer->sy) {
Quentin Glidiccde13452016-08-12 10:41:32 +02004324 pointer_send_motion(pointer, time,
4325 pointer->sx, pointer->sy);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004326 }
4327
Quentin Glidiccde13452016-08-12 10:41:32 +02004328 pointer_send_relative_motion(pointer, time, event);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004329}
4330
4331static void
4332confined_pointer_grab_pointer_button(struct weston_pointer_grab *grab,
4333 uint32_t time,
4334 uint32_t button,
4335 uint32_t state_w)
4336{
4337 weston_pointer_send_button(grab->pointer, time, button, state_w);
4338}
4339
4340static void
4341confined_pointer_grab_pointer_axis(struct weston_pointer_grab *grab,
4342 uint32_t time,
4343 struct weston_pointer_axis_event *event)
4344{
4345 weston_pointer_send_axis(grab->pointer, time, event);
4346}
4347
4348static void
4349confined_pointer_grab_pointer_axis_source(struct weston_pointer_grab *grab,
4350 uint32_t source)
4351{
4352 weston_pointer_send_axis_source(grab->pointer, source);
4353}
4354
4355static void
4356confined_pointer_grab_pointer_frame(struct weston_pointer_grab *grab)
4357{
4358 weston_pointer_send_frame(grab->pointer);
4359}
4360
4361static void
4362confined_pointer_grab_pointer_cancel(struct weston_pointer_grab *grab)
4363{
4364 struct weston_pointer_constraint *constraint =
4365 container_of(grab, struct weston_pointer_constraint, grab);
4366
4367 disable_pointer_constraint(constraint);
4368
4369 /* If this is a persistent constraint, re-add the surface destroy signal
4370 * listener only if we are currently not destroying the surface. */
4371 switch (constraint->lifetime) {
4372 case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT:
4373 if (constraint->surface->resource)
4374 wl_signal_add(&constraint->surface->destroy_signal,
4375 &constraint->surface_destroy_listener);
4376 break;
4377 case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT:
4378 break;
4379 }
4380}
4381
4382static const struct weston_pointer_grab_interface
4383 confined_pointer_grab_interface = {
4384 confined_pointer_grab_pointer_focus,
4385 confined_pointer_grab_pointer_motion,
4386 confined_pointer_grab_pointer_button,
4387 confined_pointer_grab_pointer_axis,
4388 confined_pointer_grab_pointer_axis_source,
4389 confined_pointer_grab_pointer_frame,
4390 confined_pointer_grab_pointer_cancel,
4391};
4392
4393static void
4394confined_pointer_destroy(struct wl_client *client,
4395 struct wl_resource *resource)
4396{
4397 wl_resource_destroy(resource);
4398}
4399
4400static void
4401confined_pointer_set_region(struct wl_client *client,
4402 struct wl_resource *resource,
4403 struct wl_resource *region_resource)
4404{
4405 struct weston_pointer_constraint *constraint =
4406 wl_resource_get_user_data(resource);
4407 struct weston_region *region = region_resource ?
4408 wl_resource_get_user_data(region_resource) : NULL;
4409
4410 if (!constraint)
4411 return;
4412
4413 if (region) {
4414 pixman_region32_copy(&constraint->region_pending,
4415 &region->region);
4416 } else {
4417 pixman_region32_fini(&constraint->region_pending);
4418 region_init_infinite(&constraint->region_pending);
4419 }
4420 constraint->region_is_pending = true;
4421}
4422
4423static const struct zwp_confined_pointer_v1_interface confined_pointer_interface = {
4424 confined_pointer_destroy,
4425 confined_pointer_set_region,
4426};
4427
4428static void
4429pointer_constraints_confine_pointer(struct wl_client *client,
4430 struct wl_resource *resource,
4431 uint32_t id,
4432 struct wl_resource *surface_resource,
4433 struct wl_resource *pointer_resource,
4434 struct wl_resource *region_resource,
4435 uint32_t lifetime)
4436{
4437 struct weston_surface *surface =
4438 wl_resource_get_user_data(surface_resource);
4439 struct weston_pointer *pointer = wl_resource_get_user_data(pointer_resource);
4440 struct weston_region *region = region_resource ?
4441 wl_resource_get_user_data(region_resource) : NULL;
4442
4443 init_pointer_constraint(resource, id, surface, pointer, region, lifetime,
4444 &zwp_confined_pointer_v1_interface,
4445 &confined_pointer_interface,
4446 &confined_pointer_grab_interface);
4447}
4448
4449static const struct zwp_pointer_constraints_v1_interface pointer_constraints_interface = {
4450 pointer_constraints_destroy,
4451 pointer_constraints_lock_pointer,
4452 pointer_constraints_confine_pointer,
4453};
4454
4455static void
4456bind_pointer_constraints(struct wl_client *client, void *data,
4457 uint32_t version, uint32_t id)
4458{
4459 struct wl_resource *resource;
4460
4461 resource = wl_resource_create(client,
4462 &zwp_pointer_constraints_v1_interface,
4463 1, id);
4464
4465 wl_resource_set_implementation(resource, &pointer_constraints_interface,
4466 NULL, NULL);
4467}
4468
Jonas Ådahl30d61d82014-10-22 21:21:17 +02004469int
4470weston_input_init(struct weston_compositor *compositor)
4471{
4472 if (!wl_global_create(compositor->wl_display,
4473 &zwp_relative_pointer_manager_v1_interface, 1,
4474 compositor, bind_relative_pointer_manager))
4475 return -1;
4476
Jonas Ådahld3414f22016-07-22 17:56:31 +08004477 if (!wl_global_create(compositor->wl_display,
4478 &zwp_pointer_constraints_v1_interface, 1,
4479 NULL, bind_pointer_constraints))
4480 return -1;
4481
Jonas Ådahl30d61d82014-10-22 21:21:17 +02004482 return 0;
4483}