blob: 6e931bde65e13f185793fb0dba799dbc45bfc50d [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"
Jonas Ådahl30d61d82014-10-22 21:21:17 +020042#include "protocol/relative-pointer-unstable-v1-server-protocol.h"
Jonas Ådahld3414f22016-07-22 17:56:31 +080043#include "protocol/pointer-constraints-unstable-v1-server-protocol.h"
44
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
Jonas Ådahl30d61d82014-10-22 21:21:17 +0200343weston_pointer_send_relative_motion(struct weston_pointer *pointer,
344 uint32_t time,
345 struct weston_pointer_motion_event *event)
346{
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
Jonas Ådahlf44942e2016-07-22 17:54:55 +0800382weston_pointer_send_motion(struct weston_pointer *pointer, uint32_t time,
383 wl_fixed_t sx, wl_fixed_t sy)
384{
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
396static void
Giulio Camuffo1959ab82013-11-14 23:42:52 +0100397default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time,
Jonas Ådahld2510102014-10-05 21:39:14 +0200398 struct weston_pointer_motion_event *event)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400399{
Kristian Høgsbergbe6403e2013-05-08 21:03:21 -0400400 struct weston_pointer *pointer = grab->pointer;
Jonas Ådahld2510102014-10-05 21:39:14 +0200401 wl_fixed_t x, y;
Jonas Ådahl8283c342015-04-24 15:26:17 +0800402 wl_fixed_t old_sx = pointer->sx;
403 wl_fixed_t old_sy = pointer->sy;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400404
Jonas Ådahld2510102014-10-05 21:39:14 +0200405 if (pointer->focus) {
406 weston_pointer_motion_to_abs(pointer, event, &x, &y);
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -0800407 weston_view_from_global_fixed(pointer->focus, x, y,
408 &pointer->sx, &pointer->sy);
Jonas Ådahld2510102014-10-05 21:39:14 +0200409 }
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -0800410
Jonas Ådahld2510102014-10-05 21:39:14 +0200411 weston_pointer_move(pointer, event);
Giulio Camuffo1959ab82013-11-14 23:42:52 +0100412
Jonas Ådahlf44942e2016-07-22 17:54:55 +0800413 if (old_sx != pointer->sx || old_sy != pointer->sy) {
414 weston_pointer_send_motion(pointer, time,
415 pointer->sx, pointer->sy);
Kristian Høgsbergbe6403e2013-05-08 21:03:21 -0400416 }
Jonas Ådahl30d61d82014-10-22 21:21:17 +0200417
418 weston_pointer_send_relative_motion(pointer, time, event);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400419}
420
421static void
Jonas Ådahlc02ac112016-07-22 17:55:43 +0800422weston_pointer_send_button(struct weston_pointer *pointer,
423 uint32_t time, uint32_t button, uint32_t state_w)
424{
425 struct wl_display *display = pointer->seat->compositor->wl_display;
426 struct wl_list *resource_list;
427 struct wl_resource *resource;
428 uint32_t serial;
429
430 if (!pointer->focus_client)
431 return;
432
433 resource_list = &pointer->focus_client->pointer_resources;
434 if (resource_list && !wl_list_empty(resource_list)) {
435 resource_list = &pointer->focus_client->pointer_resources;
436 serial = wl_display_next_serial(display);
437 wl_resource_for_each(resource, resource_list) {
438 wl_pointer_send_button(resource,
439 serial,
440 time,
441 button,
442 state_w);
443 }
444 }
445}
446
447static void
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700448default_grab_pointer_button(struct weston_pointer_grab *grab,
449 uint32_t time, uint32_t button, uint32_t state_w)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400450{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400451 struct weston_pointer *pointer = grab->pointer;
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400452 struct weston_compositor *compositor = pointer->seat->compositor;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500453 struct weston_view *view;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400454 enum wl_pointer_button_state state = state_w;
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400455 wl_fixed_t sx, sy;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400456
Jonas Ådahlc02ac112016-07-22 17:55:43 +0800457 weston_pointer_send_button(pointer, time, button, state_w);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400458
459 if (pointer->button_count == 0 &&
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400460 state == WL_POINTER_BUTTON_STATE_RELEASED) {
Jason Ekstranda7af7042013-10-12 22:38:11 -0500461 view = weston_compositor_pick_view(compositor,
462 pointer->x, pointer->y,
463 &sx, &sy);
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400464
Jason Ekstranda7af7042013-10-12 22:38:11 -0500465 weston_pointer_set_focus(pointer, view, sx, sy);
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400466 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400467}
468
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200469/** Send wl_pointer.axis events to focused resources.
470 *
471 * \param pointer The pointer where the axis events originates from.
472 * \param time The timestamp of the event
473 * \param axis The axis enum value of the event
474 * \param value The axis value of the event
475 *
476 * For every resource that is currently in focus, send a wl_pointer.axis event
477 * with the passed parameters. The focused resources are the wl_pointer
478 * resources of the client which currently has the surface with pointer focus.
479 */
480WL_EXPORT void
481weston_pointer_send_axis(struct weston_pointer *pointer,
Peter Hutterer89b6a492016-01-18 15:58:17 +1000482 uint32_t time,
483 struct weston_pointer_axis_event *event)
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200484{
485 struct wl_resource *resource;
486 struct wl_list *resource_list;
487
Jonas Ådahl2cbf2932015-07-22 12:05:38 +0800488 if (!pointer->focus_client)
489 return;
490
491 resource_list = &pointer->focus_client->pointer_resources;
Peter Hutterer87743e92016-01-18 16:38:22 +1000492 wl_resource_for_each(resource, resource_list) {
493 if (event->has_discrete &&
494 wl_resource_get_version(resource) >=
495 WL_POINTER_AXIS_DISCRETE_SINCE_VERSION)
496 wl_pointer_send_axis_discrete(resource, event->axis,
497 event->discrete);
498
499 if (event->value)
500 wl_pointer_send_axis(resource, time,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +0200501 event->axis,
502 wl_fixed_from_double(event->value));
Peter Hutterer87743e92016-01-18 16:38:22 +1000503 else if (wl_resource_get_version(resource) >=
504 WL_POINTER_AXIS_STOP_SINCE_VERSION)
505 wl_pointer_send_axis_stop(resource, time,
506 event->axis);
507 }
508}
509
510WL_EXPORT void
511weston_pointer_send_axis_source(struct weston_pointer *pointer, uint32_t source)
512{
513 struct wl_resource *resource;
514 struct wl_list *resource_list;
515
Jonas Ådahled6014a2016-04-21 10:21:48 +0800516 if (!pointer->focus_client)
517 return;
518
Peter Hutterer87743e92016-01-18 16:38:22 +1000519 resource_list = &pointer->focus_client->pointer_resources;
520 wl_resource_for_each(resource, resource_list) {
521 if (wl_resource_get_version(resource) >=
522 WL_POINTER_AXIS_SOURCE_SINCE_VERSION) {
523 wl_pointer_send_axis_source(resource, source);
524 }
525 }
526}
527
528static void
529pointer_send_frame(struct wl_resource *resource)
530{
531 if (wl_resource_get_version(resource) >=
532 WL_POINTER_FRAME_SINCE_VERSION) {
533 wl_pointer_send_frame(resource);
534 }
535}
536
537WL_EXPORT void
538weston_pointer_send_frame(struct weston_pointer *pointer)
539{
540 struct wl_resource *resource;
541 struct wl_list *resource_list;
542
Derek Foreman8efa31b2016-01-29 10:29:46 -0600543 if (!pointer->focus_client)
544 return;
545
Peter Hutterer87743e92016-01-18 16:38:22 +1000546 resource_list = &pointer->focus_client->pointer_resources;
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200547 wl_resource_for_each(resource, resource_list)
Peter Hutterer87743e92016-01-18 16:38:22 +1000548 pointer_send_frame(resource);
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200549}
550
551static void
552default_grab_pointer_axis(struct weston_pointer_grab *grab,
Peter Hutterer89b6a492016-01-18 15:58:17 +1000553 uint32_t time,
554 struct weston_pointer_axis_event *event)
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200555{
Peter Hutterer89b6a492016-01-18 15:58:17 +1000556 weston_pointer_send_axis(grab->pointer, time, event);
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200557}
558
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200559static void
Peter Hutterer87743e92016-01-18 16:38:22 +1000560default_grab_pointer_axis_source(struct weston_pointer_grab *grab,
561 uint32_t source)
562{
563 weston_pointer_send_axis_source(grab->pointer, source);
564}
565
566static void
567default_grab_pointer_frame(struct weston_pointer_grab *grab)
568{
569 weston_pointer_send_frame(grab->pointer);
570}
571
572static void
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200573default_grab_pointer_cancel(struct weston_pointer_grab *grab)
574{
575}
576
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400577static const struct weston_pointer_grab_interface
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400578 default_pointer_grab_interface = {
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700579 default_grab_pointer_focus,
580 default_grab_pointer_motion,
581 default_grab_pointer_button,
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200582 default_grab_pointer_axis,
Peter Hutterer87743e92016-01-18 16:38:22 +1000583 default_grab_pointer_axis_source,
584 default_grab_pointer_frame,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200585 default_grab_pointer_cancel,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400586};
587
Kristian Høgsberge329f362013-05-06 22:19:57 -0400588static void
589default_grab_touch_down(struct weston_touch_grab *grab, uint32_t time,
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300590 int touch_id, wl_fixed_t x, wl_fixed_t y)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400591{
Kristian Høgsberge329f362013-05-06 22:19:57 -0400592 struct weston_touch *touch = grab->touch;
Rob Bradford880ebc72013-07-22 17:31:38 +0100593 struct wl_display *display = touch->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400594 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +0100595 struct wl_resource *resource;
596 struct wl_list *resource_list;
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300597 wl_fixed_t sx, sy;
598
Bryce Harrington2c40d1d2016-02-02 10:18:48 -0800599 if (!touch->focus)
600 return;
601
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300602 weston_view_from_global_fixed(touch->focus, x, y, &sx, &sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400603
Neil Roberts96d790e2013-09-19 17:32:00 +0100604 resource_list = &touch->focus_resource_list;
605
Bryce Harrington2c40d1d2016-02-02 10:18:48 -0800606 if (!wl_list_empty(resource_list)) {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400607 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +0100608 wl_resource_for_each(resource, resource_list)
609 wl_touch_send_down(resource, serial, time,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500610 touch->focus->surface->resource,
Neil Roberts96d790e2013-09-19 17:32:00 +0100611 touch_id, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400612 }
613}
614
Kristian Høgsberge329f362013-05-06 22:19:57 -0400615static void
616default_grab_touch_up(struct weston_touch_grab *grab,
617 uint32_t time, int touch_id)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400618{
Kristian Høgsberge329f362013-05-06 22:19:57 -0400619 struct weston_touch *touch = grab->touch;
Rob Bradford880ebc72013-07-22 17:31:38 +0100620 struct wl_display *display = touch->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400621 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +0100622 struct wl_resource *resource;
623 struct wl_list *resource_list;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400624
Neil Roberts96d790e2013-09-19 17:32:00 +0100625 resource_list = &touch->focus_resource_list;
626
627 if (!wl_list_empty(resource_list)) {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400628 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +0100629 wl_resource_for_each(resource, resource_list)
630 wl_touch_send_up(resource, serial, time, touch_id);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400631 }
632}
633
Kristian Høgsberge329f362013-05-06 22:19:57 -0400634static void
635default_grab_touch_motion(struct weston_touch_grab *grab, uint32_t time,
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300636 int touch_id, wl_fixed_t x, wl_fixed_t y)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400637{
Kristian Høgsberge329f362013-05-06 22:19:57 -0400638 struct weston_touch *touch = grab->touch;
Neil Roberts96d790e2013-09-19 17:32:00 +0100639 struct wl_resource *resource;
640 struct wl_list *resource_list;
Giulio Camuffo61ed7b62015-07-08 11:55:28 +0300641 wl_fixed_t sx, sy;
642
643 weston_view_from_global_fixed(touch->focus, x, y, &sx, &sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400644
Neil Roberts96d790e2013-09-19 17:32:00 +0100645 resource_list = &touch->focus_resource_list;
646
647 wl_resource_for_each(resource, resource_list) {
648 wl_touch_send_motion(resource, time,
Kristian Høgsberge329f362013-05-06 22:19:57 -0400649 touch_id, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400650 }
651}
652
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200653static void
Jonas Ådahl1679f232014-04-12 09:39:51 +0200654default_grab_touch_frame(struct weston_touch_grab *grab)
655{
656 struct wl_resource *resource;
657
658 wl_resource_for_each(resource, &grab->touch->focus_resource_list)
659 wl_touch_send_frame(resource);
660}
661
662static void
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200663default_grab_touch_cancel(struct weston_touch_grab *grab)
664{
665}
666
Kristian Høgsberge329f362013-05-06 22:19:57 -0400667static const struct weston_touch_grab_interface default_touch_grab_interface = {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400668 default_grab_touch_down,
669 default_grab_touch_up,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200670 default_grab_touch_motion,
Jonas Ådahl1679f232014-04-12 09:39:51 +0200671 default_grab_touch_frame,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200672 default_grab_touch_cancel,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400673};
674
675static void
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700676default_grab_keyboard_key(struct weston_keyboard_grab *grab,
677 uint32_t time, uint32_t key, uint32_t state)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400678{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400679 struct weston_keyboard *keyboard = grab->keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400680 struct wl_resource *resource;
Rob Bradford880ebc72013-07-22 17:31:38 +0100681 struct wl_display *display = keyboard->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400682 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +0100683 struct wl_list *resource_list;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400684
Neil Roberts96d790e2013-09-19 17:32:00 +0100685 resource_list = &keyboard->focus_resource_list;
686 if (!wl_list_empty(resource_list)) {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400687 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +0100688 wl_resource_for_each(resource, resource_list)
689 wl_keyboard_send_key(resource,
690 serial,
691 time,
692 key,
693 state);
694 }
695}
696
697static void
698send_modifiers_to_resource(struct weston_keyboard *keyboard,
699 struct wl_resource *resource,
700 uint32_t serial)
701{
702 wl_keyboard_send_modifiers(resource,
703 serial,
704 keyboard->modifiers.mods_depressed,
705 keyboard->modifiers.mods_latched,
706 keyboard->modifiers.mods_locked,
707 keyboard->modifiers.group);
708}
709
710static void
711send_modifiers_to_client_in_list(struct wl_client *client,
712 struct wl_list *list,
713 uint32_t serial,
714 struct weston_keyboard *keyboard)
715{
716 struct wl_resource *resource;
717
718 wl_resource_for_each(resource, list) {
719 if (wl_resource_get_client(resource) == client)
720 send_modifiers_to_resource(keyboard,
721 resource,
722 serial);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400723 }
724}
725
Jonas Ådahl2cbf2932015-07-22 12:05:38 +0800726static struct weston_pointer_client *
727find_pointer_client_for_surface(struct weston_pointer *pointer,
728 struct weston_surface *surface)
729{
730 struct wl_client *client;
731
732 if (!surface)
733 return NULL;
734
735 if (!surface->resource)
736 return NULL;
737
738 client = wl_resource_get_client(surface->resource);
739 return weston_pointer_get_pointer_client(pointer, client);
740}
741
742static struct weston_pointer_client *
743find_pointer_client_for_view(struct weston_pointer *pointer, struct weston_view *view)
744{
745 if (!view)
746 return NULL;
747
748 return find_pointer_client_for_surface(pointer, view->surface);
749}
750
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400751static struct wl_resource *
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400752find_resource_for_surface(struct wl_list *list, struct weston_surface *surface)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400753{
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400754 if (!surface)
755 return NULL;
756
Jason Ekstrand44a38632013-06-14 10:08:00 -0500757 if (!surface->resource)
758 return NULL;
Stefan Schmidtfda26522013-09-17 10:54:09 +0100759
Jason Ekstrand44a38632013-06-14 10:08:00 -0500760 return wl_resource_find_for_client(list, wl_resource_get_client(surface->resource));
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400761}
762
763static void
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700764default_grab_keyboard_modifiers(struct weston_keyboard_grab *grab,
765 uint32_t serial, uint32_t mods_depressed,
766 uint32_t mods_latched,
767 uint32_t mods_locked, uint32_t group)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400768{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400769 struct weston_keyboard *keyboard = grab->keyboard;
Derek Foreman1281a362015-07-31 16:55:32 -0500770 struct weston_pointer *pointer =
771 weston_seat_get_pointer(grab->keyboard->seat);
Neil Roberts96d790e2013-09-19 17:32:00 +0100772 struct wl_resource *resource;
773 struct wl_list *resource_list;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400774
Neil Roberts96d790e2013-09-19 17:32:00 +0100775 resource_list = &keyboard->focus_resource_list;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400776
Neil Roberts96d790e2013-09-19 17:32:00 +0100777 wl_resource_for_each(resource, resource_list) {
778 wl_keyboard_send_modifiers(resource, serial, mods_depressed,
779 mods_latched, mods_locked, group);
780 }
Jason Ekstrand42133d42013-11-14 20:06:16 -0600781 if (pointer && pointer->focus && pointer->focus->surface->resource &&
782 pointer->focus->surface != keyboard->focus) {
Neil Roberts96d790e2013-09-19 17:32:00 +0100783 struct wl_client *pointer_client =
Jason Ekstranda7af7042013-10-12 22:38:11 -0500784 wl_resource_get_client(pointer->focus->surface->resource);
Neil Roberts96d790e2013-09-19 17:32:00 +0100785 send_modifiers_to_client_in_list(pointer_client,
786 &keyboard->resource_list,
787 serial,
788 keyboard);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400789 }
790}
791
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200792static void
793default_grab_keyboard_cancel(struct weston_keyboard_grab *grab)
794{
795}
796
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400797static const struct weston_keyboard_grab_interface
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400798 default_keyboard_grab_interface = {
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700799 default_grab_keyboard_key,
800 default_grab_keyboard_modifiers,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200801 default_grab_keyboard_cancel,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400802};
803
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400804static void
805pointer_unmap_sprite(struct weston_pointer *pointer)
806{
Pekka Paalanenc557ff72014-11-12 16:42:52 +0200807 struct weston_surface *surface = pointer->sprite->surface;
808
809 if (weston_surface_is_mapped(surface))
810 weston_surface_unmap(surface);
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400811
812 wl_list_remove(&pointer->sprite_destroy_listener.link);
Pekka Paalanenc557ff72014-11-12 16:42:52 +0200813 surface->configure = NULL;
814 surface->configure_private = NULL;
Pekka Paalanen8274d902014-08-06 19:36:51 +0300815 weston_surface_set_label_func(surface, NULL);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500816 weston_view_destroy(pointer->sprite);
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400817 pointer->sprite = NULL;
818}
819
820static void
821pointer_handle_sprite_destroy(struct wl_listener *listener, void *data)
822{
823 struct weston_pointer *pointer =
824 container_of(listener, struct weston_pointer,
825 sprite_destroy_listener);
826
827 pointer->sprite = NULL;
828}
829
Jonas Ådahl3e12e632013-12-02 22:05:05 +0100830static void
831weston_pointer_reset_state(struct weston_pointer *pointer)
832{
833 pointer->button_count = 0;
834}
835
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +0200836static void
837weston_pointer_handle_output_destroy(struct wl_listener *listener, void *data);
838
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400839WL_EXPORT struct weston_pointer *
Giulio Camuffocdb4d292013-11-14 23:42:53 +0100840weston_pointer_create(struct weston_seat *seat)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400841{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400842 struct weston_pointer *pointer;
843
Peter Huttererf3d62272013-08-08 11:57:05 +1000844 pointer = zalloc(sizeof *pointer);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400845 if (pointer == NULL)
846 return NULL;
847
Jonas Ådahl2cbf2932015-07-22 12:05:38 +0800848 wl_list_init(&pointer->pointer_clients);
Giulio Camuffocdb4d292013-11-14 23:42:53 +0100849 weston_pointer_set_default_grab(pointer,
850 seat->compositor->default_pointer_grab);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100851 wl_list_init(&pointer->focus_resource_listener.link);
852 pointer->focus_resource_listener.notify = pointer_focus_resource_destroyed;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400853 pointer->default_grab.pointer = pointer;
854 pointer->grab = &pointer->default_grab;
Giulio Camuffo6fcb3782013-11-14 23:42:50 +0100855 wl_signal_init(&pointer->motion_signal);
Emilio Pozuelo Monfortaa7a4762013-11-19 11:37:15 +0100856 wl_signal_init(&pointer->focus_signal);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100857 wl_list_init(&pointer->focus_view_listener.link);
Jonas Ådahl3eb4ddd2016-07-22 17:52:58 +0800858 wl_signal_init(&pointer->destroy_signal);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400859
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400860 pointer->sprite_destroy_listener.notify = pointer_handle_sprite_destroy;
861
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400862 /* FIXME: Pick better co-ords. */
863 pointer->x = wl_fixed_from_int(100);
864 pointer->y = wl_fixed_from_int(100);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400865
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +0200866 pointer->output_destroy_listener.notify =
867 weston_pointer_handle_output_destroy;
868 wl_signal_add(&seat->compositor->output_destroyed_signal,
869 &pointer->output_destroy_listener);
870
Derek Foremanf9318d12015-05-11 15:40:11 -0500871 pointer->sx = wl_fixed_from_int(-1000000);
872 pointer->sy = wl_fixed_from_int(-1000000);
873
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400874 return pointer;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400875}
876
877WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400878weston_pointer_destroy(struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400879{
Jonas Ådahl3eb4ddd2016-07-22 17:52:58 +0800880 wl_signal_emit(&pointer->destroy_signal, pointer);
881
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400882 if (pointer->sprite)
883 pointer_unmap_sprite(pointer);
884
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400885 /* XXX: What about pointer->resource_list? */
Neil Roberts96d790e2013-09-19 17:32:00 +0100886
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100887 wl_list_remove(&pointer->focus_resource_listener.link);
888 wl_list_remove(&pointer->focus_view_listener.link);
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +0200889 wl_list_remove(&pointer->output_destroy_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400890 free(pointer);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400891}
892
Giulio Camuffocdb4d292013-11-14 23:42:53 +0100893void
894weston_pointer_set_default_grab(struct weston_pointer *pointer,
895 const struct weston_pointer_grab_interface *interface)
896{
897 if (interface)
898 pointer->default_grab.interface = interface;
899 else
900 pointer->default_grab.interface =
901 &default_pointer_grab_interface;
902}
903
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400904WL_EXPORT struct weston_keyboard *
905weston_keyboard_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400906{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400907 struct weston_keyboard *keyboard;
908
Peter Huttererf3d62272013-08-08 11:57:05 +1000909 keyboard = zalloc(sizeof *keyboard);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400910 if (keyboard == NULL)
Neil Roberts96d790e2013-09-19 17:32:00 +0100911 return NULL;
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400912
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400913 wl_list_init(&keyboard->resource_list);
Neil Roberts96d790e2013-09-19 17:32:00 +0100914 wl_list_init(&keyboard->focus_resource_list);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100915 wl_list_init(&keyboard->focus_resource_listener.link);
916 keyboard->focus_resource_listener.notify = keyboard_focus_resource_destroyed;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400917 wl_array_init(&keyboard->keys);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400918 keyboard->default_grab.interface = &default_keyboard_grab_interface;
919 keyboard->default_grab.keyboard = keyboard;
920 keyboard->grab = &keyboard->default_grab;
921 wl_signal_init(&keyboard->focus_signal);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400922
923 return keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400924}
925
Jonas Ådahl7395ea02013-12-03 09:14:26 +0100926static void
927weston_xkb_info_destroy(struct weston_xkb_info *xkb_info);
928
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400929WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400930weston_keyboard_destroy(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400931{
932 /* XXX: What about keyboard->resource_list? */
Neil Roberts96d790e2013-09-19 17:32:00 +0100933
Jonas Ådahl7395ea02013-12-03 09:14:26 +0100934#ifdef ENABLE_XKBCOMMON
935 if (keyboard->seat->compositor->use_xkbcommon) {
Ran Benitac9c74152014-08-19 23:59:52 +0300936 xkb_state_unref(keyboard->xkb_state.state);
Jonas Ådahl7395ea02013-12-03 09:14:26 +0100937 if (keyboard->xkb_info)
938 weston_xkb_info_destroy(keyboard->xkb_info);
Ran Benitac9c74152014-08-19 23:59:52 +0300939 xkb_keymap_unref(keyboard->pending_keymap);
Jonas Ådahl7395ea02013-12-03 09:14:26 +0100940 }
941#endif
942
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400943 wl_array_release(&keyboard->keys);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100944 wl_list_remove(&keyboard->focus_resource_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400945 free(keyboard);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400946}
947
Jonas Ådahlcbfa7f72013-12-02 22:05:04 +0100948static void
949weston_touch_reset_state(struct weston_touch *touch)
950{
951 touch->num_tp = 0;
952}
953
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400954WL_EXPORT struct weston_touch *
955weston_touch_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400956{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400957 struct weston_touch *touch;
958
Peter Huttererf3d62272013-08-08 11:57:05 +1000959 touch = zalloc(sizeof *touch);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400960 if (touch == NULL)
961 return NULL;
962
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400963 wl_list_init(&touch->resource_list);
Neil Roberts96d790e2013-09-19 17:32:00 +0100964 wl_list_init(&touch->focus_resource_list);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100965 wl_list_init(&touch->focus_view_listener.link);
966 touch->focus_view_listener.notify = touch_focus_view_destroyed;
967 wl_list_init(&touch->focus_resource_listener.link);
968 touch->focus_resource_listener.notify = touch_focus_resource_destroyed;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400969 touch->default_grab.interface = &default_touch_grab_interface;
970 touch->default_grab.touch = touch;
971 touch->grab = &touch->default_grab;
972 wl_signal_init(&touch->focus_signal);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400973
974 return touch;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400975}
976
977WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400978weston_touch_destroy(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400979{
980 /* XXX: What about touch->resource_list? */
Neil Roberts96d790e2013-09-19 17:32:00 +0100981
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100982 wl_list_remove(&touch->focus_view_listener.link);
983 wl_list_remove(&touch->focus_resource_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400984 free(touch);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400985}
986
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400987static void
Kristian Høgsberge3148752013-05-06 23:19:49 -0400988seat_send_updated_caps(struct weston_seat *seat)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400989{
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400990 enum wl_seat_capability caps = 0;
Rob Bradford6e737f52013-09-06 17:48:19 +0100991 struct wl_resource *resource;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400992
Jonas Ådahld6e1c342013-10-17 23:04:05 +0200993 if (seat->pointer_device_count > 0)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400994 caps |= WL_SEAT_CAPABILITY_POINTER;
Jonas Ådahld6e1c342013-10-17 23:04:05 +0200995 if (seat->keyboard_device_count > 0)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400996 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
Jonas Ådahld6e1c342013-10-17 23:04:05 +0200997 if (seat->touch_device_count > 0)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400998 caps |= WL_SEAT_CAPABILITY_TOUCH;
999
Rob Bradford6e737f52013-09-06 17:48:19 +01001000 wl_resource_for_each(resource, &seat->base_resource_list) {
1001 wl_seat_send_capabilities(resource, caps);
Jason Ekstrand44a38632013-06-14 10:08:00 -05001002 }
Jason Ekstranda4ab5422014-04-02 19:53:45 -05001003 wl_signal_emit(&seat->updated_caps_signal, seat);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001004}
1005
Derek Foremanf9318d12015-05-11 15:40:11 -05001006
1007/** Clear the pointer focus
1008 *
1009 * \param pointer the pointer to clear focus for.
1010 *
1011 * This can be used to unset pointer focus and set the co-ordinates to the
1012 * arbitrary values we use for the no focus case.
1013 *
1014 * There's no requirement to use this function. For example, passing the
1015 * results of a weston_compositor_pick_view() directly to
1016 * weston_pointer_set_focus() will do the right thing when no view is found.
1017 */
1018WL_EXPORT void
1019weston_pointer_clear_focus(struct weston_pointer *pointer)
1020{
1021 weston_pointer_set_focus(pointer, NULL,
1022 wl_fixed_from_int(-1000000),
1023 wl_fixed_from_int(-1000000));
1024}
1025
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001026WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001027weston_pointer_set_focus(struct weston_pointer *pointer,
Jason Ekstranda7af7042013-10-12 22:38:11 -05001028 struct weston_view *view,
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001029 wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001030{
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001031 struct weston_pointer_client *pointer_client;
Derek Foreman1281a362015-07-31 16:55:32 -05001032 struct weston_keyboard *kbd = weston_seat_get_keyboard(pointer->seat);
Neil Roberts96d790e2013-09-19 17:32:00 +01001033 struct wl_resource *resource;
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001034 struct wl_resource *surface_resource;
Rob Bradford880ebc72013-07-22 17:31:38 +01001035 struct wl_display *display = pointer->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001036 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +01001037 struct wl_list *focus_resource_list;
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -08001038 int refocus = 0;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001039
1040 if ((!pointer->focus && view) ||
1041 (pointer->focus && !view) ||
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -08001042 (pointer->focus && pointer->focus->surface != view->surface) ||
1043 pointer->sx != sx || pointer->sy != sy)
1044 refocus = 1;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001045
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001046 if (pointer->focus_client && refocus) {
1047 focus_resource_list = &pointer->focus_client->pointer_resources;
1048 if (!wl_list_empty(focus_resource_list)) {
1049 serial = wl_display_next_serial(display);
1050 surface_resource = pointer->focus->surface->resource;
1051 wl_resource_for_each(resource, focus_resource_list) {
1052 wl_pointer_send_leave(resource, serial,
1053 surface_resource);
Peter Hutterer87743e92016-01-18 16:38:22 +10001054 pointer_send_frame(resource);
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001055 }
Neil Roberts96d790e2013-09-19 17:32:00 +01001056 }
1057
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001058 pointer->focus_client = NULL;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001059 }
1060
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001061 pointer_client = find_pointer_client_for_view(pointer, view);
1062 if (pointer_client && refocus) {
1063 struct wl_client *surface_client = pointer_client->client;
Neil Roberts96d790e2013-09-19 17:32:00 +01001064
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001065 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +01001066
Jason Ekstranda7af7042013-10-12 22:38:11 -05001067 if (kbd && kbd->focus != view->surface)
Kristian Høgsbergcb406f12013-10-09 10:54:03 -07001068 send_modifiers_to_client_in_list(surface_client,
1069 &kbd->resource_list,
1070 serial,
1071 kbd);
1072
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001073 pointer->focus_client = pointer_client;
Neil Roberts96d790e2013-09-19 17:32:00 +01001074
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08001075 focus_resource_list = &pointer->focus_client->pointer_resources;
Neil Roberts96d790e2013-09-19 17:32:00 +01001076 wl_resource_for_each(resource, focus_resource_list) {
1077 wl_pointer_send_enter(resource,
1078 serial,
Jason Ekstranda7af7042013-10-12 22:38:11 -05001079 view->surface->resource,
Neil Roberts96d790e2013-09-19 17:32:00 +01001080 sx, sy);
Peter Hutterer87743e92016-01-18 16:38:22 +10001081 pointer_send_frame(resource);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001082 }
Neil Roberts96d790e2013-09-19 17:32:00 +01001083
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001084 pointer->focus_serial = serial;
1085 }
1086
Giulio Camuffo65a07f82013-12-06 12:46:27 +01001087 wl_list_remove(&pointer->focus_view_listener.link);
1088 wl_list_init(&pointer->focus_view_listener.link);
1089 wl_list_remove(&pointer->focus_resource_listener.link);
1090 wl_list_init(&pointer->focus_resource_listener.link);
Emilio Pozuelo Monfortaa7a4762013-11-19 11:37:15 +01001091 if (view)
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001092 wl_signal_add(&view->destroy_signal, &pointer->focus_view_listener);
Giulio Camuffo65a07f82013-12-06 12:46:27 +01001093 if (view && view->surface->resource)
1094 wl_resource_add_destroy_listener(view->surface->resource,
1095 &pointer->focus_resource_listener);
1096
1097 pointer->focus = view;
1098 pointer->focus_view_listener.notify = pointer_focus_view_destroyed;
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -08001099 pointer->sx = sx;
1100 pointer->sy = sy;
1101
Derek Foremanf9318d12015-05-11 15:40:11 -05001102 assert(view || sx == wl_fixed_from_int(-1000000));
1103 assert(view || sy == wl_fixed_from_int(-1000000));
1104
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001105 wl_signal_emit(&pointer->focus_signal, pointer);
1106}
1107
Neil Roberts96d790e2013-09-19 17:32:00 +01001108static void
1109send_enter_to_resource_list(struct wl_list *list,
1110 struct weston_keyboard *keyboard,
1111 struct weston_surface *surface,
1112 uint32_t serial)
1113{
1114 struct wl_resource *resource;
1115
1116 wl_resource_for_each(resource, list) {
1117 send_modifiers_to_resource(keyboard, resource, serial);
1118 wl_keyboard_send_enter(resource, serial,
1119 surface->resource,
1120 &keyboard->keys);
1121 }
1122}
1123
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001124WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -04001125weston_keyboard_set_focus(struct weston_keyboard *keyboard,
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -04001126 struct weston_surface *surface)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001127{
1128 struct wl_resource *resource;
Rob Bradford880ebc72013-07-22 17:31:38 +01001129 struct wl_display *display = keyboard->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001130 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +01001131 struct wl_list *focus_resource_list;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001132
Neil Roberts96d790e2013-09-19 17:32:00 +01001133 focus_resource_list = &keyboard->focus_resource_list;
1134
1135 if (!wl_list_empty(focus_resource_list) && keyboard->focus != surface) {
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001136 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +01001137 wl_resource_for_each(resource, focus_resource_list) {
1138 wl_keyboard_send_leave(resource, serial,
1139 keyboard->focus->resource);
1140 }
1141 move_resources(&keyboard->resource_list, focus_resource_list);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001142 }
1143
Neil Roberts96d790e2013-09-19 17:32:00 +01001144 if (find_resource_for_surface(&keyboard->resource_list, surface) &&
1145 keyboard->focus != surface) {
1146 struct wl_client *surface_client =
1147 wl_resource_get_client(surface->resource);
1148
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001149 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +01001150
1151 move_resources_for_client(focus_resource_list,
1152 &keyboard->resource_list,
1153 surface_client);
1154 send_enter_to_resource_list(focus_resource_list,
1155 keyboard,
1156 surface,
1157 serial);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001158 keyboard->focus_serial = serial;
Giulio Camuffo65a07f82013-12-06 12:46:27 +01001159 }
1160
1161 wl_list_remove(&keyboard->focus_resource_listener.link);
1162 wl_list_init(&keyboard->focus_resource_listener.link);
1163 if (surface && surface->resource)
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001164 wl_resource_add_destroy_listener(surface->resource,
1165 &keyboard->focus_resource_listener);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001166
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001167 keyboard->focus = surface;
1168 wl_signal_emit(&keyboard->focus_signal, keyboard);
1169}
1170
Giulio Camuffoa20ca812014-11-22 11:16:56 +02001171/* Users of this function must manually manage the keyboard focus */
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001172WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -04001173weston_keyboard_start_grab(struct weston_keyboard *keyboard,
1174 struct weston_keyboard_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001175{
1176 keyboard->grab = grab;
1177 grab->keyboard = keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001178}
1179
1180WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -04001181weston_keyboard_end_grab(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001182{
1183 keyboard->grab = &keyboard->default_grab;
1184}
1185
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02001186static void
1187weston_keyboard_cancel_grab(struct weston_keyboard *keyboard)
1188{
1189 keyboard->grab->interface->cancel(keyboard->grab);
1190}
1191
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001192WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001193weston_pointer_start_grab(struct weston_pointer *pointer,
1194 struct weston_pointer_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001195{
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001196 pointer->grab = grab;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001197 grab->pointer = pointer;
Kristian Høgsbergda751b82013-07-04 00:58:07 -04001198 pointer->grab->interface->focus(pointer->grab);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001199}
1200
1201WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001202weston_pointer_end_grab(struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001203{
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001204 pointer->grab = &pointer->default_grab;
Kristian Høgsbergda751b82013-07-04 00:58:07 -04001205 pointer->grab->interface->focus(pointer->grab);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001206}
1207
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02001208static void
1209weston_pointer_cancel_grab(struct weston_pointer *pointer)
1210{
1211 pointer->grab->interface->cancel(pointer->grab);
1212}
1213
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001214WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -04001215weston_touch_start_grab(struct weston_touch *touch, struct weston_touch_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001216{
1217 touch->grab = grab;
1218 grab->touch = touch;
1219}
1220
1221WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -04001222weston_touch_end_grab(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001223{
1224 touch->grab = &touch->default_grab;
1225}
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001226
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02001227static void
1228weston_touch_cancel_grab(struct weston_touch *touch)
1229{
1230 touch->grab->interface->cancel(touch->grab);
1231}
1232
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001233static void
1234weston_pointer_clamp_for_output(struct weston_pointer *pointer,
1235 struct weston_output *output,
1236 wl_fixed_t *fx, wl_fixed_t *fy)
1237{
1238 int x, y;
1239
1240 x = wl_fixed_to_int(*fx);
1241 y = wl_fixed_to_int(*fy);
1242
1243 if (x < output->x)
1244 *fx = wl_fixed_from_int(output->x);
1245 else if (x >= output->x + output->width)
1246 *fx = wl_fixed_from_int(output->x +
1247 output->width - 1);
1248 if (y < output->y)
1249 *fy = wl_fixed_from_int(output->y);
1250 else if (y >= output->y + output->height)
1251 *fy = wl_fixed_from_int(output->y +
1252 output->height - 1);
1253}
1254
Rob Bradford806d8c02013-06-25 18:56:41 +01001255WL_EXPORT void
1256weston_pointer_clamp(struct weston_pointer *pointer, wl_fixed_t *fx, wl_fixed_t *fy)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001257{
Rob Bradford806d8c02013-06-25 18:56:41 +01001258 struct weston_compositor *ec = pointer->seat->compositor;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001259 struct weston_output *output, *prev = NULL;
1260 int x, y, old_x, old_y, valid = 0;
1261
1262 x = wl_fixed_to_int(*fx);
1263 y = wl_fixed_to_int(*fy);
Rob Bradford806d8c02013-06-25 18:56:41 +01001264 old_x = wl_fixed_to_int(pointer->x);
1265 old_y = wl_fixed_to_int(pointer->y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001266
1267 wl_list_for_each(output, &ec->output_list, link) {
Rob Bradford66bd9f52013-06-25 18:56:42 +01001268 if (pointer->seat->output && pointer->seat->output != output)
1269 continue;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001270 if (pixman_region32_contains_point(&output->region,
1271 x, y, NULL))
1272 valid = 1;
1273 if (pixman_region32_contains_point(&output->region,
1274 old_x, old_y, NULL))
1275 prev = output;
1276 }
1277
Rob Bradford66bd9f52013-06-25 18:56:42 +01001278 if (!prev)
1279 prev = pointer->seat->output;
1280
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001281 if (prev && !valid)
1282 weston_pointer_clamp_for_output(pointer, prev, fx, fy);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001283}
1284
Jonas Ådahld2510102014-10-05 21:39:14 +02001285static void
1286weston_pointer_move_to(struct weston_pointer *pointer,
1287 wl_fixed_t x, wl_fixed_t y)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001288{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001289 int32_t ix, iy;
1290
Rob Bradford806d8c02013-06-25 18:56:41 +01001291 weston_pointer_clamp (pointer, &x, &y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001292
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001293 pointer->x = x;
1294 pointer->y = y;
1295
1296 ix = wl_fixed_to_int(x);
1297 iy = wl_fixed_to_int(y);
1298
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001299 if (pointer->sprite) {
Jason Ekstranda7af7042013-10-12 22:38:11 -05001300 weston_view_set_position(pointer->sprite,
1301 ix - pointer->hotspot_x,
1302 iy - pointer->hotspot_y);
1303 weston_view_schedule_repaint(pointer->sprite);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001304 }
Giulio Camuffo6fcb3782013-11-14 23:42:50 +01001305
Giulio Camuffo1959ab82013-11-14 23:42:52 +01001306 pointer->grab->interface->focus(pointer->grab);
Giulio Camuffo6fcb3782013-11-14 23:42:50 +01001307 wl_signal_emit(&pointer->motion_signal, pointer);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001308}
1309
Jonas Ådahld2510102014-10-05 21:39:14 +02001310WL_EXPORT void
Jonas Ådahld2510102014-10-05 21:39:14 +02001311weston_pointer_move(struct weston_pointer *pointer,
1312 struct weston_pointer_motion_event *event)
1313{
1314 wl_fixed_t x, y;
1315
1316 weston_pointer_motion_to_abs(pointer, event, &x, &y);
1317 weston_pointer_move_to(pointer, x, y);
1318}
1319
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001320/** Verify if the pointer is in a valid position and move it if it isn't.
1321 */
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001322static void
1323weston_pointer_handle_output_destroy(struct wl_listener *listener, void *data)
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001324{
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001325 struct weston_pointer *pointer;
1326 struct weston_compositor *ec;
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001327 struct weston_output *output, *closest = NULL;
1328 int x, y, distance, min = INT_MAX;
1329 wl_fixed_t fx, fy;
1330
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02001331 pointer = container_of(listener, struct weston_pointer,
1332 output_destroy_listener);
1333 ec = pointer->seat->compositor;
1334
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001335 x = wl_fixed_to_int(pointer->x);
1336 y = wl_fixed_to_int(pointer->y);
1337
1338 wl_list_for_each(output, &ec->output_list, link) {
1339 if (pixman_region32_contains_point(&output->region,
1340 x, y, NULL))
1341 return;
1342
1343 /* Aproximante the distance from the pointer to the center of
1344 * the output. */
1345 distance = abs(output->x + output->width / 2 - x) +
1346 abs(output->y + output->height / 2 - y);
1347 if (distance < min) {
1348 min = distance;
1349 closest = output;
1350 }
1351 }
1352
1353 /* Nothing to do if there's no output left. */
1354 if (!closest)
1355 return;
1356
1357 fx = pointer->x;
1358 fy = pointer->y;
1359
1360 weston_pointer_clamp_for_output(pointer, closest, &fx, &fy);
Jonas Ådahld2510102014-10-05 21:39:14 +02001361 weston_pointer_move_to(pointer, fx, fy);
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +02001362}
1363
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001364WL_EXPORT void
1365notify_motion(struct weston_seat *seat,
Jonas Ådahld2510102014-10-05 21:39:14 +02001366 uint32_t time,
1367 struct weston_pointer_motion_event *event)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001368{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001369 struct weston_compositor *ec = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001370 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001371
1372 weston_compositor_wake(ec);
Jonas Ådahld2510102014-10-05 21:39:14 +02001373 pointer->grab->interface->motion(pointer->grab, time, event);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001374}
1375
Daniel Stone96d47c02013-11-19 11:37:12 +01001376static void
1377run_modifier_bindings(struct weston_seat *seat, uint32_t old, uint32_t new)
1378{
1379 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001380 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Daniel Stone96d47c02013-11-19 11:37:12 +01001381 uint32_t diff;
1382 unsigned int i;
1383 struct {
1384 uint32_t xkb;
1385 enum weston_keyboard_modifier weston;
1386 } mods[] = {
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001387 { keyboard->xkb_info->ctrl_mod, MODIFIER_CTRL },
1388 { keyboard->xkb_info->alt_mod, MODIFIER_ALT },
1389 { keyboard->xkb_info->super_mod, MODIFIER_SUPER },
1390 { keyboard->xkb_info->shift_mod, MODIFIER_SHIFT },
Daniel Stone96d47c02013-11-19 11:37:12 +01001391 };
1392
1393 diff = new & ~old;
1394 for (i = 0; i < ARRAY_LENGTH(mods); i++) {
1395 if (diff & (1 << mods[i].xkb))
1396 weston_compositor_run_modifier_binding(compositor,
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001397 keyboard,
Daniel Stone96d47c02013-11-19 11:37:12 +01001398 mods[i].weston,
1399 WL_KEYBOARD_KEY_STATE_PRESSED);
1400 }
1401
1402 diff = old & ~new;
1403 for (i = 0; i < ARRAY_LENGTH(mods); i++) {
1404 if (diff & (1 << mods[i].xkb))
1405 weston_compositor_run_modifier_binding(compositor,
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001406 keyboard,
Daniel Stone96d47c02013-11-19 11:37:12 +01001407 mods[i].weston,
1408 WL_KEYBOARD_KEY_STATE_RELEASED);
1409 }
1410}
1411
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001412WL_EXPORT void
1413notify_motion_absolute(struct weston_seat *seat,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001414 uint32_t time, double x, double y)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001415{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001416 struct weston_compositor *ec = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001417 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Jonas Ådahld2510102014-10-05 21:39:14 +02001418 struct weston_pointer_motion_event event = { 0 };
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001419
1420 weston_compositor_wake(ec);
Jonas Ådahld2510102014-10-05 21:39:14 +02001421
1422 event = (struct weston_pointer_motion_event) {
1423 .mask = WESTON_POINTER_MOTION_ABS,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001424 .x = x,
1425 .y = y,
Jonas Ådahld2510102014-10-05 21:39:14 +02001426 };
1427
1428 pointer->grab->interface->motion(pointer->grab, time, &event);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001429}
1430
Jonas Ådahl94e2e2d2014-10-18 18:42:19 +02001431static unsigned int
1432peek_next_activate_serial(struct weston_compositor *c)
1433{
1434 unsigned serial = c->activate_serial + 1;
1435
1436 return serial == 0 ? 1 : serial;
1437}
1438
1439static void
1440inc_activate_serial(struct weston_compositor *c)
1441{
1442 c->activate_serial = peek_next_activate_serial (c);
1443}
1444
1445WL_EXPORT void
1446weston_view_activate(struct weston_view *view,
1447 struct weston_seat *seat,
1448 uint32_t flags)
1449{
1450 struct weston_compositor *compositor = seat->compositor;
1451
1452 if (flags & WESTON_ACTIVATE_FLAG_CLICKED) {
1453 view->click_to_activate_serial =
1454 peek_next_activate_serial(compositor);
1455 }
1456
1457 weston_seat_set_keyboard_focus(seat, view->surface);
1458}
1459
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001460WL_EXPORT void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001461notify_button(struct weston_seat *seat, uint32_t time, int32_t button,
1462 enum wl_pointer_button_state state)
1463{
1464 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001465 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001466
1467 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001468 weston_compositor_idle_inhibit(compositor);
1469 if (pointer->button_count == 0) {
1470 pointer->grab_button = button;
1471 pointer->grab_time = time;
1472 pointer->grab_x = pointer->x;
1473 pointer->grab_y = pointer->y;
1474 }
1475 pointer->button_count++;
1476 } else {
1477 weston_compositor_idle_release(compositor);
1478 pointer->button_count--;
1479 }
1480
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001481 weston_compositor_run_button_binding(compositor, pointer, time, button,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001482 state);
1483
1484 pointer->grab->interface->button(pointer->grab, time, button, state);
1485
1486 if (pointer->button_count == 1)
1487 pointer->grab_serial =
1488 wl_display_get_serial(compositor->wl_display);
1489}
1490
1491WL_EXPORT void
Peter Hutterer89b6a492016-01-18 15:58:17 +10001492notify_axis(struct weston_seat *seat, uint32_t time,
1493 struct weston_pointer_axis_event *event)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001494{
1495 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001496 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001497
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001498 weston_compositor_wake(compositor);
1499
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001500 if (weston_compositor_run_axis_binding(compositor, pointer,
Peter Hutterer89b6a492016-01-18 15:58:17 +10001501 time, event))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001502 return;
1503
Peter Hutterer89b6a492016-01-18 15:58:17 +10001504 pointer->grab->interface->axis(pointer->grab, time, event);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001505}
1506
Peter Hutterer87743e92016-01-18 16:38:22 +10001507WL_EXPORT void
1508notify_axis_source(struct weston_seat *seat, uint32_t source)
1509{
1510 struct weston_compositor *compositor = seat->compositor;
1511 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1512
1513 weston_compositor_wake(compositor);
1514
1515 pointer->grab->interface->axis_source(pointer->grab, source);
1516}
1517
1518WL_EXPORT void
1519notify_pointer_frame(struct weston_seat *seat)
1520{
1521 struct weston_compositor *compositor = seat->compositor;
1522 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1523
1524 weston_compositor_wake(compositor);
1525
1526 pointer->grab->interface->frame(pointer->grab);
1527}
1528
Giulio Camuffo6ef444d2014-08-28 19:44:09 +03001529WL_EXPORT int
1530weston_keyboard_set_locks(struct weston_keyboard *keyboard,
1531 uint32_t mask, uint32_t value)
1532{
1533#ifdef ENABLE_XKBCOMMON
1534 uint32_t serial;
1535 xkb_mod_mask_t mods_depressed, mods_latched, mods_locked, group;
1536 xkb_mod_mask_t num, caps;
1537
1538 /* We don't want the leds to go out of sync with the actual state
1539 * so if the backend has no way to change the leds don't try to
1540 * change the state */
1541 if (!keyboard->seat->led_update)
1542 return -1;
1543
1544 mods_depressed = xkb_state_serialize_mods(keyboard->xkb_state.state,
1545 XKB_STATE_DEPRESSED);
1546 mods_latched = xkb_state_serialize_mods(keyboard->xkb_state.state,
1547 XKB_STATE_LATCHED);
1548 mods_locked = xkb_state_serialize_mods(keyboard->xkb_state.state,
1549 XKB_STATE_LOCKED);
1550 group = xkb_state_serialize_group(keyboard->xkb_state.state,
1551 XKB_STATE_EFFECTIVE);
1552
1553 num = (1 << keyboard->xkb_info->mod2_mod);
1554 caps = (1 << keyboard->xkb_info->caps_mod);
1555 if (mask & WESTON_NUM_LOCK) {
1556 if (value & WESTON_NUM_LOCK)
1557 mods_locked |= num;
1558 else
1559 mods_locked &= ~num;
1560 }
1561 if (mask & WESTON_CAPS_LOCK) {
1562 if (value & WESTON_CAPS_LOCK)
1563 mods_locked |= caps;
1564 else
1565 mods_locked &= ~caps;
1566 }
1567
1568 xkb_state_update_mask(keyboard->xkb_state.state, mods_depressed,
1569 mods_latched, mods_locked, 0, 0, group);
1570
1571 serial = wl_display_next_serial(
1572 keyboard->seat->compositor->wl_display);
1573 notify_modifiers(keyboard->seat, serial);
1574
1575 return 0;
1576#else
1577 return -1;
1578#endif
1579}
1580
Rob Bradford382ff462013-06-24 16:52:45 +01001581#ifdef ENABLE_XKBCOMMON
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001582WL_EXPORT void
1583notify_modifiers(struct weston_seat *seat, uint32_t serial)
1584{
Derek Foreman1281a362015-07-31 16:55:32 -05001585 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001586 struct weston_keyboard_grab *grab = keyboard->grab;
1587 uint32_t mods_depressed, mods_latched, mods_locked, group;
1588 uint32_t mods_lookup;
1589 enum weston_led leds = 0;
1590 int changed = 0;
1591
1592 /* Serialize and update our internal state, checking to see if it's
1593 * different to the previous state. */
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001594 mods_depressed = xkb_state_serialize_mods(keyboard->xkb_state.state,
Ran Benita2e1968f2014-08-19 23:59:51 +03001595 XKB_STATE_MODS_DEPRESSED);
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001596 mods_latched = xkb_state_serialize_mods(keyboard->xkb_state.state,
Ran Benita2e1968f2014-08-19 23:59:51 +03001597 XKB_STATE_MODS_LATCHED);
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001598 mods_locked = xkb_state_serialize_mods(keyboard->xkb_state.state,
Ran Benita2e1968f2014-08-19 23:59:51 +03001599 XKB_STATE_MODS_LOCKED);
1600 group = xkb_state_serialize_layout(keyboard->xkb_state.state,
1601 XKB_STATE_LAYOUT_EFFECTIVE);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001602
Derek Foreman244e99e2015-06-03 15:53:26 -05001603 if (mods_depressed != keyboard->modifiers.mods_depressed ||
1604 mods_latched != keyboard->modifiers.mods_latched ||
1605 mods_locked != keyboard->modifiers.mods_locked ||
1606 group != keyboard->modifiers.group)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001607 changed = 1;
1608
Derek Foreman244e99e2015-06-03 15:53:26 -05001609 run_modifier_bindings(seat, keyboard->modifiers.mods_depressed,
Daniel Stone96d47c02013-11-19 11:37:12 +01001610 mods_depressed);
1611
Derek Foreman244e99e2015-06-03 15:53:26 -05001612 keyboard->modifiers.mods_depressed = mods_depressed;
1613 keyboard->modifiers.mods_latched = mods_latched;
1614 keyboard->modifiers.mods_locked = mods_locked;
1615 keyboard->modifiers.group = group;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001616
1617 /* And update the modifier_state for bindings. */
1618 mods_lookup = mods_depressed | mods_latched;
1619 seat->modifier_state = 0;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001620 if (mods_lookup & (1 << keyboard->xkb_info->ctrl_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001621 seat->modifier_state |= MODIFIER_CTRL;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001622 if (mods_lookup & (1 << keyboard->xkb_info->alt_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001623 seat->modifier_state |= MODIFIER_ALT;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001624 if (mods_lookup & (1 << keyboard->xkb_info->super_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001625 seat->modifier_state |= MODIFIER_SUPER;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001626 if (mods_lookup & (1 << keyboard->xkb_info->shift_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001627 seat->modifier_state |= MODIFIER_SHIFT;
1628
1629 /* Finally, notify the compositor that LEDs have changed. */
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001630 if (xkb_state_led_index_is_active(keyboard->xkb_state.state,
1631 keyboard->xkb_info->num_led))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001632 leds |= LED_NUM_LOCK;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001633 if (xkb_state_led_index_is_active(keyboard->xkb_state.state,
1634 keyboard->xkb_info->caps_led))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001635 leds |= LED_CAPS_LOCK;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001636 if (xkb_state_led_index_is_active(keyboard->xkb_state.state,
1637 keyboard->xkb_info->scroll_led))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001638 leds |= LED_SCROLL_LOCK;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001639 if (leds != keyboard->xkb_state.leds && seat->led_update)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001640 seat->led_update(seat, leds);
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001641 keyboard->xkb_state.leds = leds;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001642
1643 if (changed) {
1644 grab->interface->modifiers(grab,
1645 serial,
1646 keyboard->modifiers.mods_depressed,
1647 keyboard->modifiers.mods_latched,
1648 keyboard->modifiers.mods_locked,
1649 keyboard->modifiers.group);
1650 }
1651}
1652
1653static void
1654update_modifier_state(struct weston_seat *seat, uint32_t serial, uint32_t key,
1655 enum wl_keyboard_key_state state)
1656{
Derek Foreman1281a362015-07-31 16:55:32 -05001657 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001658 enum xkb_key_direction direction;
1659
Matt Roper01a92732013-06-24 16:52:44 +01001660 /* Keyboard modifiers don't exist in raw keyboard mode */
1661 if (!seat->compositor->use_xkbcommon)
1662 return;
1663
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001664 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
1665 direction = XKB_KEY_DOWN;
1666 else
1667 direction = XKB_KEY_UP;
1668
1669 /* Offset the keycode by 8, as the evdev XKB rules reflect X's
1670 * broken keycode system, which starts at 8. */
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001671 xkb_state_update_key(keyboard->xkb_state.state, key + 8, direction);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001672
1673 notify_modifiers(seat, serial);
1674}
Rui Matos65196bc2013-10-10 19:44:19 +02001675
1676static void
1677send_keymap(struct wl_resource *resource, struct weston_xkb_info *xkb_info)
1678{
1679 wl_keyboard_send_keymap(resource,
1680 WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
1681 xkb_info->keymap_fd,
1682 xkb_info->keymap_size);
1683}
1684
1685static void
1686send_modifiers(struct wl_resource *resource, uint32_t serial, struct weston_keyboard *keyboard)
1687{
1688 wl_keyboard_send_modifiers(resource, serial,
1689 keyboard->modifiers.mods_depressed,
1690 keyboard->modifiers.mods_latched,
1691 keyboard->modifiers.mods_locked,
1692 keyboard->modifiers.group);
1693}
1694
1695static struct weston_xkb_info *
1696weston_xkb_info_create(struct xkb_keymap *keymap);
Rui Matos65196bc2013-10-10 19:44:19 +02001697
1698static void
1699update_keymap(struct weston_seat *seat)
1700{
Derek Foreman1281a362015-07-31 16:55:32 -05001701 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Rui Matos65196bc2013-10-10 19:44:19 +02001702 struct wl_resource *resource;
1703 struct weston_xkb_info *xkb_info;
1704 struct xkb_state *state;
1705 xkb_mod_mask_t latched_mods;
1706 xkb_mod_mask_t locked_mods;
1707
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001708 xkb_info = weston_xkb_info_create(keyboard->pending_keymap);
Rui Matos65196bc2013-10-10 19:44:19 +02001709
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001710 xkb_keymap_unref(keyboard->pending_keymap);
1711 keyboard->pending_keymap = NULL;
Rui Matos65196bc2013-10-10 19:44:19 +02001712
1713 if (!xkb_info) {
1714 weston_log("failed to create XKB info\n");
1715 return;
1716 }
1717
1718 state = xkb_state_new(xkb_info->keymap);
1719 if (!state) {
1720 weston_log("failed to initialise XKB state\n");
1721 weston_xkb_info_destroy(xkb_info);
1722 return;
1723 }
1724
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001725 latched_mods = xkb_state_serialize_mods(keyboard->xkb_state.state,
1726 XKB_STATE_MODS_LATCHED);
1727 locked_mods = xkb_state_serialize_mods(keyboard->xkb_state.state,
1728 XKB_STATE_MODS_LOCKED);
Rui Matos65196bc2013-10-10 19:44:19 +02001729 xkb_state_update_mask(state,
1730 0, /* depressed */
1731 latched_mods,
1732 locked_mods,
1733 0, 0, 0);
1734
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001735 weston_xkb_info_destroy(keyboard->xkb_info);
1736 keyboard->xkb_info = xkb_info;
Rui Matos65196bc2013-10-10 19:44:19 +02001737
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001738 xkb_state_unref(keyboard->xkb_state.state);
1739 keyboard->xkb_state.state = state;
Rui Matos65196bc2013-10-10 19:44:19 +02001740
Derek Foremanbc91e542015-06-03 15:53:27 -05001741 wl_resource_for_each(resource, &keyboard->resource_list)
Rui Matos65196bc2013-10-10 19:44:19 +02001742 send_keymap(resource, xkb_info);
Derek Foremanbc91e542015-06-03 15:53:27 -05001743 wl_resource_for_each(resource, &keyboard->focus_resource_list)
Rui Matos65196bc2013-10-10 19:44:19 +02001744 send_keymap(resource, xkb_info);
1745
1746 notify_modifiers(seat, wl_display_next_serial(seat->compositor->wl_display));
1747
1748 if (!latched_mods && !locked_mods)
1749 return;
1750
Derek Foremanbc91e542015-06-03 15:53:27 -05001751 wl_resource_for_each(resource, &keyboard->resource_list)
1752 send_modifiers(resource, wl_display_get_serial(seat->compositor->wl_display), keyboard);
1753 wl_resource_for_each(resource, &keyboard->focus_resource_list)
1754 send_modifiers(resource, wl_display_get_serial(seat->compositor->wl_display), keyboard);
Rui Matos65196bc2013-10-10 19:44:19 +02001755}
Rob Bradford382ff462013-06-24 16:52:45 +01001756#else
1757WL_EXPORT void
1758notify_modifiers(struct weston_seat *seat, uint32_t serial)
1759{
1760}
1761
1762static void
1763update_modifier_state(struct weston_seat *seat, uint32_t serial, uint32_t key,
1764 enum wl_keyboard_key_state state)
1765{
1766}
Rui Matos65196bc2013-10-10 19:44:19 +02001767
1768static void
1769update_keymap(struct weston_seat *seat)
1770{
1771}
Rob Bradford382ff462013-06-24 16:52:45 +01001772#endif
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001773
1774WL_EXPORT void
1775notify_key(struct weston_seat *seat, uint32_t time, uint32_t key,
1776 enum wl_keyboard_key_state state,
1777 enum weston_key_state_update update_state)
1778{
1779 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001780 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001781 struct weston_keyboard_grab *grab = keyboard->grab;
Pekka Paalanen86b53962014-11-19 13:43:32 +02001782 uint32_t *k, *end;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001783
1784 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001785 weston_compositor_idle_inhibit(compositor);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001786 } else {
1787 weston_compositor_idle_release(compositor);
1788 }
1789
Pekka Paalanen86b53962014-11-19 13:43:32 +02001790 end = keyboard->keys.data + keyboard->keys.size;
1791 for (k = keyboard->keys.data; k < end; k++) {
1792 if (*k == key) {
1793 /* Ignore server-generated repeats. */
1794 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
1795 return;
1796 *k = *--end;
1797 }
1798 }
1799 keyboard->keys.size = (void *) end - keyboard->keys.data;
1800 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
1801 k = wl_array_add(&keyboard->keys, sizeof *k);
1802 *k = key;
1803 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001804
1805 if (grab == &keyboard->default_grab ||
1806 grab == &keyboard->input_method_grab) {
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001807 weston_compositor_run_key_binding(compositor, keyboard, time,
1808 key, state);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001809 grab = keyboard->grab;
1810 }
1811
1812 grab->interface->key(grab, time, key, state);
1813
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001814 if (keyboard->pending_keymap &&
Pekka Paalanen86b53962014-11-19 13:43:32 +02001815 keyboard->keys.size == 0)
Rui Matos65196bc2013-10-10 19:44:19 +02001816 update_keymap(seat);
1817
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001818 if (update_state == STATE_UPDATE_AUTOMATIC) {
1819 update_modifier_state(seat,
1820 wl_display_get_serial(compositor->wl_display),
1821 key,
1822 state);
1823 }
Giulio Camuffob6ddf6c2015-02-06 19:06:54 +02001824
1825 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
1826 keyboard->grab_serial =
1827 wl_display_get_serial(compositor->wl_display);
1828 keyboard->grab_time = time;
1829 keyboard->grab_key = key;
1830 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001831}
1832
1833WL_EXPORT void
1834notify_pointer_focus(struct weston_seat *seat, struct weston_output *output,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001835 double x, double y)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001836{
Derek Foreman1281a362015-07-31 16:55:32 -05001837 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1838
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001839 if (output) {
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001840 weston_pointer_move_to(pointer,
1841 wl_fixed_from_double(x),
1842 wl_fixed_from_double(y));
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001843 } else {
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001844 /* FIXME: We should call weston_pointer_set_focus(seat,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001845 * NULL) here, but somehow that breaks re-entry... */
1846 }
1847}
1848
1849static void
1850destroy_device_saved_kbd_focus(struct wl_listener *listener, void *data)
1851{
1852 struct weston_seat *ws;
1853
1854 ws = container_of(listener, struct weston_seat,
1855 saved_kbd_focus_listener);
1856
1857 ws->saved_kbd_focus = NULL;
1858}
1859
1860WL_EXPORT void
1861notify_keyboard_focus_in(struct weston_seat *seat, struct wl_array *keys,
1862 enum weston_key_state_update update_state)
1863{
1864 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001865 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -04001866 struct weston_surface *surface;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001867 uint32_t *k, serial;
1868
1869 serial = wl_display_next_serial(compositor->wl_display);
1870 wl_array_copy(&keyboard->keys, keys);
1871 wl_array_for_each(k, &keyboard->keys) {
1872 weston_compositor_idle_inhibit(compositor);
1873 if (update_state == STATE_UPDATE_AUTOMATIC)
1874 update_modifier_state(seat, serial, *k,
1875 WL_KEYBOARD_KEY_STATE_PRESSED);
1876 }
1877
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001878 surface = seat->saved_kbd_focus;
1879
1880 if (surface) {
1881 wl_list_remove(&seat->saved_kbd_focus_listener.link);
1882 weston_keyboard_set_focus(keyboard, surface);
1883 seat->saved_kbd_focus = NULL;
1884 }
1885}
1886
1887WL_EXPORT void
1888notify_keyboard_focus_out(struct weston_seat *seat)
1889{
1890 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001891 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
1892 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001893 uint32_t *k, serial;
1894
1895 serial = wl_display_next_serial(compositor->wl_display);
1896 wl_array_for_each(k, &keyboard->keys) {
1897 weston_compositor_idle_release(compositor);
1898 update_modifier_state(seat, serial, *k,
1899 WL_KEYBOARD_KEY_STATE_RELEASED);
1900 }
1901
1902 seat->modifier_state = 0;
1903
1904 if (keyboard->focus) {
1905 seat->saved_kbd_focus = keyboard->focus;
1906 seat->saved_kbd_focus_listener.notify =
1907 destroy_device_saved_kbd_focus;
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05001908 wl_signal_add(&keyboard->focus->destroy_signal,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001909 &seat->saved_kbd_focus_listener);
1910 }
1911
1912 weston_keyboard_set_focus(keyboard, NULL);
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02001913 weston_keyboard_cancel_grab(keyboard);
Derek Foreman1281a362015-07-31 16:55:32 -05001914 if (pointer)
1915 weston_pointer_cancel_grab(pointer);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001916}
1917
Michael Fua2bb7912013-07-23 15:51:06 +08001918WL_EXPORT void
Derek Foreman4c93c082015-04-30 16:45:41 -05001919weston_touch_set_focus(struct weston_touch *touch, struct weston_view *view)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001920{
Neil Roberts96d790e2013-09-19 17:32:00 +01001921 struct wl_list *focus_resource_list;
1922
Derek Foreman4c93c082015-04-30 16:45:41 -05001923 focus_resource_list = &touch->focus_resource_list;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001924
Derek Foreman4c93c082015-04-30 16:45:41 -05001925 if (view && touch->focus &&
1926 touch->focus->surface == view->surface) {
1927 touch->focus = view;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001928 return;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001929 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001930
Derek Foreman4c93c082015-04-30 16:45:41 -05001931 wl_list_remove(&touch->focus_resource_listener.link);
1932 wl_list_init(&touch->focus_resource_listener.link);
1933 wl_list_remove(&touch->focus_view_listener.link);
1934 wl_list_init(&touch->focus_view_listener.link);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001935
Neil Roberts96d790e2013-09-19 17:32:00 +01001936 if (!wl_list_empty(focus_resource_list)) {
Derek Foreman4c93c082015-04-30 16:45:41 -05001937 move_resources(&touch->resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01001938 focus_resource_list);
1939 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001940
Jason Ekstranda7af7042013-10-12 22:38:11 -05001941 if (view) {
Derek Foreman362656b2014-09-04 10:23:05 -05001942 struct wl_client *surface_client;
1943
1944 if (!view->surface->resource) {
Derek Foreman4c93c082015-04-30 16:45:41 -05001945 touch->focus = NULL;
Derek Foreman362656b2014-09-04 10:23:05 -05001946 return;
1947 }
1948
1949 surface_client = wl_resource_get_client(view->surface->resource);
Neil Roberts96d790e2013-09-19 17:32:00 +01001950 move_resources_for_client(focus_resource_list,
Derek Foreman4c93c082015-04-30 16:45:41 -05001951 &touch->resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01001952 surface_client);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001953 wl_resource_add_destroy_listener(view->surface->resource,
Derek Foreman4c93c082015-04-30 16:45:41 -05001954 &touch->focus_resource_listener);
1955 wl_signal_add(&view->destroy_signal, &touch->focus_view_listener);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001956 }
Derek Foreman4c93c082015-04-30 16:45:41 -05001957 touch->focus = view;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001958}
1959
1960/**
1961 * notify_touch - emulates button touches and notifies surfaces accordingly.
1962 *
1963 * It assumes always the correct cycle sequence until it gets here: touch_down
1964 * → touch_update → ... → touch_update → touch_end. The driver is responsible
1965 * for sending along such order.
1966 *
1967 */
1968WL_EXPORT void
1969notify_touch(struct weston_seat *seat, uint32_t time, int touch_id,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001970 double double_x, double double_y, int touch_type)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001971{
1972 struct weston_compositor *ec = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001973 struct weston_touch *touch = weston_seat_get_touch(seat);
Kristian Høgsberge329f362013-05-06 22:19:57 -04001974 struct weston_touch_grab *grab = touch->grab;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001975 struct weston_view *ev;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001976 wl_fixed_t sx, sy;
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001977 wl_fixed_t x = wl_fixed_from_double(double_x);
1978 wl_fixed_t y = wl_fixed_from_double(double_y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001979
1980 /* Update grab's global coordinates. */
Neil Roberts306fe082013-10-03 16:43:06 +01001981 if (touch_id == touch->grab_touch_id && touch_type != WL_TOUCH_UP) {
1982 touch->grab_x = x;
1983 touch->grab_y = y;
1984 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001985
1986 switch (touch_type) {
1987 case WL_TOUCH_DOWN:
1988 weston_compositor_idle_inhibit(ec);
1989
Jonas Ådahl9484b692013-12-02 22:05:03 +01001990 touch->num_tp++;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001991
Jason Ekstranda7af7042013-10-12 22:38:11 -05001992 /* the first finger down picks the view, and all further go
1993 * to that view for the remainder of the touch session i.e.
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001994 * until all touch points are up again. */
Jonas Ådahl9484b692013-12-02 22:05:03 +01001995 if (touch->num_tp == 1) {
Jason Ekstranda7af7042013-10-12 22:38:11 -05001996 ev = weston_compositor_pick_view(ec, x, y, &sx, &sy);
Derek Foreman4c93c082015-04-30 16:45:41 -05001997 weston_touch_set_focus(touch, ev);
Giulio Camuffo61ed7b62015-07-08 11:55:28 +03001998 } else if (!touch->focus) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001999 /* Unexpected condition: We have non-initial touch but
2000 * there is no focused surface.
2001 */
Chris Michael3f607d32015-10-07 11:59:49 -04002002 weston_log("touch event received with %d points down "
Jonas Ådahl9484b692013-12-02 22:05:03 +01002003 "but no surface focused\n", touch->num_tp);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002004 return;
2005 }
2006
Derek Foreman99a6a2d2015-07-15 13:00:43 -05002007 weston_compositor_run_touch_binding(ec, touch,
Kristian Høgsbergc8964012014-02-05 14:25:18 -08002008 time, touch_type);
2009
Giulio Camuffo61ed7b62015-07-08 11:55:28 +03002010 grab->interface->down(grab, time, touch_id, x, y);
Jonas Ådahl9484b692013-12-02 22:05:03 +01002011 if (touch->num_tp == 1) {
Rusty Lynchf1407ff2013-08-08 21:13:57 -07002012 touch->grab_serial =
2013 wl_display_get_serial(ec->wl_display);
Neil Roberts306fe082013-10-03 16:43:06 +01002014 touch->grab_touch_id = touch_id;
Rusty Lynchf1407ff2013-08-08 21:13:57 -07002015 touch->grab_time = time;
2016 touch->grab_x = x;
2017 touch->grab_y = y;
2018 }
2019
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002020 break;
2021 case WL_TOUCH_MOTION:
Jason Ekstranda7af7042013-10-12 22:38:11 -05002022 ev = touch->focus;
2023 if (!ev)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002024 break;
2025
Giulio Camuffo61ed7b62015-07-08 11:55:28 +03002026 grab->interface->motion(grab, time, touch_id, x, y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002027 break;
2028 case WL_TOUCH_UP:
Kristian Høgsberga30e29a2014-01-08 22:29:20 -08002029 if (touch->num_tp == 0) {
2030 /* This can happen if we start out with one or
2031 * more fingers on the touch screen, in which
2032 * case we didn't get the corresponding down
2033 * event. */
2034 weston_log("unmatched touch up event\n");
2035 break;
2036 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002037 weston_compositor_idle_release(ec);
Jonas Ådahl9484b692013-12-02 22:05:03 +01002038 touch->num_tp--;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002039
2040 grab->interface->up(grab, time, touch_id);
Jonas Ådahl9484b692013-12-02 22:05:03 +01002041 if (touch->num_tp == 0)
Derek Foreman4c93c082015-04-30 16:45:41 -05002042 weston_touch_set_focus(touch, NULL);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002043 break;
2044 }
2045}
2046
Jonas Ådahl1679f232014-04-12 09:39:51 +02002047WL_EXPORT void
2048notify_touch_frame(struct weston_seat *seat)
2049{
Derek Foreman1281a362015-07-31 16:55:32 -05002050 struct weston_touch *touch = weston_seat_get_touch(seat);
Jonas Ådahl1679f232014-04-12 09:39:51 +02002051 struct weston_touch_grab *grab = touch->grab;
2052
2053 grab->interface->frame(grab);
2054}
2055
Derek Foreman3cc004a2015-11-06 15:56:09 -06002056WL_EXPORT void
2057notify_touch_cancel(struct weston_seat *seat)
2058{
2059 struct weston_touch *touch = weston_seat_get_touch(seat);
2060 struct weston_touch_grab *grab = touch->grab;
2061
2062 grab->interface->cancel(grab);
2063}
2064
Pekka Paalanen8274d902014-08-06 19:36:51 +03002065static int
2066pointer_cursor_surface_get_label(struct weston_surface *surface,
2067 char *buf, size_t len)
2068{
2069 return snprintf(buf, len, "cursor");
2070}
2071
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002072static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002073pointer_cursor_surface_configure(struct weston_surface *es,
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06002074 int32_t dx, int32_t dy)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002075{
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002076 struct weston_pointer *pointer = es->configure_private;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002077 int x, y;
2078
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06002079 if (es->width == 0)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002080 return;
2081
Jason Ekstranda7af7042013-10-12 22:38:11 -05002082 assert(es == pointer->sprite->surface);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002083
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002084 pointer->hotspot_x -= dx;
2085 pointer->hotspot_y -= dy;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002086
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002087 x = wl_fixed_to_int(pointer->x) - pointer->hotspot_x;
2088 y = wl_fixed_to_int(pointer->y) - pointer->hotspot_y;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002089
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06002090 weston_view_set_position(pointer->sprite, x, y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002091
2092 empty_region(&es->pending.input);
Ander Conselvan de Oliveira23900f72014-01-31 16:07:51 +02002093 empty_region(&es->input);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002094
2095 if (!weston_surface_is_mapped(es)) {
Giulio Camuffo412e6a52014-07-09 22:12:56 +03002096 weston_layer_entry_insert(&es->compositor->cursor_layer.view_list,
2097 &pointer->sprite->layer_link);
Jason Ekstranda7af7042013-10-12 22:38:11 -05002098 weston_view_update_transform(pointer->sprite);
Armin Krezovićf8486c32016-06-30 06:04:28 +02002099 es->is_mapped = true;
2100 pointer->sprite->is_mapped = true;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002101 }
2102}
2103
2104static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002105pointer_set_cursor(struct wl_client *client, struct wl_resource *resource,
2106 uint32_t serial, struct wl_resource *surface_resource,
2107 int32_t x, int32_t y)
2108{
Jason Ekstrand44a38632013-06-14 10:08:00 -05002109 struct weston_pointer *pointer = wl_resource_get_user_data(resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002110 struct weston_surface *surface = NULL;
2111
2112 if (surface_resource)
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05002113 surface = wl_resource_get_user_data(surface_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002114
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002115 if (pointer->focus == NULL)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002116 return;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002117 /* pointer->focus->surface->resource can be NULL. Surfaces like the
Giulio Camuffo1fd4b012013-06-20 18:13:07 +02002118 black_surface used in shell.c for fullscreen don't have
2119 a resource, but can still have focus */
Jason Ekstranda7af7042013-10-12 22:38:11 -05002120 if (pointer->focus->surface->resource == NULL)
Giulio Camuffo1fd4b012013-06-20 18:13:07 +02002121 return;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002122 if (wl_resource_get_client(pointer->focus->surface->resource) != client)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002123 return;
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002124 if (pointer->focus_serial - serial > UINT32_MAX / 2)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002125 return;
2126
Derek Foreman4e53c532015-03-23 10:55:32 -05002127 if (!surface) {
2128 if (pointer->sprite)
2129 pointer_unmap_sprite(pointer);
2130 return;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002131 }
2132
Jonas Ådahlb4070242015-03-18 15:08:03 +08002133 if (pointer->sprite && pointer->sprite->surface == surface &&
2134 pointer->hotspot_x == x && pointer->hotspot_y == y)
2135 return;
2136
Derek Foreman4e53c532015-03-23 10:55:32 -05002137 if (!pointer->sprite || pointer->sprite->surface != surface) {
2138 if (weston_surface_set_role(surface, "wl_pointer-cursor",
2139 resource,
2140 WL_POINTER_ERROR_ROLE) < 0)
2141 return;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002142
Derek Foreman4e53c532015-03-23 10:55:32 -05002143 if (pointer->sprite)
2144 pointer_unmap_sprite(pointer);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002145
Derek Foreman4e53c532015-03-23 10:55:32 -05002146 wl_signal_add(&surface->destroy_signal,
2147 &pointer->sprite_destroy_listener);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002148
Derek Foreman4e53c532015-03-23 10:55:32 -05002149 surface->configure = pointer_cursor_surface_configure;
2150 surface->configure_private = pointer;
2151 weston_surface_set_label_func(surface,
2152 pointer_cursor_surface_get_label);
2153 pointer->sprite = weston_view_create(surface);
2154 }
2155
Kristian Høgsberg195b8692013-05-08 15:02:05 -04002156 pointer->hotspot_x = x;
2157 pointer->hotspot_y = y;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002158
Jonas Ådahl16fe4dc2014-09-08 19:33:41 +02002159 if (surface->buffer_ref.buffer) {
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06002160 pointer_cursor_surface_configure(surface, 0, 0);
Jonas Ådahl16fe4dc2014-09-08 19:33:41 +02002161 weston_view_schedule_repaint(pointer->sprite);
2162 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002163}
2164
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002165static void
2166pointer_release(struct wl_client *client, struct wl_resource *resource)
2167{
2168 wl_resource_destroy(resource);
2169}
2170
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002171static const struct wl_pointer_interface pointer_interface = {
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002172 pointer_set_cursor,
2173 pointer_release
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002174};
2175
2176static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002177seat_get_pointer(struct wl_client *client, struct wl_resource *resource,
2178 uint32_t id)
2179{
Jason Ekstrand44a38632013-06-14 10:08:00 -05002180 struct weston_seat *seat = wl_resource_get_user_data(resource);
Derek Foreman1281a362015-07-31 16:55:32 -05002181 /* We use the pointer_state directly, which means we'll
2182 * give a wl_pointer if the seat has ever had one - even though
2183 * the spec explicitly states that this request only takes effect
2184 * if the seat has the pointer capability.
2185 *
2186 * This prevents a race between the compositor sending new
2187 * capabilities and the client trying to use the old ones.
2188 */
2189 struct weston_pointer *pointer = seat->pointer_state;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002190 struct wl_resource *cr;
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08002191 struct weston_pointer_client *pointer_client;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002192
Derek Foreman1281a362015-07-31 16:55:32 -05002193 if (!pointer)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002194 return;
2195
Jason Ekstranda85118c2013-06-27 20:17:02 -05002196 cr = wl_resource_create(client, &wl_pointer_interface,
2197 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07002198 if (cr == NULL) {
2199 wl_client_post_no_memory(client);
2200 return;
2201 }
2202
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08002203 pointer_client = weston_pointer_ensure_pointer_client(pointer, client);
2204 if (!pointer_client) {
2205 wl_client_post_no_memory(client);
2206 return;
2207 }
2208
2209 wl_list_insert(&pointer_client->pointer_resources,
2210 wl_resource_get_link(cr));
Derek Foreman1281a362015-07-31 16:55:32 -05002211 wl_resource_set_implementation(cr, &pointer_interface, pointer,
Jonas Ådahl2cbf2932015-07-22 12:05:38 +08002212 unbind_pointer_client_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002213
Derek Foreman1281a362015-07-31 16:55:32 -05002214 if (pointer->focus && pointer->focus->surface->resource &&
2215 wl_resource_get_client(pointer->focus->surface->resource) == client) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002216 wl_fixed_t sx, sy;
2217
Derek Foreman1281a362015-07-31 16:55:32 -05002218 weston_view_from_global_fixed(pointer->focus,
2219 pointer->x,
2220 pointer->y,
Jason Ekstranda7af7042013-10-12 22:38:11 -05002221 &sx, &sy);
Neil Roberts96d790e2013-09-19 17:32:00 +01002222
Neil Roberts96d790e2013-09-19 17:32:00 +01002223 wl_pointer_send_enter(cr,
Derek Foreman1281a362015-07-31 16:55:32 -05002224 pointer->focus_serial,
2225 pointer->focus->surface->resource,
Neil Roberts96d790e2013-09-19 17:32:00 +01002226 sx, sy);
Peter Hutterer87743e92016-01-18 16:38:22 +10002227 pointer_send_frame(cr);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002228 }
2229}
2230
2231static void
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002232keyboard_release(struct wl_client *client, struct wl_resource *resource)
2233{
2234 wl_resource_destroy(resource);
2235}
2236
2237static const struct wl_keyboard_interface keyboard_interface = {
2238 keyboard_release
2239};
2240
Derek Foreman280e7dd2014-10-03 13:13:42 -05002241static bool
Neil Roberts96d790e2013-09-19 17:32:00 +01002242should_send_modifiers_to_client(struct weston_seat *seat,
2243 struct wl_client *client)
2244{
Derek Foreman1281a362015-07-31 16:55:32 -05002245 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
2246 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
2247
2248 if (keyboard &&
2249 keyboard->focus &&
2250 keyboard->focus->resource &&
2251 wl_resource_get_client(keyboard->focus->resource) == client)
Derek Foreman280e7dd2014-10-03 13:13:42 -05002252 return true;
Neil Roberts96d790e2013-09-19 17:32:00 +01002253
Derek Foreman1281a362015-07-31 16:55:32 -05002254 if (pointer &&
2255 pointer->focus &&
2256 pointer->focus->surface->resource &&
2257 wl_resource_get_client(pointer->focus->surface->resource) == client)
Derek Foreman280e7dd2014-10-03 13:13:42 -05002258 return true;
Neil Roberts96d790e2013-09-19 17:32:00 +01002259
Derek Foreman280e7dd2014-10-03 13:13:42 -05002260 return false;
Neil Roberts96d790e2013-09-19 17:32:00 +01002261}
2262
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002263static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002264seat_get_keyboard(struct wl_client *client, struct wl_resource *resource,
2265 uint32_t id)
2266{
Jason Ekstrand44a38632013-06-14 10:08:00 -05002267 struct weston_seat *seat = wl_resource_get_user_data(resource);
Derek Foreman1281a362015-07-31 16:55:32 -05002268 /* We use the keyboard_state directly, which means we'll
2269 * give a wl_keyboard if the seat has ever had one - even though
2270 * the spec explicitly states that this request only takes effect
2271 * if the seat has the keyboard capability.
2272 *
2273 * This prevents a race between the compositor sending new
2274 * capabilities and the client trying to use the old ones.
2275 */
2276 struct weston_keyboard *keyboard = seat->keyboard_state;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002277 struct wl_resource *cr;
2278
Derek Foreman345c9f32015-06-03 15:53:28 -05002279 if (!keyboard)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002280 return;
2281
Jason Ekstranda85118c2013-06-27 20:17:02 -05002282 cr = wl_resource_create(client, &wl_keyboard_interface,
2283 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07002284 if (cr == NULL) {
2285 wl_client_post_no_memory(client);
2286 return;
2287 }
2288
Neil Roberts96d790e2013-09-19 17:32:00 +01002289 /* May be moved to focused list later by either
2290 * weston_keyboard_set_focus or directly if this client is already
2291 * focused */
Derek Foreman345c9f32015-06-03 15:53:28 -05002292 wl_list_insert(&keyboard->resource_list, wl_resource_get_link(cr));
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002293 wl_resource_set_implementation(cr, &keyboard_interface,
2294 seat, unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002295
Jonny Lamb66a41a02014-08-12 14:58:25 +02002296 if (wl_resource_get_version(cr) >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) {
2297 wl_keyboard_send_repeat_info(cr,
2298 seat->compositor->kb_repeat_rate,
2299 seat->compositor->kb_repeat_delay);
2300 }
Jasper St. Pierred8c6aeb2014-08-04 13:43:24 -04002301
Matt Roper01a92732013-06-24 16:52:44 +01002302 if (seat->compositor->use_xkbcommon) {
2303 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002304 keyboard->xkb_info->keymap_fd,
2305 keyboard->xkb_info->keymap_size);
Matt Roper01a92732013-06-24 16:52:44 +01002306 } else {
2307 int null_fd = open("/dev/null", O_RDONLY);
2308 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP,
2309 null_fd,
2310 0);
2311 close(null_fd);
2312 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002313
Neil Roberts96d790e2013-09-19 17:32:00 +01002314 if (should_send_modifiers_to_client(seat, client)) {
Derek Foreman345c9f32015-06-03 15:53:28 -05002315 send_modifiers_to_resource(keyboard,
Neil Roberts96d790e2013-09-19 17:32:00 +01002316 cr,
Derek Foreman345c9f32015-06-03 15:53:28 -05002317 keyboard->focus_serial);
Neil Roberts96d790e2013-09-19 17:32:00 +01002318 }
2319
Derek Foreman345c9f32015-06-03 15:53:28 -05002320 if (keyboard->focus && keyboard->focus->resource &&
2321 wl_resource_get_client(keyboard->focus->resource) == client) {
Neil Roberts96d790e2013-09-19 17:32:00 +01002322 struct weston_surface *surface =
Derek Foreman345c9f32015-06-03 15:53:28 -05002323 (struct weston_surface *)keyboard->focus;
Neil Roberts96d790e2013-09-19 17:32:00 +01002324
2325 wl_list_remove(wl_resource_get_link(cr));
Derek Foreman345c9f32015-06-03 15:53:28 -05002326 wl_list_insert(&keyboard->focus_resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01002327 wl_resource_get_link(cr));
2328 wl_keyboard_send_enter(cr,
Derek Foreman345c9f32015-06-03 15:53:28 -05002329 keyboard->focus_serial,
Neil Roberts96d790e2013-09-19 17:32:00 +01002330 surface->resource,
Derek Foreman345c9f32015-06-03 15:53:28 -05002331 &keyboard->keys);
Neil Roberts96d790e2013-09-19 17:32:00 +01002332
2333 /* If this is the first keyboard resource for this
2334 * client... */
Derek Foreman345c9f32015-06-03 15:53:28 -05002335 if (keyboard->focus_resource_list.prev ==
Neil Roberts96d790e2013-09-19 17:32:00 +01002336 wl_resource_get_link(cr))
2337 wl_data_device_set_keyboard_focus(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002338 }
2339}
2340
2341static void
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002342touch_release(struct wl_client *client, struct wl_resource *resource)
2343{
2344 wl_resource_destroy(resource);
2345}
2346
2347static const struct wl_touch_interface touch_interface = {
2348 touch_release
2349};
2350
2351static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002352seat_get_touch(struct wl_client *client, struct wl_resource *resource,
2353 uint32_t id)
2354{
Jason Ekstrand44a38632013-06-14 10:08:00 -05002355 struct weston_seat *seat = wl_resource_get_user_data(resource);
Derek Foreman1281a362015-07-31 16:55:32 -05002356 /* We use the touch_state directly, which means we'll
2357 * give a wl_touch if the seat has ever had one - even though
2358 * the spec explicitly states that this request only takes effect
2359 * if the seat has the touch capability.
2360 *
2361 * This prevents a race between the compositor sending new
2362 * capabilities and the client trying to use the old ones.
2363 */
2364 struct weston_touch *touch = seat->touch_state;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002365 struct wl_resource *cr;
2366
Derek Foreman1281a362015-07-31 16:55:32 -05002367 if (!touch)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002368 return;
2369
Jason Ekstranda85118c2013-06-27 20:17:02 -05002370 cr = wl_resource_create(client, &wl_touch_interface,
2371 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07002372 if (cr == NULL) {
2373 wl_client_post_no_memory(client);
2374 return;
2375 }
2376
Derek Foreman1281a362015-07-31 16:55:32 -05002377 if (touch->focus &&
2378 wl_resource_get_client(touch->focus->surface->resource) == client) {
Chokshi, Mituld6697142015-10-09 08:28:47 +00002379 wl_list_insert(&touch->focus_resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01002380 wl_resource_get_link(cr));
2381 } else {
Chokshi, Mituld6697142015-10-09 08:28:47 +00002382 wl_list_insert(&touch->resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01002383 wl_resource_get_link(cr));
2384 }
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01002385 wl_resource_set_implementation(cr, &touch_interface,
2386 seat, unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002387}
2388
Quentin Glidicaab1d362016-03-13 17:49:08 +01002389static void
2390seat_release(struct wl_client *client, struct wl_resource *resource)
2391{
2392 wl_resource_destroy(resource);
2393}
2394
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002395static const struct wl_seat_interface seat_interface = {
2396 seat_get_pointer,
2397 seat_get_keyboard,
2398 seat_get_touch,
Quentin Glidicaab1d362016-03-13 17:49:08 +01002399 seat_release,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002400};
2401
2402static void
2403bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
2404{
Kristian Høgsberge3148752013-05-06 23:19:49 -04002405 struct weston_seat *seat = data;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002406 struct wl_resource *resource;
2407 enum wl_seat_capability caps = 0;
2408
Jason Ekstranda85118c2013-06-27 20:17:02 -05002409 resource = wl_resource_create(client,
Derek Foreman1909c102015-11-26 14:17:47 -06002410 &wl_seat_interface, version, id);
Jason Ekstrand44a38632013-06-14 10:08:00 -05002411 wl_list_insert(&seat->base_resource_list, wl_resource_get_link(resource));
Jason Ekstranda85118c2013-06-27 20:17:02 -05002412 wl_resource_set_implementation(resource, &seat_interface, data,
2413 unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002414
Derek Foreman1281a362015-07-31 16:55:32 -05002415 if (weston_seat_get_pointer(seat))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002416 caps |= WL_SEAT_CAPABILITY_POINTER;
Derek Foreman1281a362015-07-31 16:55:32 -05002417 if (weston_seat_get_keyboard(seat))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002418 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
Derek Foreman1281a362015-07-31 16:55:32 -05002419 if (weston_seat_get_touch(seat))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002420 caps |= WL_SEAT_CAPABILITY_TOUCH;
2421
2422 wl_seat_send_capabilities(resource, caps);
Jasper St. Pierre0013a292014-08-07 16:43:11 -04002423 if (version >= WL_SEAT_NAME_SINCE_VERSION)
Rob Bradforde445ae62013-05-31 18:09:51 +01002424 wl_seat_send_name(resource, seat->seat_name);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002425}
2426
Jonas Ådahl30d61d82014-10-22 21:21:17 +02002427static void
2428relative_pointer_destroy(struct wl_client *client,
2429 struct wl_resource *resource)
2430{
2431 wl_resource_destroy(resource);
2432}
2433
2434static const struct zwp_relative_pointer_v1_interface relative_pointer_interface = {
2435 relative_pointer_destroy
2436};
2437
2438static void
2439relative_pointer_manager_destroy(struct wl_client *client,
2440 struct wl_resource *resource)
2441{
2442 wl_resource_destroy(resource);
2443}
2444
2445static void
2446relative_pointer_manager_get_relative_pointer(struct wl_client *client,
2447 struct wl_resource *resource,
2448 uint32_t id,
2449 struct wl_resource *pointer_resource)
2450{
2451 struct weston_pointer *pointer =
2452 wl_resource_get_user_data(pointer_resource);
2453 struct weston_pointer_client *pointer_client;
2454 struct wl_resource *cr;
2455
2456 cr = wl_resource_create(client, &zwp_relative_pointer_v1_interface,
2457 wl_resource_get_version(resource), id);
2458 if (cr == NULL) {
2459 wl_client_post_no_memory(client);
2460 return;
2461 }
2462
2463 pointer_client = weston_pointer_ensure_pointer_client(pointer, client);
2464 if (!pointer_client) {
2465 wl_client_post_no_memory(client);
2466 return;
2467 }
2468
2469 wl_list_insert(&pointer_client->relative_pointer_resources,
2470 wl_resource_get_link(cr));
2471 wl_resource_set_implementation(cr, &relative_pointer_interface,
2472 pointer,
2473 unbind_pointer_client_resource);
2474}
2475
2476static const struct zwp_relative_pointer_manager_v1_interface relative_pointer_manager = {
2477 relative_pointer_manager_destroy,
2478 relative_pointer_manager_get_relative_pointer,
2479};
2480
2481static void
2482bind_relative_pointer_manager(struct wl_client *client, void *data,
2483 uint32_t version, uint32_t id)
2484{
2485 struct weston_compositor *compositor = data;
2486 struct wl_resource *resource;
2487
2488 resource = wl_resource_create(client,
2489 &zwp_relative_pointer_manager_v1_interface,
2490 1, id);
2491
2492 wl_resource_set_implementation(resource, &relative_pointer_manager,
2493 compositor,
2494 NULL);
2495}
2496
Rob Bradford382ff462013-06-24 16:52:45 +01002497#ifdef ENABLE_XKBCOMMON
Giulio Camuffo0358af42016-06-02 21:48:08 +03002498WL_EXPORT int
2499weston_compositor_set_xkb_rule_names(struct weston_compositor *ec,
2500 struct xkb_rule_names *names)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002501{
Rob Bradford382ff462013-06-24 16:52:45 +01002502 ec->use_xkbcommon = 1;
Matt Roper01a92732013-06-24 16:52:44 +01002503
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002504 if (ec->xkb_context == NULL) {
2505 ec->xkb_context = xkb_context_new(0);
2506 if (ec->xkb_context == NULL) {
2507 weston_log("failed to create XKB context\n");
2508 return -1;
2509 }
2510 }
2511
2512 if (names)
2513 ec->xkb_names = *names;
2514 if (!ec->xkb_names.rules)
2515 ec->xkb_names.rules = strdup("evdev");
2516 if (!ec->xkb_names.model)
2517 ec->xkb_names.model = strdup("pc105");
2518 if (!ec->xkb_names.layout)
2519 ec->xkb_names.layout = strdup("us");
2520
2521 return 0;
2522}
2523
Stefan Schmidtfda26522013-09-17 10:54:09 +01002524static void
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002525weston_xkb_info_destroy(struct weston_xkb_info *xkb_info)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002526{
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002527 if (--xkb_info->ref_count > 0)
2528 return;
2529
Ran Benitac9c74152014-08-19 23:59:52 +03002530 xkb_keymap_unref(xkb_info->keymap);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002531
2532 if (xkb_info->keymap_area)
2533 munmap(xkb_info->keymap_area, xkb_info->keymap_size);
2534 if (xkb_info->keymap_fd >= 0)
2535 close(xkb_info->keymap_fd);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002536 free(xkb_info);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002537}
2538
2539void
2540weston_compositor_xkb_destroy(struct weston_compositor *ec)
2541{
Matt Roper01a92732013-06-24 16:52:44 +01002542 /*
2543 * If we're operating in raw keyboard mode, we never initialized
2544 * libxkbcommon so there's no cleanup to do either.
2545 */
2546 if (!ec->use_xkbcommon)
2547 return;
2548
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002549 free((char *) ec->xkb_names.rules);
2550 free((char *) ec->xkb_names.model);
2551 free((char *) ec->xkb_names.layout);
2552 free((char *) ec->xkb_names.variant);
2553 free((char *) ec->xkb_names.options);
Stefan Schmidtfda26522013-09-17 10:54:09 +01002554
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002555 if (ec->xkb_info)
2556 weston_xkb_info_destroy(ec->xkb_info);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002557 xkb_context_unref(ec->xkb_context);
2558}
2559
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002560static struct weston_xkb_info *
2561weston_xkb_info_create(struct xkb_keymap *keymap)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002562{
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002563 struct weston_xkb_info *xkb_info = zalloc(sizeof *xkb_info);
2564 if (xkb_info == NULL)
2565 return NULL;
2566
Ran Benita2e1968f2014-08-19 23:59:51 +03002567 xkb_info->keymap = xkb_keymap_ref(keymap);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002568 xkb_info->ref_count = 1;
2569
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002570 char *keymap_str;
2571
Ran Benita2e1968f2014-08-19 23:59:51 +03002572 xkb_info->shift_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2573 XKB_MOD_NAME_SHIFT);
2574 xkb_info->caps_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2575 XKB_MOD_NAME_CAPS);
2576 xkb_info->ctrl_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2577 XKB_MOD_NAME_CTRL);
2578 xkb_info->alt_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2579 XKB_MOD_NAME_ALT);
2580 xkb_info->mod2_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2581 "Mod2");
2582 xkb_info->mod3_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2583 "Mod3");
2584 xkb_info->super_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2585 XKB_MOD_NAME_LOGO);
2586 xkb_info->mod5_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2587 "Mod5");
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002588
Ran Benita2e1968f2014-08-19 23:59:51 +03002589 xkb_info->num_led = xkb_keymap_led_get_index(xkb_info->keymap,
2590 XKB_LED_NAME_NUM);
2591 xkb_info->caps_led = xkb_keymap_led_get_index(xkb_info->keymap,
2592 XKB_LED_NAME_CAPS);
2593 xkb_info->scroll_led = xkb_keymap_led_get_index(xkb_info->keymap,
2594 XKB_LED_NAME_SCROLL);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002595
Ran Benita2e1968f2014-08-19 23:59:51 +03002596 keymap_str = xkb_keymap_get_as_string(xkb_info->keymap,
2597 XKB_KEYMAP_FORMAT_TEXT_V1);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002598 if (keymap_str == NULL) {
2599 weston_log("failed to get string version of keymap\n");
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002600 goto err_keymap;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002601 }
2602 xkb_info->keymap_size = strlen(keymap_str) + 1;
2603
2604 xkb_info->keymap_fd = os_create_anonymous_file(xkb_info->keymap_size);
2605 if (xkb_info->keymap_fd < 0) {
2606 weston_log("creating a keymap file for %lu bytes failed: %m\n",
2607 (unsigned long) xkb_info->keymap_size);
2608 goto err_keymap_str;
2609 }
2610
2611 xkb_info->keymap_area = mmap(NULL, xkb_info->keymap_size,
2612 PROT_READ | PROT_WRITE,
2613 MAP_SHARED, xkb_info->keymap_fd, 0);
2614 if (xkb_info->keymap_area == MAP_FAILED) {
2615 weston_log("failed to mmap() %lu bytes\n",
2616 (unsigned long) xkb_info->keymap_size);
2617 goto err_dev_zero;
2618 }
2619 strcpy(xkb_info->keymap_area, keymap_str);
2620 free(keymap_str);
2621
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002622 return xkb_info;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002623
2624err_dev_zero:
2625 close(xkb_info->keymap_fd);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002626err_keymap_str:
2627 free(keymap_str);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002628err_keymap:
Ran Benita2e1968f2014-08-19 23:59:51 +03002629 xkb_keymap_unref(xkb_info->keymap);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002630 free(xkb_info);
2631 return NULL;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002632}
2633
2634static int
2635weston_compositor_build_global_keymap(struct weston_compositor *ec)
2636{
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002637 struct xkb_keymap *keymap;
2638
2639 if (ec->xkb_info != NULL)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002640 return 0;
2641
Ran Benita2e1968f2014-08-19 23:59:51 +03002642 keymap = xkb_keymap_new_from_names(ec->xkb_context,
2643 &ec->xkb_names,
2644 0);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002645 if (keymap == NULL) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002646 weston_log("failed to compile global XKB keymap\n");
2647 weston_log(" tried rules %s, model %s, layout %s, variant %s, "
2648 "options %s\n",
2649 ec->xkb_names.rules, ec->xkb_names.model,
2650 ec->xkb_names.layout, ec->xkb_names.variant,
2651 ec->xkb_names.options);
2652 return -1;
2653 }
2654
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002655 ec->xkb_info = weston_xkb_info_create(keymap);
Rui Matos73d93952013-10-24 19:28:41 +02002656 xkb_keymap_unref(keymap);
Stefan Schmidtfda26522013-09-17 10:54:09 +01002657 if (ec->xkb_info == NULL)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002658 return -1;
2659
2660 return 0;
2661}
Rob Bradford382ff462013-06-24 16:52:45 +01002662#else
Giulio Camuffo0358af42016-06-02 21:48:08 +03002663WL_EXPORT int
2664weston_compositor_set_xkb_rule_names(struct weston_compositor *ec,
2665 struct xkb_rule_names *names)
Rob Bradford382ff462013-06-24 16:52:45 +01002666{
2667 return 0;
2668}
2669
2670void
2671weston_compositor_xkb_destroy(struct weston_compositor *ec)
2672{
2673}
2674#endif
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002675
Rui Matos65196bc2013-10-10 19:44:19 +02002676WL_EXPORT void
2677weston_seat_update_keymap(struct weston_seat *seat, struct xkb_keymap *keymap)
2678{
Derek Foreman1281a362015-07-31 16:55:32 -05002679 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
2680
2681 if (!keyboard || !keymap)
Rui Matos65196bc2013-10-10 19:44:19 +02002682 return;
2683
2684#ifdef ENABLE_XKBCOMMON
2685 if (!seat->compositor->use_xkbcommon)
2686 return;
2687
Derek Foreman1281a362015-07-31 16:55:32 -05002688 xkb_keymap_unref(keyboard->pending_keymap);
2689 keyboard->pending_keymap = xkb_keymap_ref(keymap);
Rui Matos65196bc2013-10-10 19:44:19 +02002690
Derek Foreman1281a362015-07-31 16:55:32 -05002691 if (keyboard->keys.size == 0)
Rui Matos65196bc2013-10-10 19:44:19 +02002692 update_keymap(seat);
2693#endif
2694}
2695
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002696WL_EXPORT int
2697weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap)
2698{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002699 struct weston_keyboard *keyboard;
2700
Derek Foreman1281a362015-07-31 16:55:32 -05002701 if (seat->keyboard_state) {
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002702 seat->keyboard_device_count += 1;
2703 if (seat->keyboard_device_count == 1)
2704 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002705 return 0;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002706 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002707
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002708 keyboard = weston_keyboard_create();
2709 if (keyboard == NULL) {
2710 weston_log("failed to allocate weston keyboard struct\n");
2711 return -1;
2712 }
2713
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002714#ifdef ENABLE_XKBCOMMON
2715 if (seat->compositor->use_xkbcommon) {
2716 if (keymap != NULL) {
2717 keyboard->xkb_info = weston_xkb_info_create(keymap);
2718 if (keyboard->xkb_info == NULL)
Ander Conselvan de Oliveira4d363cf2014-01-31 17:35:45 +02002719 goto err;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002720 } else {
2721 if (weston_compositor_build_global_keymap(seat->compositor) < 0)
Ander Conselvan de Oliveira4d363cf2014-01-31 17:35:45 +02002722 goto err;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002723 keyboard->xkb_info = seat->compositor->xkb_info;
2724 keyboard->xkb_info->ref_count++;
2725 }
2726
2727 keyboard->xkb_state.state = xkb_state_new(keyboard->xkb_info->keymap);
2728 if (keyboard->xkb_state.state == NULL) {
2729 weston_log("failed to initialise XKB state\n");
Ander Conselvan de Oliveira4d363cf2014-01-31 17:35:45 +02002730 goto err;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002731 }
2732
2733 keyboard->xkb_state.leds = 0;
2734 }
2735#endif
2736
Derek Foreman1281a362015-07-31 16:55:32 -05002737 seat->keyboard_state = keyboard;
Ander Conselvan de Oliveira4d363cf2014-01-31 17:35:45 +02002738 seat->keyboard_device_count = 1;
2739 keyboard->seat = seat;
2740
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002741 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002742
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002743 return 0;
Ander Conselvan de Oliveira4d363cf2014-01-31 17:35:45 +02002744
2745err:
2746 if (keyboard->xkb_info)
2747 weston_xkb_info_destroy(keyboard->xkb_info);
2748 free(keyboard);
2749
2750 return -1;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002751}
2752
Jonas Ådahl91fed542013-12-03 09:14:27 +01002753static void
2754weston_keyboard_reset_state(struct weston_keyboard *keyboard)
2755{
2756 struct weston_seat *seat = keyboard->seat;
2757 struct xkb_state *state;
2758
2759#ifdef ENABLE_XKBCOMMON
2760 if (seat->compositor->use_xkbcommon) {
2761 state = xkb_state_new(keyboard->xkb_info->keymap);
2762 if (!state) {
2763 weston_log("failed to reset XKB state\n");
2764 return;
2765 }
2766 xkb_state_unref(keyboard->xkb_state.state);
2767 keyboard->xkb_state.state = state;
2768
2769 keyboard->xkb_state.leds = 0;
2770 }
2771#endif
2772
2773 seat->modifier_state = 0;
2774}
2775
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002776WL_EXPORT void
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002777weston_seat_release_keyboard(struct weston_seat *seat)
2778{
2779 seat->keyboard_device_count--;
Derek Foremand621df22014-11-19 11:04:12 -06002780 assert(seat->keyboard_device_count >= 0);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002781 if (seat->keyboard_device_count == 0) {
Derek Foreman1281a362015-07-31 16:55:32 -05002782 weston_keyboard_set_focus(seat->keyboard_state, NULL);
2783 weston_keyboard_cancel_grab(seat->keyboard_state);
2784 weston_keyboard_reset_state(seat->keyboard_state);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002785 seat_send_updated_caps(seat);
2786 }
2787}
2788
2789WL_EXPORT void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002790weston_seat_init_pointer(struct weston_seat *seat)
2791{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002792 struct weston_pointer *pointer;
2793
Derek Foreman1281a362015-07-31 16:55:32 -05002794 if (seat->pointer_state) {
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002795 seat->pointer_device_count += 1;
2796 if (seat->pointer_device_count == 1)
2797 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002798 return;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002799 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002800
Giulio Camuffocdb4d292013-11-14 23:42:53 +01002801 pointer = weston_pointer_create(seat);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002802 if (pointer == NULL)
2803 return;
2804
Derek Foreman1281a362015-07-31 16:55:32 -05002805 seat->pointer_state = pointer;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002806 seat->pointer_device_count = 1;
2807 pointer->seat = seat;
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002808
2809 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002810}
2811
2812WL_EXPORT void
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002813weston_seat_release_pointer(struct weston_seat *seat)
2814{
Derek Foreman1281a362015-07-31 16:55:32 -05002815 struct weston_pointer *pointer = seat->pointer_state;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002816
2817 seat->pointer_device_count--;
2818 if (seat->pointer_device_count == 0) {
Derek Foremanf9318d12015-05-11 15:40:11 -05002819 weston_pointer_clear_focus(pointer);
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02002820 weston_pointer_cancel_grab(pointer);
Jonas Ådahl630bae82013-10-17 23:04:06 +02002821
Jonas Ådahla4932742013-10-17 23:04:07 +02002822 if (pointer->sprite)
2823 pointer_unmap_sprite(pointer);
2824
Jonas Ådahl3e12e632013-12-02 22:05:05 +01002825 weston_pointer_reset_state(pointer);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002826 seat_send_updated_caps(seat);
Derek Foremanfd5ca512015-01-07 15:00:25 -06002827
2828 /* seat->pointer is intentionally not destroyed so that
2829 * a newly attached pointer on this seat will retain
2830 * the previous cursor co-ordinates.
2831 */
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002832 }
2833}
2834
2835WL_EXPORT void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002836weston_seat_init_touch(struct weston_seat *seat)
2837{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002838 struct weston_touch *touch;
2839
Derek Foreman1281a362015-07-31 16:55:32 -05002840 if (seat->touch_state) {
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002841 seat->touch_device_count += 1;
2842 if (seat->touch_device_count == 1)
2843 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002844 return;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002845 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002846
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002847 touch = weston_touch_create();
2848 if (touch == NULL)
2849 return;
2850
Derek Foreman1281a362015-07-31 16:55:32 -05002851 seat->touch_state = touch;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002852 seat->touch_device_count = 1;
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002853 touch->seat = seat;
2854
2855 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002856}
2857
2858WL_EXPORT void
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002859weston_seat_release_touch(struct weston_seat *seat)
2860{
2861 seat->touch_device_count--;
2862 if (seat->touch_device_count == 0) {
Derek Foreman1281a362015-07-31 16:55:32 -05002863 weston_touch_set_focus(seat->touch_state, NULL);
2864 weston_touch_cancel_grab(seat->touch_state);
2865 weston_touch_reset_state(seat->touch_state);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002866 seat_send_updated_caps(seat);
2867 }
2868}
2869
2870WL_EXPORT void
Rob Bradford9af5f9e2013-05-31 18:09:50 +01002871weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec,
2872 const char *seat_name)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002873{
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04002874 memset(seat, 0, sizeof *seat);
2875
Kristian Høgsberge3148752013-05-06 23:19:49 -04002876 seat->selection_data_source = NULL;
2877 wl_list_init(&seat->base_resource_list);
2878 wl_signal_init(&seat->selection_signal);
2879 wl_list_init(&seat->drag_resource_list);
Kristian Høgsberge3148752013-05-06 23:19:49 -04002880 wl_signal_init(&seat->destroy_signal);
Jason Ekstranda4ab5422014-04-02 19:53:45 -05002881 wl_signal_init(&seat->updated_caps_signal);
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04002882
Peter Hutterer87743e92016-01-18 16:38:22 +10002883 seat->global = wl_global_create(ec->wl_display, &wl_seat_interface, 5,
Kristian Høgsberg919cddb2013-07-08 19:03:57 -04002884 seat, bind_seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002885
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002886 seat->compositor = ec;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002887 seat->modifier_state = 0;
Rob Bradford9af5f9e2013-05-31 18:09:50 +01002888 seat->seat_name = strdup(seat_name);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002889
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002890 wl_list_insert(ec->seat_list.prev, &seat->link);
2891
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002892 clipboard_create(seat);
2893
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002894 wl_signal_emit(&ec->seat_created_signal, seat);
2895}
2896
2897WL_EXPORT void
2898weston_seat_release(struct weston_seat *seat)
2899{
2900 wl_list_remove(&seat->link);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002901
Jonas Ådahl1afb2382014-01-03 19:46:51 +01002902 if (seat->saved_kbd_focus)
2903 wl_list_remove(&seat->saved_kbd_focus_listener.link);
2904
Derek Foreman1281a362015-07-31 16:55:32 -05002905 if (seat->pointer_state)
2906 weston_pointer_destroy(seat->pointer_state);
2907 if (seat->keyboard_state)
2908 weston_keyboard_destroy(seat->keyboard_state);
2909 if (seat->touch_state)
2910 weston_touch_destroy(seat->touch_state);
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04002911
Rob Bradford9af5f9e2013-05-31 18:09:50 +01002912 free (seat->seat_name);
2913
Kristian Høgsberg919cddb2013-07-08 19:03:57 -04002914 wl_global_destroy(seat->global);
Kristian Høgsbergaaadc772013-07-08 16:20:31 -04002915
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002916 wl_signal_emit(&seat->destroy_signal, seat);
2917}
Derek Foreman1281a362015-07-31 16:55:32 -05002918
2919/** Get a seat's keyboard pointer
2920 *
2921 * \param seat The seat to query
2922 * \return The seat's keyboard pointer, or NULL if no keyboard is present
2923 *
2924 * The keyboard pointer for a seat isn't freed when all keyboards are removed,
2925 * so it should only be used when the seat's keyboard_device_count is greater
2926 * than zero. This function does that test and only returns a pointer
2927 * when a keyboard is present.
2928 */
2929WL_EXPORT struct weston_keyboard *
2930weston_seat_get_keyboard(struct weston_seat *seat)
2931{
2932 if (!seat)
2933 return NULL;
2934
2935 if (seat->keyboard_device_count)
2936 return seat->keyboard_state;
2937
2938 return NULL;
2939}
2940
2941/** Get a seat's pointer pointer
2942 *
2943 * \param seat The seat to query
2944 * \return The seat's pointer pointer, or NULL if no pointer device is present
2945 *
2946 * The pointer pointer for a seat isn't freed when all mice are removed,
2947 * so it should only be used when the seat's pointer_device_count is greater
2948 * than zero. This function does that test and only returns a pointer
2949 * when a pointing device is present.
2950 */
2951WL_EXPORT struct weston_pointer *
2952weston_seat_get_pointer(struct weston_seat *seat)
2953{
2954 if (!seat)
2955 return NULL;
2956
2957 if (seat->pointer_device_count)
2958 return seat->pointer_state;
2959
2960 return NULL;
2961}
2962
Jonas Ådahld3414f22016-07-22 17:56:31 +08002963static const struct zwp_locked_pointer_v1_interface locked_pointer_interface;
2964static const struct zwp_confined_pointer_v1_interface confined_pointer_interface;
2965
2966static enum pointer_constraint_type
2967pointer_constraint_get_type(struct weston_pointer_constraint *constraint)
2968{
2969 if (wl_resource_instance_of(constraint->resource,
2970 &zwp_locked_pointer_v1_interface,
2971 &locked_pointer_interface)) {
2972 return POINTER_CONSTRAINT_TYPE_LOCK;
2973 } else if (wl_resource_instance_of(constraint->resource,
2974 &zwp_confined_pointer_v1_interface,
2975 &confined_pointer_interface)) {
2976 return POINTER_CONSTRAINT_TYPE_CONFINE;
2977 }
2978
2979 abort();
2980 return 0;
2981}
2982
2983static void
2984pointer_constraint_notify_activated(struct weston_pointer_constraint *constraint)
2985{
2986 struct wl_resource *resource = constraint->resource;
2987
2988 switch (pointer_constraint_get_type(constraint)) {
2989 case POINTER_CONSTRAINT_TYPE_LOCK:
2990 zwp_locked_pointer_v1_send_locked(resource);
2991 break;
2992 case POINTER_CONSTRAINT_TYPE_CONFINE:
2993 zwp_confined_pointer_v1_send_confined(resource);
2994 break;
2995 }
2996}
2997
2998static void
2999pointer_constraint_notify_deactivated(struct weston_pointer_constraint *constraint)
3000{
3001 struct wl_resource *resource = constraint->resource;
3002
3003 switch (pointer_constraint_get_type(constraint)) {
3004 case POINTER_CONSTRAINT_TYPE_LOCK:
3005 zwp_locked_pointer_v1_send_unlocked(resource);
3006 break;
3007 case POINTER_CONSTRAINT_TYPE_CONFINE:
3008 zwp_confined_pointer_v1_send_unconfined(resource);
3009 break;
3010 }
3011}
3012
3013static struct weston_pointer_constraint *
3014get_pointer_constraint_for_pointer(struct weston_surface *surface,
3015 struct weston_pointer *pointer)
3016{
3017 struct weston_pointer_constraint *constraint;
3018
3019 wl_list_for_each(constraint, &surface->pointer_constraints, link) {
3020 if (constraint->pointer == pointer)
3021 return constraint;
3022 }
3023
3024 return NULL;
3025}
3026
Derek Foreman1281a362015-07-31 16:55:32 -05003027/** Get a seat's touch pointer
3028 *
3029 * \param seat The seat to query
3030 * \return The seat's touch pointer, or NULL if no touch device is present
3031 *
3032 * The touch pointer for a seat isn't freed when all touch devices are removed,
3033 * so it should only be used when the seat's touch_device_count is greater
3034 * than zero. This function does that test and only returns a pointer
3035 * when a touch device is present.
3036 */
3037WL_EXPORT struct weston_touch *
3038weston_seat_get_touch(struct weston_seat *seat)
3039{
3040 if (!seat)
3041 return NULL;
3042
3043 if (seat->touch_device_count)
3044 return seat->touch_state;
3045
3046 return NULL;
3047}
Bryce Harrington24f917e2016-06-29 19:04:07 -07003048
3049/** Sets the keyboard focus to the given surface
3050 *
3051 * \param seat The seat to query
3052 */
3053WL_EXPORT void
3054weston_seat_set_keyboard_focus(struct weston_seat *seat,
3055 struct weston_surface *surface)
3056{
3057 struct weston_compositor *compositor = seat->compositor;
3058 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Jonas Ådahlf7deb6a2016-07-22 17:50:26 +08003059 struct weston_surface_activation_data activation_data;
Bryce Harrington24f917e2016-06-29 19:04:07 -07003060
Jonas Ådahlef8e1c32016-03-15 20:28:51 +08003061 if (keyboard && keyboard->focus != surface) {
Bryce Harrington24f917e2016-06-29 19:04:07 -07003062 weston_keyboard_set_focus(keyboard, surface);
3063 wl_data_device_set_keyboard_focus(seat);
3064 }
3065
Jonas Ådahl94e2e2d2014-10-18 18:42:19 +02003066 inc_activate_serial(compositor);
Jonas Ådahlf7deb6a2016-07-22 17:50:26 +08003067
3068 activation_data = (struct weston_surface_activation_data) {
3069 .surface = surface,
3070 .seat = seat,
3071 };
3072 wl_signal_emit(&compositor->activate_signal, &activation_data);
Bryce Harrington24f917e2016-06-29 19:04:07 -07003073}
Jonas Ådahl30d61d82014-10-22 21:21:17 +02003074
Jonas Ådahld3414f22016-07-22 17:56:31 +08003075static void
3076enable_pointer_constraint(struct weston_pointer_constraint *constraint,
3077 struct weston_view *view)
3078{
3079 assert(constraint->view == NULL);
3080 constraint->view = view;
3081 pointer_constraint_notify_activated(constraint);
3082 weston_pointer_start_grab(constraint->pointer, &constraint->grab);
3083 wl_list_remove(&constraint->surface_destroy_listener.link);
3084 wl_list_init(&constraint->surface_destroy_listener.link);
3085}
3086
3087static bool
3088is_pointer_constraint_enabled(struct weston_pointer_constraint *constraint)
3089{
3090 return constraint->view != NULL;
3091}
3092
3093static void
3094weston_pointer_constraint_disable(struct weston_pointer_constraint *constraint)
3095{
3096 constraint->view = NULL;
3097 pointer_constraint_notify_deactivated(constraint);
3098 weston_pointer_end_grab(constraint->grab.pointer);
3099}
3100
3101void
3102weston_pointer_constraint_destroy(struct weston_pointer_constraint *constraint)
3103{
3104 if (is_pointer_constraint_enabled(constraint))
3105 weston_pointer_constraint_disable(constraint);
3106
3107 wl_list_remove(&constraint->pointer_destroy_listener.link);
3108 wl_list_remove(&constraint->surface_destroy_listener.link);
3109 wl_list_remove(&constraint->surface_commit_listener.link);
3110 wl_list_remove(&constraint->surface_activate_listener.link);
3111
3112 wl_resource_set_user_data(constraint->resource, NULL);
3113 pixman_region32_fini(&constraint->region);
3114 wl_list_remove(&constraint->link);
3115 free(constraint);
3116}
3117
3118static void
3119disable_pointer_constraint(struct weston_pointer_constraint *constraint)
3120{
3121 switch (constraint->lifetime) {
3122 case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT:
3123 weston_pointer_constraint_destroy(constraint);
3124 break;
3125 case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT:
3126 weston_pointer_constraint_disable(constraint);
3127 break;
3128 }
3129}
3130
3131static bool
3132is_within_constraint_region(struct weston_pointer_constraint *constraint,
3133 wl_fixed_t sx, wl_fixed_t sy)
3134{
3135 struct weston_surface *surface = constraint->surface;
3136 pixman_region32_t constraint_region;
3137 bool result;
3138
3139 pixman_region32_init(&constraint_region);
3140 pixman_region32_intersect(&constraint_region,
3141 &surface->input,
3142 &constraint->region);
3143 result = pixman_region32_contains_point(&constraint_region,
3144 wl_fixed_to_int(sx),
3145 wl_fixed_to_int(sy),
3146 NULL);
3147 pixman_region32_fini(&constraint_region);
3148
3149 return result;
3150}
3151
3152static void
3153maybe_enable_pointer_constraint(struct weston_pointer_constraint *constraint)
3154{
3155 struct weston_surface *surface = constraint->surface;
3156 struct weston_view *vit;
3157 struct weston_view *view = NULL;
3158 struct weston_pointer *pointer = constraint->pointer;
3159 struct weston_keyboard *keyboard;
3160 struct weston_seat *seat = pointer->seat;
3161 int32_t x, y;
3162
3163 /* Postpone if no view of the surface was most recently clicked. */
3164 wl_list_for_each(vit, &surface->views, surface_link) {
3165 if (vit->click_to_activate_serial ==
3166 surface->compositor->activate_serial) {
3167 view = vit;
3168 }
3169 }
3170 if (view == NULL)
3171 return;
3172
3173 /* Postpone if surface doesn't have keyboard focus. */
3174 keyboard = weston_seat_get_keyboard(seat);
3175 if (!keyboard || keyboard->focus != surface)
3176 return;
3177
3178 /* Postpone constraint if the pointer is not within the
3179 * constraint region.
3180 */
3181 weston_view_from_global(view,
3182 wl_fixed_to_int(pointer->x),
3183 wl_fixed_to_int(pointer->y),
3184 &x, &y);
3185 if (!is_within_constraint_region(constraint,
3186 wl_fixed_from_int(x),
3187 wl_fixed_from_int(y)))
3188 return;
3189
3190 enable_pointer_constraint(constraint, view);
3191}
3192
3193static void
3194locked_pointer_grab_pointer_focus(struct weston_pointer_grab *grab)
3195{
3196}
3197
3198static void
3199locked_pointer_grab_pointer_motion(struct weston_pointer_grab *grab,
3200 uint32_t time,
3201 struct weston_pointer_motion_event *event)
3202{
3203 weston_pointer_send_relative_motion(grab->pointer, time, event);
3204}
3205
3206static void
3207locked_pointer_grab_pointer_button(struct weston_pointer_grab *grab,
3208 uint32_t time,
3209 uint32_t button,
3210 uint32_t state_w)
3211{
3212 weston_pointer_send_button(grab->pointer, time, button, state_w);
3213}
3214
3215static void
3216locked_pointer_grab_pointer_axis(struct weston_pointer_grab *grab,
3217 uint32_t time,
3218 struct weston_pointer_axis_event *event)
3219{
3220 weston_pointer_send_axis(grab->pointer, time, event);
3221}
3222
3223static void
3224locked_pointer_grab_pointer_axis_source(struct weston_pointer_grab *grab,
3225 uint32_t source)
3226{
3227 weston_pointer_send_axis_source(grab->pointer, source);
3228}
3229
3230static void
3231locked_pointer_grab_pointer_frame(struct weston_pointer_grab *grab)
3232{
3233 weston_pointer_send_frame(grab->pointer);
3234}
3235
3236static void
3237locked_pointer_grab_pointer_cancel(struct weston_pointer_grab *grab)
3238{
3239 struct weston_pointer_constraint *constraint =
3240 container_of(grab, struct weston_pointer_constraint, grab);
3241
3242 disable_pointer_constraint(constraint);
3243}
3244
3245static const struct weston_pointer_grab_interface
3246 locked_pointer_grab_interface = {
3247 locked_pointer_grab_pointer_focus,
3248 locked_pointer_grab_pointer_motion,
3249 locked_pointer_grab_pointer_button,
3250 locked_pointer_grab_pointer_axis,
3251 locked_pointer_grab_pointer_axis_source,
3252 locked_pointer_grab_pointer_frame,
3253 locked_pointer_grab_pointer_cancel,
3254};
3255
3256static void
3257pointer_constraint_constrain_resource_destroyed(struct wl_resource *resource)
3258{
3259 struct weston_pointer_constraint *constraint =
3260 wl_resource_get_user_data(resource);
3261
3262 if (!constraint)
3263 return;
3264
3265 weston_pointer_constraint_destroy(constraint);
3266}
3267
3268static void
3269pointer_constraint_surface_activate(struct wl_listener *listener, void *data)
3270{
3271 struct weston_surface_activation_data *activation = data;
3272 struct weston_pointer *pointer;
3273 struct weston_surface *focus = activation->surface;
3274 struct weston_pointer_constraint *constraint =
3275 container_of(listener, struct weston_pointer_constraint,
3276 surface_activate_listener);
3277 bool is_constraint_surface;
3278
3279 pointer = weston_seat_get_pointer(activation->seat);
3280 if (!pointer)
3281 return;
3282
3283 is_constraint_surface =
3284 get_pointer_constraint_for_pointer(focus, pointer) == constraint;
3285
3286 if (is_constraint_surface &&
3287 !is_pointer_constraint_enabled(constraint))
3288 maybe_enable_pointer_constraint(constraint);
3289 else if (!is_constraint_surface &&
3290 is_pointer_constraint_enabled(constraint))
3291 disable_pointer_constraint(constraint);
3292}
3293
3294static void
3295pointer_constraint_pointer_destroyed(struct wl_listener *listener, void *data)
3296{
3297 struct weston_pointer_constraint *constraint =
3298 container_of(listener, struct weston_pointer_constraint,
3299 pointer_destroy_listener);
3300
3301 weston_pointer_constraint_destroy(constraint);
3302}
3303
3304static void
3305pointer_constraint_surface_destroyed(struct wl_listener *listener, void *data)
3306{
3307 struct weston_pointer_constraint *constraint =
3308 container_of(listener, struct weston_pointer_constraint,
3309 surface_destroy_listener);
3310
3311 weston_pointer_constraint_destroy(constraint);
3312}
3313
3314static void
3315pointer_constraint_surface_committed(struct wl_listener *listener, void *data)
3316{
3317 struct weston_pointer_constraint *constraint =
3318 container_of(listener, struct weston_pointer_constraint,
3319 surface_commit_listener);
3320
3321 if (constraint->region_is_pending) {
3322 constraint->region_is_pending = false;
3323 pixman_region32_copy(&constraint->region,
3324 &constraint->region_pending);
3325 pixman_region32_fini(&constraint->region_pending);
3326 pixman_region32_init(&constraint->region_pending);
3327 }
3328
3329 if (constraint->hint_is_pending) {
3330 constraint->hint_is_pending = false;
3331
3332 constraint->hint_is_pending = true;
3333 constraint->hint_x = constraint->hint_x_pending;
3334 constraint->hint_y = constraint->hint_y_pending;
3335 }
3336
3337 if (pointer_constraint_get_type(constraint) ==
3338 POINTER_CONSTRAINT_TYPE_CONFINE &&
3339 is_pointer_constraint_enabled(constraint))
3340 maybe_warp_confined_pointer(constraint);
3341}
3342
3343static struct weston_pointer_constraint *
3344weston_pointer_constraint_create(struct weston_surface *surface,
3345 struct weston_pointer *pointer,
3346 struct weston_region *region,
3347 enum zwp_pointer_constraints_v1_lifetime lifetime,
3348 struct wl_resource *cr,
3349 const struct weston_pointer_grab_interface *grab_interface)
3350{
3351 struct weston_pointer_constraint *constraint;
3352
3353 constraint = zalloc(sizeof *constraint);
3354 if (!constraint)
3355 return NULL;
3356
3357 constraint->lifetime = lifetime;
3358 pixman_region32_init(&constraint->region);
3359 pixman_region32_init(&constraint->region_pending);
3360 wl_list_insert(&surface->pointer_constraints, &constraint->link);
3361 constraint->surface = surface;
3362 constraint->pointer = pointer;
3363 constraint->resource = cr;
3364 constraint->grab.interface = grab_interface;
3365 if (region) {
3366 pixman_region32_copy(&constraint->region,
3367 &region->region);
3368 } else {
3369 pixman_region32_fini(&constraint->region);
3370 region_init_infinite(&constraint->region);
3371 }
3372
3373 constraint->surface_activate_listener.notify =
3374 pointer_constraint_surface_activate;
3375 constraint->surface_destroy_listener.notify =
3376 pointer_constraint_surface_destroyed;
3377 constraint->surface_commit_listener.notify =
3378 pointer_constraint_surface_committed;
3379 constraint->pointer_destroy_listener.notify =
3380 pointer_constraint_pointer_destroyed;
3381
3382 wl_signal_add(&surface->compositor->activate_signal,
3383 &constraint->surface_activate_listener);
3384 wl_signal_add(&pointer->destroy_signal,
3385 &constraint->pointer_destroy_listener);
3386 wl_signal_add(&surface->destroy_signal,
3387 &constraint->surface_destroy_listener);
3388 wl_signal_add(&surface->commit_signal,
3389 &constraint->surface_commit_listener);
3390
3391 return constraint;
3392}
3393
3394static void
3395init_pointer_constraint(struct wl_resource *pointer_constraints_resource,
3396 uint32_t id,
3397 struct weston_surface *surface,
3398 struct weston_pointer *pointer,
3399 struct weston_region *region,
3400 enum zwp_pointer_constraints_v1_lifetime lifetime,
3401 const struct wl_interface *interface,
3402 const void *implementation,
3403 const struct weston_pointer_grab_interface *grab_interface)
3404{
3405 struct wl_client *client =
3406 wl_resource_get_client(pointer_constraints_resource);
3407 struct wl_resource *cr;
3408 struct weston_pointer_constraint *constraint;
3409
3410 if (get_pointer_constraint_for_pointer(surface, pointer)) {
3411 wl_resource_post_error(pointer_constraints_resource,
3412 ZWP_POINTER_CONSTRAINTS_V1_ERROR_ALREADY_CONSTRAINED,
3413 "the pointer has a lock/confine request on this surface");
3414 return;
3415 }
3416
3417 cr = wl_resource_create(client, interface,
3418 wl_resource_get_version(pointer_constraints_resource),
3419 id);
3420 if (cr == NULL) {
3421 wl_client_post_no_memory(client);
3422 return;
3423 }
3424
3425 constraint = weston_pointer_constraint_create(surface, pointer,
3426 region, lifetime,
3427 cr, grab_interface);
3428 if (constraint == NULL) {
3429 wl_client_post_no_memory(client);
3430 return;
3431 }
3432
3433 wl_resource_set_implementation(cr, implementation, constraint,
3434 pointer_constraint_constrain_resource_destroyed);
3435
3436 maybe_enable_pointer_constraint(constraint);
3437}
3438
3439static void
3440pointer_constraints_destroy(struct wl_client *client,
3441 struct wl_resource *resource)
3442{
3443 wl_resource_destroy(resource);
3444}
3445
3446static void
3447locked_pointer_destroy(struct wl_client *client,
3448 struct wl_resource *resource)
3449{
3450 struct weston_pointer_constraint *constraint =
3451 wl_resource_get_user_data(resource);
3452 wl_fixed_t x, y;
3453
3454 if (constraint && constraint->view && constraint->hint_is_pending &&
3455 is_within_constraint_region(constraint,
3456 constraint->hint_x,
3457 constraint->hint_y)) {
3458 weston_view_to_global_fixed(constraint->view,
3459 constraint->hint_x,
3460 constraint->hint_y,
3461 &x, &y);
3462 weston_pointer_move_to(constraint->pointer, x, y);
3463 }
3464 wl_resource_destroy(resource);
3465}
3466
3467static void
3468locked_pointer_set_cursor_position_hint(struct wl_client *client,
3469 struct wl_resource *resource,
3470 wl_fixed_t surface_x,
3471 wl_fixed_t surface_y)
3472{
3473 struct weston_pointer_constraint *constraint =
3474 wl_resource_get_user_data(resource);
3475
3476 /* Ignore a set cursor hint that was sent after the lock was cancelled.
3477 */
3478 if (!constraint ||
3479 !constraint->resource ||
3480 constraint->resource != resource)
3481 return;
3482
3483 constraint->hint_is_pending = true;
3484 constraint->hint_x_pending = surface_x;
3485 constraint->hint_y_pending = surface_y;
3486}
3487
3488static void
3489locked_pointer_set_region(struct wl_client *client,
3490 struct wl_resource *resource,
3491 struct wl_resource *region_resource)
3492{
3493 struct weston_pointer_constraint *constraint =
3494 wl_resource_get_user_data(resource);
3495 struct weston_region *region = region_resource ?
3496 wl_resource_get_user_data(region_resource) : NULL;
3497
3498 if (!constraint)
3499 return;
3500
3501 if (region) {
3502 pixman_region32_copy(&constraint->region_pending,
3503 &region->region);
3504 } else {
3505 pixman_region32_fini(&constraint->region_pending);
3506 region_init_infinite(&constraint->region_pending);
3507 }
3508 constraint->region_is_pending = true;
3509}
3510
3511
3512static const struct zwp_locked_pointer_v1_interface locked_pointer_interface = {
3513 locked_pointer_destroy,
3514 locked_pointer_set_cursor_position_hint,
3515 locked_pointer_set_region,
3516};
3517
3518static void
3519pointer_constraints_lock_pointer(struct wl_client *client,
3520 struct wl_resource *resource,
3521 uint32_t id,
3522 struct wl_resource *surface_resource,
3523 struct wl_resource *pointer_resource,
3524 struct wl_resource *region_resource,
3525 uint32_t lifetime)
3526{
3527 struct weston_surface *surface =
3528 wl_resource_get_user_data(surface_resource);
3529 struct weston_pointer *pointer = wl_resource_get_user_data(pointer_resource);
3530 struct weston_region *region = region_resource ?
3531 wl_resource_get_user_data(region_resource) : NULL;
3532
3533 init_pointer_constraint(resource, id, surface, pointer, region, lifetime,
3534 &zwp_locked_pointer_v1_interface,
3535 &locked_pointer_interface,
3536 &locked_pointer_grab_interface);
3537}
3538
3539static void
3540confined_pointer_grab_pointer_focus(struct weston_pointer_grab *grab)
3541{
3542}
3543
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08003544static double
3545vec2d_cross_product(struct vec2d a, struct vec2d b)
3546{
3547 return a.x * b.y - a.y * b.x;
3548}
3549
3550static struct vec2d
3551vec2d_add(struct vec2d a, struct vec2d b)
3552{
3553 return (struct vec2d) {
3554 .x = a.x + b.x,
3555 .y = a.y + b.y,
3556 };
3557}
3558
3559static struct vec2d
3560vec2d_subtract(struct vec2d a, struct vec2d b)
3561{
3562 return (struct vec2d) {
3563 .x = a.x - b.x,
3564 .y = a.y - b.y,
3565 };
3566}
3567
3568static struct vec2d
3569vec2d_multiply_constant(double c, struct vec2d a)
3570{
3571 return (struct vec2d) {
3572 .x = c * a.x,
3573 .y = c * a.y,
3574 };
3575}
3576
3577static bool
3578lines_intersect(struct line *line1, struct line *line2,
3579 struct vec2d *intersection)
3580{
3581 struct vec2d p = line1->a;
3582 struct vec2d r = vec2d_subtract(line1->b, line1->a);
3583 struct vec2d q = line2->a;
3584 struct vec2d s = vec2d_subtract(line2->b, line2->a);
3585 double rxs;
3586 double sxr;
3587 double t;
3588 double u;
3589
3590 /*
3591 * The line (p, r) and (q, s) intersects where
3592 *
3593 * p + t r = q + u s
3594 *
3595 * Calculate t:
3596 *
3597 * (p + t r) × s = (q + u s) × s
3598 * p × s + t (r × s) = q × s + u (s × s)
3599 * p × s + t (r × s) = q × s
3600 * t (r × s) = q × s - p × s
3601 * t (r × s) = (q - p) × s
3602 * t = ((q - p) × s) / (r × s)
3603 *
3604 * Using the same method, for u we get:
3605 *
3606 * u = ((p - q) × r) / (s × r)
3607 */
3608
3609 rxs = vec2d_cross_product(r, s);
3610 sxr = vec2d_cross_product(s, r);
3611
3612 /* If r × s = 0 then the lines are either parallel or collinear. */
3613 if (fabs(rxs) < DBL_MIN)
3614 return false;
3615
3616 t = vec2d_cross_product(vec2d_subtract(q, p), s) / rxs;
3617 u = vec2d_cross_product(vec2d_subtract(p, q), r) / sxr;
3618
3619 /* The lines only intersect if 0 ≤ t ≤ 1 and 0 ≤ u ≤ 1. */
3620 if (t < 0.0 || t > 1.0 || u < 0.0 || u > 1.0)
3621 return false;
3622
3623 *intersection = vec2d_add(p, vec2d_multiply_constant(t, r));
3624 return true;
3625}
3626
3627static struct border *
3628add_border(struct wl_array *array,
3629 double x1, double y1,
3630 double x2, double y2,
3631 enum motion_direction blocking_dir)
3632{
3633 struct border *border = wl_array_add(array, sizeof *border);
3634
3635 *border = (struct border) {
3636 .line = (struct line) {
3637 .a = (struct vec2d) {
3638 .x = x1,
3639 .y = y1,
3640 },
3641 .b = (struct vec2d) {
3642 .x = x2,
3643 .y = y2,
3644 },
3645 },
3646 .blocking_dir = blocking_dir,
3647 };
3648
3649 return border;
3650}
3651
3652static int
3653compare_lines_x(const void *a, const void *b)
3654{
3655 const struct border *border_a = a;
3656 const struct border *border_b = b;
3657
3658
3659 if (border_a->line.a.x == border_b->line.a.x)
3660 return border_a->line.b.x < border_b->line.b.x;
3661 else
3662 return border_a->line.a.x > border_b->line.a.x;
3663}
3664
3665static void
3666add_non_overlapping_edges(pixman_box32_t *boxes,
3667 int band_above_start,
3668 int band_below_start,
3669 int band_below_end,
3670 struct wl_array *borders)
3671{
3672 int i;
3673 struct wl_array band_merge;
3674 struct border *border;
3675 struct border *prev_border;
3676 struct border *new_border;
3677
3678 wl_array_init(&band_merge);
3679
3680 /* Add bottom band of previous row, and top band of current row, and
3681 * sort them so lower left x coordinate comes first. If there are two
3682 * borders with the same left x coordinate, the wider one comes first.
3683 */
3684 for (i = band_above_start; i < band_below_start; i++) {
3685 pixman_box32_t *box = &boxes[i];
3686 add_border(&band_merge, box->x1, box->y2, box->x2, box->y2,
3687 MOTION_DIRECTION_POSITIVE_Y);
3688 }
3689 for (i = band_below_start; i < band_below_end; i++) {
3690 pixman_box32_t *box= &boxes[i];
3691 add_border(&band_merge, box->x1, box->y1, box->x2, box->y1,
3692 MOTION_DIRECTION_NEGATIVE_Y);
3693 }
3694 qsort(band_merge.data,
3695 band_merge.size / sizeof *border,
3696 sizeof *border,
3697 compare_lines_x);
3698
3699 /* Combine the two combined bands so that any overlapping border is
3700 * eliminated. */
3701 prev_border = NULL;
3702 wl_array_for_each(border, &band_merge) {
3703 assert(border->line.a.y == border->line.b.y);
3704 assert(!prev_border ||
3705 prev_border->line.a.y == border->line.a.y);
3706 assert(!prev_border ||
3707 (prev_border->line.a.x != border->line.a.x ||
3708 prev_border->line.b.x != border->line.b.x));
3709 assert(!prev_border ||
3710 prev_border->line.a.x <= border->line.a.x);
3711
3712 if (prev_border &&
3713 prev_border->line.a.x == border->line.a.x) {
3714 /*
3715 * ------------ +
3716 * ------- =
3717 * [ ]-----
3718 */
3719 prev_border->line.a.x = border->line.b.x;
3720 } else if (prev_border &&
3721 prev_border->line.b.x == border->line.b.x) {
3722 /*
3723 * ------------ +
3724 * ------ =
3725 * ------[ ]
3726 */
3727 prev_border->line.b.x = border->line.a.x;
3728 } else if (prev_border &&
3729 prev_border->line.b.x == border->line.a.x) {
3730 /*
3731 * -------- +
3732 * ------ =
3733 * --------------
3734 */
3735 prev_border->line.b.x = border->line.b.x;
3736 } else if (prev_border &&
3737 prev_border->line.b.x >= border->line.a.x) {
3738 /*
3739 * --------------- +
3740 * ------ =
3741 * -----[ ]----
3742 */
3743 new_border = add_border(borders,
3744 border->line.b.x,
3745 border->line.b.y,
3746 prev_border->line.b.x,
3747 prev_border->line.b.y,
3748 prev_border->blocking_dir);
3749 prev_border->line.b.x = border->line.a.x;
3750 prev_border = new_border;
3751 } else {
3752 assert(!prev_border ||
3753 prev_border->line.b.x < border->line.a.x);
3754 /*
3755 * First border or non-overlapping.
3756 *
3757 * ----- +
3758 * ----- =
3759 * ----- -----
3760 */
3761 new_border = wl_array_add(borders, sizeof *border);
3762 *new_border = *border;
3763 prev_border = new_border;
3764 }
3765 }
3766
3767 wl_array_release(&band_merge);
3768}
3769
3770static void
3771add_band_bottom_edges(pixman_box32_t *boxes,
3772 int band_start,
3773 int band_end,
3774 struct wl_array *borders)
3775{
3776 int i;
3777
3778 for (i = band_start; i < band_end; i++) {
3779 add_border(borders,
3780 boxes[i].x1, boxes[i].y2,
3781 boxes[i].x2, boxes[i].y2,
3782 MOTION_DIRECTION_POSITIVE_Y);
3783 }
3784}
3785
3786static void
3787region_to_outline(pixman_region32_t *region, struct wl_array *borders)
3788{
3789 pixman_box32_t *boxes;
3790 int num_boxes;
3791 int i;
3792 int top_most, bottom_most;
3793 int current_roof;
3794 int prev_top;
3795 int band_start, prev_band_start;
3796
3797 /*
3798 * Remove any overlapping lines from the set of rectangles. Note that
3799 * pixman regions are grouped as rows of rectangles, where rectangles
3800 * in one row never touch or overlap and are all of the same height.
3801 *
3802 * -------- --- -------- ---
3803 * | | | | | | | |
3804 * ----------====---- --- ----------- ----- ---
3805 * | | => | |
3806 * ----==========--------- ----- ----------
3807 * | | | |
3808 * ------------------- -------------------
3809 *
3810 */
3811
3812 boxes = pixman_region32_rectangles(region, &num_boxes);
3813 prev_top = 0;
3814 top_most = boxes[0].y1;
3815 current_roof = top_most;
3816 bottom_most = boxes[num_boxes - 1].y2;
3817 band_start = 0;
3818 prev_band_start = 0;
3819 for (i = 0; i < num_boxes; i++) {
3820 /* Detect if there is a vertical empty space, and add the lower
3821 * level of the previous band if so was the case. */
3822 if (i > 0 &&
3823 boxes[i].y1 != prev_top &&
3824 boxes[i].y1 != boxes[i - 1].y2) {
3825 current_roof = boxes[i].y1;
3826 add_band_bottom_edges(boxes,
3827 band_start,
3828 i,
3829 borders);
3830 }
3831
3832 /* Special case adding the last band, since it won't be handled
3833 * by the band change detection below. */
3834 if (boxes[i].y1 != current_roof && i == num_boxes - 1) {
3835 if (boxes[i].y1 != prev_top) {
3836 /* The last band is a single box, so we don't
3837 * have a prev_band_start to tell us when the
3838 * previous band started. */
3839 add_non_overlapping_edges(boxes,
3840 band_start,
3841 i,
3842 i + 1,
3843 borders);
3844 } else {
3845 add_non_overlapping_edges(boxes,
3846 prev_band_start,
3847 band_start,
3848 i + 1,
3849 borders);
3850 }
3851 }
3852
3853 /* Detect when passing a band and combine the top border of the
3854 * just passed band with the bottom band of the previous band.
3855 */
3856 if (boxes[i].y1 != top_most && boxes[i].y1 != prev_top) {
3857 /* Combine the two passed bands. */
3858 if (prev_top != current_roof) {
3859 add_non_overlapping_edges(boxes,
3860 prev_band_start,
3861 band_start,
3862 i,
3863 borders);
3864 }
3865
3866 prev_band_start = band_start;
3867 band_start = i;
3868 }
3869
3870 /* Add the top border if the box is part of the current roof. */
3871 if (boxes[i].y1 == current_roof) {
3872 add_border(borders,
3873 boxes[i].x1, boxes[i].y1,
3874 boxes[i].x2, boxes[i].y1,
3875 MOTION_DIRECTION_NEGATIVE_Y);
3876 }
3877
3878 /* Add the bottom border of the last band. */
3879 if (boxes[i].y2 == bottom_most) {
3880 add_border(borders,
3881 boxes[i].x1, boxes[i].y2,
3882 boxes[i].x2, boxes[i].y2,
3883 MOTION_DIRECTION_POSITIVE_Y);
3884 }
3885
3886 /* Always add the left border. */
3887 add_border(borders,
3888 boxes[i].x1, boxes[i].y1,
3889 boxes[i].x1, boxes[i].y2,
3890 MOTION_DIRECTION_NEGATIVE_X);
3891
3892 /* Always add the right border. */
3893 add_border(borders,
3894 boxes[i].x2, boxes[i].y1,
3895 boxes[i].x2, boxes[i].y2,
3896 MOTION_DIRECTION_POSITIVE_X);
3897
3898 prev_top = boxes[i].y1;
3899 }
3900}
3901
3902static bool
3903is_border_horizontal (struct border *border)
3904{
3905 return border->line.a.y == border->line.b.y;
3906}
3907
3908static bool
3909is_border_blocking_directions(struct border *border,
3910 uint32_t directions)
3911{
3912 /* Don't block parallel motions. */
3913 if (is_border_horizontal(border)) {
3914 if ((directions & (MOTION_DIRECTION_POSITIVE_Y |
3915 MOTION_DIRECTION_NEGATIVE_Y)) == 0)
3916 return false;
3917 } else {
3918 if ((directions & (MOTION_DIRECTION_POSITIVE_X |
3919 MOTION_DIRECTION_NEGATIVE_X)) == 0)
3920 return false;
3921 }
3922
3923 return (~border->blocking_dir & directions) != directions;
3924}
3925
3926static struct border *
3927get_closest_border(struct wl_array *borders,
3928 struct line *motion,
3929 uint32_t directions)
3930{
3931 struct border *border;
3932 struct vec2d intersection;
3933 struct vec2d delta;
3934 double distance_2;
3935 struct border *closest_border = NULL;
3936 double closest_distance_2 = DBL_MAX;
3937
3938 wl_array_for_each(border, borders) {
3939 if (!is_border_blocking_directions(border, directions))
3940 continue;
3941
3942 if (!lines_intersect(&border->line, motion, &intersection))
3943 continue;
3944
3945 delta = vec2d_subtract(intersection, motion->a);
3946 distance_2 = delta.x*delta.x + delta.y*delta.y;
3947 if (distance_2 < closest_distance_2) {
3948 closest_border = border;
3949 closest_distance_2 = distance_2;
3950 }
3951 }
3952
3953 return closest_border;
3954}
3955
3956static void
3957clamp_to_border(struct border *border,
3958 struct line *motion,
3959 uint32_t *motion_dir)
3960{
3961 /*
3962 * When clamping either rightward or downward motions, the motion needs
3963 * to be clamped so that the destination coordinate does not end up on
3964 * the border (see weston_pointer_clamp_event_to_region). Do this by
3965 * clamping such motions to the border minus the smallest possible
3966 * wl_fixed_t value.
3967 */
3968 if (is_border_horizontal(border)) {
3969 if (*motion_dir & MOTION_DIRECTION_POSITIVE_Y)
3970 motion->b.y = border->line.a.y - wl_fixed_to_double(1);
3971 else
3972 motion->b.y = border->line.a.y;
3973 *motion_dir &= ~(MOTION_DIRECTION_POSITIVE_Y |
3974 MOTION_DIRECTION_NEGATIVE_Y);
3975 } else {
3976 if (*motion_dir & MOTION_DIRECTION_POSITIVE_X)
3977 motion->b.x = border->line.a.x - wl_fixed_to_double(1);
3978 else
3979 motion->b.x = border->line.a.x;
3980 *motion_dir &= ~(MOTION_DIRECTION_POSITIVE_X |
3981 MOTION_DIRECTION_NEGATIVE_X);
3982 }
3983}
3984
3985static uint32_t
3986get_motion_directions(struct line *motion)
3987{
3988 uint32_t directions = 0;
3989
3990 if (motion->a.x < motion->b.x)
3991 directions |= MOTION_DIRECTION_POSITIVE_X;
3992 else if (motion->a.x > motion->b.x)
3993 directions |= MOTION_DIRECTION_NEGATIVE_X;
3994 if (motion->a.y < motion->b.y)
3995 directions |= MOTION_DIRECTION_POSITIVE_Y;
3996 else if (motion->a.y > motion->b.y)
3997 directions |= MOTION_DIRECTION_NEGATIVE_Y;
3998
3999 return directions;
4000}
4001
Jonas Ådahld3414f22016-07-22 17:56:31 +08004002static void
4003weston_pointer_clamp_event_to_region(struct weston_pointer *pointer,
4004 struct weston_pointer_motion_event *event,
4005 pixman_region32_t *region,
4006 wl_fixed_t *clamped_x,
4007 wl_fixed_t *clamped_y)
4008{
4009 wl_fixed_t x, y;
4010 wl_fixed_t sx, sy;
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004011 wl_fixed_t old_sx = pointer->sx;
4012 wl_fixed_t old_sy = pointer->sy;
4013 struct wl_array borders;
4014 struct line motion;
4015 struct border *closest_border;
4016 float new_x_f, new_y_f;
4017 uint32_t directions;
Jonas Ådahld3414f22016-07-22 17:56:31 +08004018
4019 weston_pointer_motion_to_abs(pointer, event, &x, &y);
4020 weston_view_from_global_fixed(pointer->focus, x, y, &sx, &sy);
4021
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004022 wl_array_init(&borders);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004023
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004024 /*
4025 * Generate borders given the confine region we are to use. The borders
4026 * are defined to be the outer region of the allowed area. This means
4027 * top/left borders are "within" the allowed area, while bottom/right
4028 * borders are outside. This needs to be considered when clamping
4029 * confined motion vectors.
4030 */
4031 region_to_outline(region, &borders);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004032
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004033 motion = (struct line) {
4034 .a = (struct vec2d) {
4035 .x = wl_fixed_to_double(old_sx),
4036 .y = wl_fixed_to_double(old_sy),
4037 },
4038 .b = (struct vec2d) {
4039 .x = wl_fixed_to_double(sx),
4040 .y = wl_fixed_to_double(sy),
4041 },
4042 };
4043 directions = get_motion_directions(&motion);
4044
4045 while (directions) {
4046 closest_border = get_closest_border(&borders,
4047 &motion,
4048 directions);
4049 if (closest_border)
4050 clamp_to_border(closest_border, &motion, &directions);
4051 else
4052 break;
4053 }
4054
4055 weston_view_to_global_float(pointer->focus,
4056 (float) motion.b.x, (float) motion.b.y,
4057 &new_x_f, &new_y_f);
4058 *clamped_x = wl_fixed_from_double(new_x_f);
4059 *clamped_y = wl_fixed_from_double(new_y_f);
4060
4061 wl_array_release(&borders);
4062}
4063
4064static double
4065point_to_border_distance_2(struct border *border, double x, double y)
4066{
4067 double orig_x, orig_y;
4068 double dx, dy;
4069
4070 if (is_border_horizontal(border)) {
4071 if (x < border->line.a.x)
4072 orig_x = border->line.a.x;
4073 else if (x > border->line.b.x)
4074 orig_x = border->line.b.x;
4075 else
4076 orig_x = x;
4077 orig_y = border->line.a.y;
4078 } else {
4079 if (y < border->line.a.y)
4080 orig_y = border->line.a.y;
4081 else if (y > border->line.b.y)
4082 orig_y = border->line.b.y;
4083 else
4084 orig_y = y;
4085 orig_x = border->line.a.x;
4086 }
4087
4088
4089 dx = fabs(orig_x - x);
4090 dy = fabs(orig_y - y);
4091 return dx*dx + dy*dy;
4092}
4093
4094static void
4095warp_to_behind_border(struct border *border, wl_fixed_t *sx, wl_fixed_t *sy)
4096{
4097 switch (border->blocking_dir) {
4098 case MOTION_DIRECTION_POSITIVE_X:
4099 case MOTION_DIRECTION_NEGATIVE_X:
4100 if (border->blocking_dir == MOTION_DIRECTION_POSITIVE_X)
4101 *sx = wl_fixed_from_double(border->line.a.x) - 1;
4102 else
4103 *sx = wl_fixed_from_double(border->line.a.x) + 1;
4104 if (*sy < wl_fixed_from_double(border->line.a.y))
4105 *sy = wl_fixed_from_double(border->line.a.y) + 1;
4106 else if (*sy > wl_fixed_from_double(border->line.b.y))
4107 *sy = wl_fixed_from_double(border->line.b.y) - 1;
4108 break;
4109 case MOTION_DIRECTION_POSITIVE_Y:
4110 case MOTION_DIRECTION_NEGATIVE_Y:
4111 if (border->blocking_dir == MOTION_DIRECTION_POSITIVE_Y)
4112 *sy = wl_fixed_from_double(border->line.a.y) - 1;
4113 else
4114 *sy = wl_fixed_from_double(border->line.a.y) + 1;
4115 if (*sx < wl_fixed_from_double(border->line.a.x))
4116 *sx = wl_fixed_from_double(border->line.a.x) + 1;
4117 else if (*sx > wl_fixed_from_double(border->line.b.x))
4118 *sx = wl_fixed_from_double(border->line.b.x) - 1;
4119 break;
4120 }
Jonas Ådahld3414f22016-07-22 17:56:31 +08004121}
4122
4123static void
4124maybe_warp_confined_pointer(struct weston_pointer_constraint *constraint)
4125{
4126 wl_fixed_t x;
4127 wl_fixed_t y;
4128 wl_fixed_t sx;
4129 wl_fixed_t sy;
4130
4131 weston_view_from_global_fixed(constraint->view,
4132 constraint->pointer->x,
4133 constraint->pointer->y,
4134 &sx,
4135 &sy);
4136
4137 if (!is_within_constraint_region(constraint, sx, sy)) {
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004138 double xf = wl_fixed_to_double(sx);
4139 double yf = wl_fixed_to_double(sy);
4140 pixman_region32_t confine_region;
4141 struct wl_array borders;
4142 struct border *border;
4143 double closest_distance_2 = DBL_MAX;
4144 struct border *closest_border = NULL;
Jonas Ådahld3414f22016-07-22 17:56:31 +08004145
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004146 wl_array_init(&borders);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004147
Jonas Ådahld0be2bb2015-04-30 17:56:37 +08004148 pixman_region32_init(&confine_region);
4149 pixman_region32_intersect(&confine_region,
4150 &constraint->view->surface->input,
4151 &constraint->region);
4152 region_to_outline(&confine_region, &borders);
4153 pixman_region32_fini(&confine_region);
4154
4155 wl_array_for_each(border, &borders) {
4156 double distance_2;
4157
4158 distance_2 = point_to_border_distance_2(border, xf, yf);
4159 if (distance_2 < closest_distance_2) {
4160 closest_border = border;
4161 closest_distance_2 = distance_2;
4162 }
4163 }
4164 assert(closest_border);
4165
4166 warp_to_behind_border(closest_border, &sx, &sy);
4167
4168 wl_array_release(&borders);
Jonas Ådahld3414f22016-07-22 17:56:31 +08004169
4170 weston_view_to_global_fixed(constraint->view, sx, sy, &x, &y);
4171 weston_pointer_move_to(constraint->pointer, x, y);
4172 }
4173}
4174
4175static void
4176confined_pointer_grab_pointer_motion(struct weston_pointer_grab *grab,
4177 uint32_t time,
4178 struct weston_pointer_motion_event *event)
4179{
4180 struct weston_pointer_constraint *constraint =
4181 container_of(grab, struct weston_pointer_constraint, grab);
4182 struct weston_pointer *pointer = grab->pointer;
4183 struct weston_surface *surface;
4184 wl_fixed_t x, y;
4185 wl_fixed_t old_sx = pointer->sx;
4186 wl_fixed_t old_sy = pointer->sy;
4187 pixman_region32_t confine_region;
4188
4189 assert(pointer->focus);
4190 assert(pointer->focus->surface == constraint->surface);
4191
4192 surface = pointer->focus->surface;
4193
4194 pixman_region32_init(&confine_region);
4195 pixman_region32_intersect(&confine_region,
4196 &surface->input,
4197 &constraint->region);
4198 weston_pointer_clamp_event_to_region(pointer, event,
4199 &confine_region, &x, &y);
4200 weston_pointer_move_to(pointer, x, y);
4201 pixman_region32_fini(&confine_region);
4202
4203 weston_view_from_global_fixed(pointer->focus, x, y,
4204 &pointer->sx, &pointer->sy);
4205
4206 if (old_sx != pointer->sx || old_sy != pointer->sy) {
4207 weston_pointer_send_motion(pointer, time,
4208 pointer->sx, pointer->sy);
4209 }
4210
4211 weston_pointer_send_relative_motion(pointer, time, event);
4212}
4213
4214static void
4215confined_pointer_grab_pointer_button(struct weston_pointer_grab *grab,
4216 uint32_t time,
4217 uint32_t button,
4218 uint32_t state_w)
4219{
4220 weston_pointer_send_button(grab->pointer, time, button, state_w);
4221}
4222
4223static void
4224confined_pointer_grab_pointer_axis(struct weston_pointer_grab *grab,
4225 uint32_t time,
4226 struct weston_pointer_axis_event *event)
4227{
4228 weston_pointer_send_axis(grab->pointer, time, event);
4229}
4230
4231static void
4232confined_pointer_grab_pointer_axis_source(struct weston_pointer_grab *grab,
4233 uint32_t source)
4234{
4235 weston_pointer_send_axis_source(grab->pointer, source);
4236}
4237
4238static void
4239confined_pointer_grab_pointer_frame(struct weston_pointer_grab *grab)
4240{
4241 weston_pointer_send_frame(grab->pointer);
4242}
4243
4244static void
4245confined_pointer_grab_pointer_cancel(struct weston_pointer_grab *grab)
4246{
4247 struct weston_pointer_constraint *constraint =
4248 container_of(grab, struct weston_pointer_constraint, grab);
4249
4250 disable_pointer_constraint(constraint);
4251
4252 /* If this is a persistent constraint, re-add the surface destroy signal
4253 * listener only if we are currently not destroying the surface. */
4254 switch (constraint->lifetime) {
4255 case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT:
4256 if (constraint->surface->resource)
4257 wl_signal_add(&constraint->surface->destroy_signal,
4258 &constraint->surface_destroy_listener);
4259 break;
4260 case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT:
4261 break;
4262 }
4263}
4264
4265static const struct weston_pointer_grab_interface
4266 confined_pointer_grab_interface = {
4267 confined_pointer_grab_pointer_focus,
4268 confined_pointer_grab_pointer_motion,
4269 confined_pointer_grab_pointer_button,
4270 confined_pointer_grab_pointer_axis,
4271 confined_pointer_grab_pointer_axis_source,
4272 confined_pointer_grab_pointer_frame,
4273 confined_pointer_grab_pointer_cancel,
4274};
4275
4276static void
4277confined_pointer_destroy(struct wl_client *client,
4278 struct wl_resource *resource)
4279{
4280 wl_resource_destroy(resource);
4281}
4282
4283static void
4284confined_pointer_set_region(struct wl_client *client,
4285 struct wl_resource *resource,
4286 struct wl_resource *region_resource)
4287{
4288 struct weston_pointer_constraint *constraint =
4289 wl_resource_get_user_data(resource);
4290 struct weston_region *region = region_resource ?
4291 wl_resource_get_user_data(region_resource) : NULL;
4292
4293 if (!constraint)
4294 return;
4295
4296 if (region) {
4297 pixman_region32_copy(&constraint->region_pending,
4298 &region->region);
4299 } else {
4300 pixman_region32_fini(&constraint->region_pending);
4301 region_init_infinite(&constraint->region_pending);
4302 }
4303 constraint->region_is_pending = true;
4304}
4305
4306static const struct zwp_confined_pointer_v1_interface confined_pointer_interface = {
4307 confined_pointer_destroy,
4308 confined_pointer_set_region,
4309};
4310
4311static void
4312pointer_constraints_confine_pointer(struct wl_client *client,
4313 struct wl_resource *resource,
4314 uint32_t id,
4315 struct wl_resource *surface_resource,
4316 struct wl_resource *pointer_resource,
4317 struct wl_resource *region_resource,
4318 uint32_t lifetime)
4319{
4320 struct weston_surface *surface =
4321 wl_resource_get_user_data(surface_resource);
4322 struct weston_pointer *pointer = wl_resource_get_user_data(pointer_resource);
4323 struct weston_region *region = region_resource ?
4324 wl_resource_get_user_data(region_resource) : NULL;
4325
4326 init_pointer_constraint(resource, id, surface, pointer, region, lifetime,
4327 &zwp_confined_pointer_v1_interface,
4328 &confined_pointer_interface,
4329 &confined_pointer_grab_interface);
4330}
4331
4332static const struct zwp_pointer_constraints_v1_interface pointer_constraints_interface = {
4333 pointer_constraints_destroy,
4334 pointer_constraints_lock_pointer,
4335 pointer_constraints_confine_pointer,
4336};
4337
4338static void
4339bind_pointer_constraints(struct wl_client *client, void *data,
4340 uint32_t version, uint32_t id)
4341{
4342 struct wl_resource *resource;
4343
4344 resource = wl_resource_create(client,
4345 &zwp_pointer_constraints_v1_interface,
4346 1, id);
4347
4348 wl_resource_set_implementation(resource, &pointer_constraints_interface,
4349 NULL, NULL);
4350}
4351
Jonas Ådahl30d61d82014-10-22 21:21:17 +02004352int
4353weston_input_init(struct weston_compositor *compositor)
4354{
4355 if (!wl_global_create(compositor->wl_display,
4356 &zwp_relative_pointer_manager_v1_interface, 1,
4357 compositor, bind_relative_pointer_manager))
4358 return -1;
4359
Jonas Ådahld3414f22016-07-22 17:56:31 +08004360 if (!wl_global_create(compositor->wl_display,
4361 &zwp_pointer_constraints_v1_interface, 1,
4362 NULL, bind_pointer_constraints))
4363 return -1;
4364
Jonas Ådahl30d61d82014-10-22 21:21:17 +02004365 return 0;
4366}