blob: 8f24ccd5f21ad99042ccadf4f4f063f5669f0db8 [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
Kristian Høgsberg2158a882013-04-18 15:07:39 -040028#include <stdlib.h>
29#include <stdint.h>
30#include <string.h>
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040031#include <sys/mman.h>
32#include <assert.h>
33#include <unistd.h>
Matt Roper01a92732013-06-24 16:52:44 +010034#include <fcntl.h>
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +020035#include <limits.h>
Kristian Høgsberg2158a882013-04-18 15:07:39 -040036
Jon Cruz35b2eaa2015-06-15 15:37:08 -070037#include "shared/helpers.h"
Jon Cruz4678bab2015-06-15 15:37:07 -070038#include "shared/os-compatibility.h"
Kristian Høgsberg2158a882013-04-18 15:07:39 -040039#include "compositor.h"
40
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040041static void
42empty_region(pixman_region32_t *region)
43{
44 pixman_region32_fini(region);
45 pixman_region32_init(region);
46}
47
48static void unbind_resource(struct wl_resource *resource)
49{
Jason Ekstrand44a38632013-06-14 10:08:00 -050050 wl_list_remove(wl_resource_get_link(resource));
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040051}
52
Jonas Ådahl3042ffe2013-10-17 23:04:08 +020053WL_EXPORT void
Kristian Høgsberga71e8b22013-05-06 21:51:21 -040054weston_seat_repick(struct weston_seat *seat)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040055{
Derek Foreman1281a362015-07-31 16:55:32 -050056 const struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040057
Derek Foreman1b786ee2015-06-03 15:53:23 -050058 if (!pointer)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040059 return;
60
Derek Foreman1b786ee2015-06-03 15:53:23 -050061 pointer->grab->interface->focus(pointer->grab);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040062}
63
64static void
65weston_compositor_idle_inhibit(struct weston_compositor *compositor)
66{
67 weston_compositor_wake(compositor);
68 compositor->idle_inhibit++;
69}
70
71static void
72weston_compositor_idle_release(struct weston_compositor *compositor)
73{
74 compositor->idle_inhibit--;
75 weston_compositor_wake(compositor);
76}
77
Kristian Høgsberg2158a882013-04-18 15:07:39 -040078static void
Giulio Camuffo576fe2a2013-11-20 18:00:24 +010079pointer_focus_view_destroyed(struct wl_listener *listener, void *data)
80{
81 struct weston_pointer *pointer =
82 container_of(listener, struct weston_pointer,
83 focus_view_listener);
84
85 weston_pointer_set_focus(pointer, NULL, 0, 0);
86}
87
88static void
89pointer_focus_resource_destroyed(struct wl_listener *listener, void *data)
90{
91 struct weston_pointer *pointer =
92 container_of(listener, struct weston_pointer,
93 focus_resource_listener);
94
95 weston_pointer_set_focus(pointer, NULL, 0, 0);
96}
97
98static void
99keyboard_focus_resource_destroyed(struct wl_listener *listener, void *data)
100{
101 struct weston_keyboard *keyboard =
102 container_of(listener, struct weston_keyboard,
103 focus_resource_listener);
104
105 weston_keyboard_set_focus(keyboard, NULL);
106}
107
108static void
109touch_focus_view_destroyed(struct wl_listener *listener, void *data)
110{
111 struct weston_touch *touch =
112 container_of(listener, struct weston_touch,
113 focus_view_listener);
114
Derek Foreman4c93c082015-04-30 16:45:41 -0500115 weston_touch_set_focus(touch, NULL);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100116}
117
118static void
119touch_focus_resource_destroyed(struct wl_listener *listener, void *data)
120{
121 struct weston_touch *touch =
122 container_of(listener, struct weston_touch,
123 focus_resource_listener);
124
Derek Foreman4c93c082015-04-30 16:45:41 -0500125 weston_touch_set_focus(touch, NULL);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100126}
127
128static void
Neil Roberts96d790e2013-09-19 17:32:00 +0100129move_resources(struct wl_list *destination, struct wl_list *source)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400130{
Neil Roberts96d790e2013-09-19 17:32:00 +0100131 wl_list_insert_list(destination, source);
132 wl_list_init(source);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400133}
134
135static void
Neil Roberts96d790e2013-09-19 17:32:00 +0100136move_resources_for_client(struct wl_list *destination,
137 struct wl_list *source,
138 struct wl_client *client)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400139{
Neil Roberts96d790e2013-09-19 17:32:00 +0100140 struct wl_resource *resource, *tmp;
141 wl_resource_for_each_safe(resource, tmp, source) {
142 if (wl_resource_get_client(resource) == client) {
143 wl_list_remove(wl_resource_get_link(resource));
144 wl_list_insert(destination,
145 wl_resource_get_link(resource));
146 }
147 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400148}
149
150static void
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700151default_grab_pointer_focus(struct weston_pointer_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400152{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400153 struct weston_pointer *pointer = grab->pointer;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500154 struct weston_view *view;
Kristian Høgsberg6848c252013-05-08 22:02:59 -0400155 wl_fixed_t sx, sy;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400156
157 if (pointer->button_count > 0)
158 return;
159
Jason Ekstranda7af7042013-10-12 22:38:11 -0500160 view = weston_compositor_pick_view(pointer->seat->compositor,
161 pointer->x, pointer->y,
162 &sx, &sy);
Kristian Høgsberg6848c252013-05-08 22:02:59 -0400163
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -0800164 if (pointer->focus != view || pointer->sx != sx || pointer->sy != sy)
Jason Ekstranda7af7042013-10-12 22:38:11 -0500165 weston_pointer_set_focus(pointer, view, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400166}
167
168static void
Giulio Camuffo1959ab82013-11-14 23:42:52 +0100169default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time,
170 wl_fixed_t x, wl_fixed_t y)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400171{
Kristian Høgsbergbe6403e2013-05-08 21:03:21 -0400172 struct weston_pointer *pointer = grab->pointer;
Neil Roberts96d790e2013-09-19 17:32:00 +0100173 struct wl_list *resource_list;
174 struct wl_resource *resource;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400175
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -0800176 if (pointer->focus)
177 weston_view_from_global_fixed(pointer->focus, x, y,
178 &pointer->sx, &pointer->sy);
179
Giulio Camuffo1959ab82013-11-14 23:42:52 +0100180 weston_pointer_move(pointer, x, y);
181
Neil Roberts96d790e2013-09-19 17:32:00 +0100182 resource_list = &pointer->focus_resource_list;
183 wl_resource_for_each(resource, resource_list) {
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -0800184 wl_pointer_send_motion(resource, time,
185 pointer->sx, pointer->sy);
Kristian Høgsbergbe6403e2013-05-08 21:03:21 -0400186 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400187}
188
189static void
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700190default_grab_pointer_button(struct weston_pointer_grab *grab,
191 uint32_t time, uint32_t button, uint32_t state_w)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400192{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400193 struct weston_pointer *pointer = grab->pointer;
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400194 struct weston_compositor *compositor = pointer->seat->compositor;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500195 struct weston_view *view;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400196 struct wl_resource *resource;
197 uint32_t serial;
198 enum wl_pointer_button_state state = state_w;
Rob Bradford880ebc72013-07-22 17:31:38 +0100199 struct wl_display *display = compositor->wl_display;
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400200 wl_fixed_t sx, sy;
Neil Roberts96d790e2013-09-19 17:32:00 +0100201 struct wl_list *resource_list;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400202
Neil Roberts96d790e2013-09-19 17:32:00 +0100203 resource_list = &pointer->focus_resource_list;
204 if (!wl_list_empty(resource_list)) {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400205 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +0100206 wl_resource_for_each(resource, resource_list)
207 wl_pointer_send_button(resource,
208 serial,
209 time,
210 button,
211 state_w);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400212 }
213
214 if (pointer->button_count == 0 &&
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400215 state == WL_POINTER_BUTTON_STATE_RELEASED) {
Jason Ekstranda7af7042013-10-12 22:38:11 -0500216 view = weston_compositor_pick_view(compositor,
217 pointer->x, pointer->y,
218 &sx, &sy);
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400219
Jason Ekstranda7af7042013-10-12 22:38:11 -0500220 weston_pointer_set_focus(pointer, view, sx, sy);
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400221 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400222}
223
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200224static void
225default_grab_pointer_cancel(struct weston_pointer_grab *grab)
226{
227}
228
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400229static const struct weston_pointer_grab_interface
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400230 default_pointer_grab_interface = {
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700231 default_grab_pointer_focus,
232 default_grab_pointer_motion,
233 default_grab_pointer_button,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200234 default_grab_pointer_cancel,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400235};
236
Kristian Høgsberge329f362013-05-06 22:19:57 -0400237static void
238default_grab_touch_down(struct weston_touch_grab *grab, uint32_t time,
239 int touch_id, wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400240{
Kristian Høgsberge329f362013-05-06 22:19:57 -0400241 struct weston_touch *touch = grab->touch;
Rob Bradford880ebc72013-07-22 17:31:38 +0100242 struct wl_display *display = touch->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400243 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +0100244 struct wl_resource *resource;
245 struct wl_list *resource_list;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400246
Neil Roberts96d790e2013-09-19 17:32:00 +0100247 resource_list = &touch->focus_resource_list;
248
249 if (!wl_list_empty(resource_list) && touch->focus) {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400250 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +0100251 wl_resource_for_each(resource, resource_list)
252 wl_touch_send_down(resource, serial, time,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500253 touch->focus->surface->resource,
Neil Roberts96d790e2013-09-19 17:32:00 +0100254 touch_id, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400255 }
256}
257
Kristian Høgsberge329f362013-05-06 22:19:57 -0400258static void
259default_grab_touch_up(struct weston_touch_grab *grab,
260 uint32_t time, int touch_id)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400261{
Kristian Høgsberge329f362013-05-06 22:19:57 -0400262 struct weston_touch *touch = grab->touch;
Rob Bradford880ebc72013-07-22 17:31:38 +0100263 struct wl_display *display = touch->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400264 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +0100265 struct wl_resource *resource;
266 struct wl_list *resource_list;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400267
Neil Roberts96d790e2013-09-19 17:32:00 +0100268 resource_list = &touch->focus_resource_list;
269
270 if (!wl_list_empty(resource_list)) {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400271 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +0100272 wl_resource_for_each(resource, resource_list)
273 wl_touch_send_up(resource, serial, time, touch_id);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400274 }
275}
276
Kristian Høgsberge329f362013-05-06 22:19:57 -0400277static void
278default_grab_touch_motion(struct weston_touch_grab *grab, uint32_t time,
279 int touch_id, wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400280{
Kristian Høgsberge329f362013-05-06 22:19:57 -0400281 struct weston_touch *touch = grab->touch;
Neil Roberts96d790e2013-09-19 17:32:00 +0100282 struct wl_resource *resource;
283 struct wl_list *resource_list;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400284
Neil Roberts96d790e2013-09-19 17:32:00 +0100285 resource_list = &touch->focus_resource_list;
286
287 wl_resource_for_each(resource, resource_list) {
288 wl_touch_send_motion(resource, time,
Kristian Høgsberge329f362013-05-06 22:19:57 -0400289 touch_id, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400290 }
291}
292
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200293static void
Jonas Ådahl1679f232014-04-12 09:39:51 +0200294default_grab_touch_frame(struct weston_touch_grab *grab)
295{
296 struct wl_resource *resource;
297
298 wl_resource_for_each(resource, &grab->touch->focus_resource_list)
299 wl_touch_send_frame(resource);
300}
301
302static void
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200303default_grab_touch_cancel(struct weston_touch_grab *grab)
304{
305}
306
Kristian Høgsberge329f362013-05-06 22:19:57 -0400307static const struct weston_touch_grab_interface default_touch_grab_interface = {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400308 default_grab_touch_down,
309 default_grab_touch_up,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200310 default_grab_touch_motion,
Jonas Ådahl1679f232014-04-12 09:39:51 +0200311 default_grab_touch_frame,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200312 default_grab_touch_cancel,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400313};
314
315static void
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700316default_grab_keyboard_key(struct weston_keyboard_grab *grab,
317 uint32_t time, uint32_t key, uint32_t state)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400318{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400319 struct weston_keyboard *keyboard = grab->keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400320 struct wl_resource *resource;
Rob Bradford880ebc72013-07-22 17:31:38 +0100321 struct wl_display *display = keyboard->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400322 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +0100323 struct wl_list *resource_list;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400324
Neil Roberts96d790e2013-09-19 17:32:00 +0100325 resource_list = &keyboard->focus_resource_list;
326 if (!wl_list_empty(resource_list)) {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400327 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +0100328 wl_resource_for_each(resource, resource_list)
329 wl_keyboard_send_key(resource,
330 serial,
331 time,
332 key,
333 state);
334 }
335}
336
337static void
338send_modifiers_to_resource(struct weston_keyboard *keyboard,
339 struct wl_resource *resource,
340 uint32_t serial)
341{
342 wl_keyboard_send_modifiers(resource,
343 serial,
344 keyboard->modifiers.mods_depressed,
345 keyboard->modifiers.mods_latched,
346 keyboard->modifiers.mods_locked,
347 keyboard->modifiers.group);
348}
349
350static void
351send_modifiers_to_client_in_list(struct wl_client *client,
352 struct wl_list *list,
353 uint32_t serial,
354 struct weston_keyboard *keyboard)
355{
356 struct wl_resource *resource;
357
358 wl_resource_for_each(resource, list) {
359 if (wl_resource_get_client(resource) == client)
360 send_modifiers_to_resource(keyboard,
361 resource,
362 serial);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400363 }
364}
365
366static struct wl_resource *
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400367find_resource_for_surface(struct wl_list *list, struct weston_surface *surface)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400368{
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400369 if (!surface)
370 return NULL;
371
Jason Ekstrand44a38632013-06-14 10:08:00 -0500372 if (!surface->resource)
373 return NULL;
Stefan Schmidtfda26522013-09-17 10:54:09 +0100374
Jason Ekstrand44a38632013-06-14 10:08:00 -0500375 return wl_resource_find_for_client(list, wl_resource_get_client(surface->resource));
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400376}
377
Jason Ekstranda7af7042013-10-12 22:38:11 -0500378static struct wl_resource *
379find_resource_for_view(struct wl_list *list, struct weston_view *view)
380{
381 if (!view)
382 return NULL;
383
384 return find_resource_for_surface(list, view->surface);
385}
386
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400387static void
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700388default_grab_keyboard_modifiers(struct weston_keyboard_grab *grab,
389 uint32_t serial, uint32_t mods_depressed,
390 uint32_t mods_latched,
391 uint32_t mods_locked, uint32_t group)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400392{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400393 struct weston_keyboard *keyboard = grab->keyboard;
Derek Foreman1281a362015-07-31 16:55:32 -0500394 struct weston_pointer *pointer =
395 weston_seat_get_pointer(grab->keyboard->seat);
Neil Roberts96d790e2013-09-19 17:32:00 +0100396 struct wl_resource *resource;
397 struct wl_list *resource_list;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400398
Neil Roberts96d790e2013-09-19 17:32:00 +0100399 resource_list = &keyboard->focus_resource_list;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400400
Neil Roberts96d790e2013-09-19 17:32:00 +0100401 wl_resource_for_each(resource, resource_list) {
402 wl_keyboard_send_modifiers(resource, serial, mods_depressed,
403 mods_latched, mods_locked, group);
404 }
Jason Ekstrand42133d42013-11-14 20:06:16 -0600405 if (pointer && pointer->focus && pointer->focus->surface->resource &&
406 pointer->focus->surface != keyboard->focus) {
Neil Roberts96d790e2013-09-19 17:32:00 +0100407 struct wl_client *pointer_client =
Jason Ekstranda7af7042013-10-12 22:38:11 -0500408 wl_resource_get_client(pointer->focus->surface->resource);
Neil Roberts96d790e2013-09-19 17:32:00 +0100409 send_modifiers_to_client_in_list(pointer_client,
410 &keyboard->resource_list,
411 serial,
412 keyboard);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400413 }
414}
415
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200416static void
417default_grab_keyboard_cancel(struct weston_keyboard_grab *grab)
418{
419}
420
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400421static const struct weston_keyboard_grab_interface
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400422 default_keyboard_grab_interface = {
Kristian Høgsbergb27901c2013-10-28 15:32:02 -0700423 default_grab_keyboard_key,
424 default_grab_keyboard_modifiers,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200425 default_grab_keyboard_cancel,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400426};
427
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400428static void
429pointer_unmap_sprite(struct weston_pointer *pointer)
430{
Pekka Paalanenc557ff72014-11-12 16:42:52 +0200431 struct weston_surface *surface = pointer->sprite->surface;
432
433 if (weston_surface_is_mapped(surface))
434 weston_surface_unmap(surface);
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400435
436 wl_list_remove(&pointer->sprite_destroy_listener.link);
Pekka Paalanenc557ff72014-11-12 16:42:52 +0200437 surface->configure = NULL;
438 surface->configure_private = NULL;
Pekka Paalanen8274d902014-08-06 19:36:51 +0300439 weston_surface_set_label_func(surface, NULL);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500440 weston_view_destroy(pointer->sprite);
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400441 pointer->sprite = NULL;
442}
443
444static void
445pointer_handle_sprite_destroy(struct wl_listener *listener, void *data)
446{
447 struct weston_pointer *pointer =
448 container_of(listener, struct weston_pointer,
449 sprite_destroy_listener);
450
451 pointer->sprite = NULL;
452}
453
Jonas Ådahl3e12e632013-12-02 22:05:05 +0100454static void
455weston_pointer_reset_state(struct weston_pointer *pointer)
456{
457 pointer->button_count = 0;
458}
459
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +0200460static void
461weston_pointer_handle_output_destroy(struct wl_listener *listener, void *data);
462
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400463WL_EXPORT struct weston_pointer *
Giulio Camuffocdb4d292013-11-14 23:42:53 +0100464weston_pointer_create(struct weston_seat *seat)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400465{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400466 struct weston_pointer *pointer;
467
Peter Huttererf3d62272013-08-08 11:57:05 +1000468 pointer = zalloc(sizeof *pointer);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400469 if (pointer == NULL)
470 return NULL;
471
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400472 wl_list_init(&pointer->resource_list);
Neil Roberts96d790e2013-09-19 17:32:00 +0100473 wl_list_init(&pointer->focus_resource_list);
Giulio Camuffocdb4d292013-11-14 23:42:53 +0100474 weston_pointer_set_default_grab(pointer,
475 seat->compositor->default_pointer_grab);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100476 wl_list_init(&pointer->focus_resource_listener.link);
477 pointer->focus_resource_listener.notify = pointer_focus_resource_destroyed;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400478 pointer->default_grab.pointer = pointer;
479 pointer->grab = &pointer->default_grab;
Giulio Camuffo6fcb3782013-11-14 23:42:50 +0100480 wl_signal_init(&pointer->motion_signal);
Emilio Pozuelo Monfortaa7a4762013-11-19 11:37:15 +0100481 wl_signal_init(&pointer->focus_signal);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100482 wl_list_init(&pointer->focus_view_listener.link);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400483
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400484 pointer->sprite_destroy_listener.notify = pointer_handle_sprite_destroy;
485
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400486 /* FIXME: Pick better co-ords. */
487 pointer->x = wl_fixed_from_int(100);
488 pointer->y = wl_fixed_from_int(100);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400489
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +0200490 pointer->output_destroy_listener.notify =
491 weston_pointer_handle_output_destroy;
492 wl_signal_add(&seat->compositor->output_destroyed_signal,
493 &pointer->output_destroy_listener);
494
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400495 return pointer;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400496}
497
498WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400499weston_pointer_destroy(struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400500{
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400501 if (pointer->sprite)
502 pointer_unmap_sprite(pointer);
503
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400504 /* XXX: What about pointer->resource_list? */
Neil Roberts96d790e2013-09-19 17:32:00 +0100505
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100506 wl_list_remove(&pointer->focus_resource_listener.link);
507 wl_list_remove(&pointer->focus_view_listener.link);
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +0200508 wl_list_remove(&pointer->output_destroy_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400509 free(pointer);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400510}
511
Giulio Camuffocdb4d292013-11-14 23:42:53 +0100512void
513weston_pointer_set_default_grab(struct weston_pointer *pointer,
514 const struct weston_pointer_grab_interface *interface)
515{
516 if (interface)
517 pointer->default_grab.interface = interface;
518 else
519 pointer->default_grab.interface =
520 &default_pointer_grab_interface;
521}
522
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400523WL_EXPORT struct weston_keyboard *
524weston_keyboard_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400525{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400526 struct weston_keyboard *keyboard;
527
Peter Huttererf3d62272013-08-08 11:57:05 +1000528 keyboard = zalloc(sizeof *keyboard);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400529 if (keyboard == NULL)
Neil Roberts96d790e2013-09-19 17:32:00 +0100530 return NULL;
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400531
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400532 wl_list_init(&keyboard->resource_list);
Neil Roberts96d790e2013-09-19 17:32:00 +0100533 wl_list_init(&keyboard->focus_resource_list);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100534 wl_list_init(&keyboard->focus_resource_listener.link);
535 keyboard->focus_resource_listener.notify = keyboard_focus_resource_destroyed;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400536 wl_array_init(&keyboard->keys);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400537 keyboard->default_grab.interface = &default_keyboard_grab_interface;
538 keyboard->default_grab.keyboard = keyboard;
539 keyboard->grab = &keyboard->default_grab;
540 wl_signal_init(&keyboard->focus_signal);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400541
542 return keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400543}
544
Jonas Ådahl7395ea02013-12-03 09:14:26 +0100545static void
546weston_xkb_info_destroy(struct weston_xkb_info *xkb_info);
547
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400548WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400549weston_keyboard_destroy(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400550{
551 /* XXX: What about keyboard->resource_list? */
Neil Roberts96d790e2013-09-19 17:32:00 +0100552
Jonas Ådahl7395ea02013-12-03 09:14:26 +0100553#ifdef ENABLE_XKBCOMMON
554 if (keyboard->seat->compositor->use_xkbcommon) {
Ran Benitac9c74152014-08-19 23:59:52 +0300555 xkb_state_unref(keyboard->xkb_state.state);
Jonas Ådahl7395ea02013-12-03 09:14:26 +0100556 if (keyboard->xkb_info)
557 weston_xkb_info_destroy(keyboard->xkb_info);
Ran Benitac9c74152014-08-19 23:59:52 +0300558 xkb_keymap_unref(keyboard->pending_keymap);
Jonas Ådahl7395ea02013-12-03 09:14:26 +0100559 }
560#endif
561
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400562 wl_array_release(&keyboard->keys);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100563 wl_list_remove(&keyboard->focus_resource_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400564 free(keyboard);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400565}
566
Jonas Ådahlcbfa7f72013-12-02 22:05:04 +0100567static void
568weston_touch_reset_state(struct weston_touch *touch)
569{
570 touch->num_tp = 0;
571}
572
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400573WL_EXPORT struct weston_touch *
574weston_touch_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400575{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400576 struct weston_touch *touch;
577
Peter Huttererf3d62272013-08-08 11:57:05 +1000578 touch = zalloc(sizeof *touch);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400579 if (touch == NULL)
580 return NULL;
581
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400582 wl_list_init(&touch->resource_list);
Neil Roberts96d790e2013-09-19 17:32:00 +0100583 wl_list_init(&touch->focus_resource_list);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100584 wl_list_init(&touch->focus_view_listener.link);
585 touch->focus_view_listener.notify = touch_focus_view_destroyed;
586 wl_list_init(&touch->focus_resource_listener.link);
587 touch->focus_resource_listener.notify = touch_focus_resource_destroyed;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400588 touch->default_grab.interface = &default_touch_grab_interface;
589 touch->default_grab.touch = touch;
590 touch->grab = &touch->default_grab;
591 wl_signal_init(&touch->focus_signal);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400592
593 return touch;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400594}
595
596WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400597weston_touch_destroy(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400598{
599 /* XXX: What about touch->resource_list? */
Neil Roberts96d790e2013-09-19 17:32:00 +0100600
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100601 wl_list_remove(&touch->focus_view_listener.link);
602 wl_list_remove(&touch->focus_resource_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400603 free(touch);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400604}
605
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400606static void
Kristian Høgsberge3148752013-05-06 23:19:49 -0400607seat_send_updated_caps(struct weston_seat *seat)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400608{
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400609 enum wl_seat_capability caps = 0;
Rob Bradford6e737f52013-09-06 17:48:19 +0100610 struct wl_resource *resource;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400611
Jonas Ådahld6e1c342013-10-17 23:04:05 +0200612 if (seat->pointer_device_count > 0)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400613 caps |= WL_SEAT_CAPABILITY_POINTER;
Jonas Ådahld6e1c342013-10-17 23:04:05 +0200614 if (seat->keyboard_device_count > 0)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400615 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
Jonas Ådahld6e1c342013-10-17 23:04:05 +0200616 if (seat->touch_device_count > 0)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400617 caps |= WL_SEAT_CAPABILITY_TOUCH;
618
Rob Bradford6e737f52013-09-06 17:48:19 +0100619 wl_resource_for_each(resource, &seat->base_resource_list) {
620 wl_seat_send_capabilities(resource, caps);
Jason Ekstrand44a38632013-06-14 10:08:00 -0500621 }
Jason Ekstranda4ab5422014-04-02 19:53:45 -0500622 wl_signal_emit(&seat->updated_caps_signal, seat);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400623}
624
625WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400626weston_pointer_set_focus(struct weston_pointer *pointer,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500627 struct weston_view *view,
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400628 wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400629{
Derek Foreman1281a362015-07-31 16:55:32 -0500630 struct weston_keyboard *kbd = weston_seat_get_keyboard(pointer->seat);
Neil Roberts96d790e2013-09-19 17:32:00 +0100631 struct wl_resource *resource;
Rob Bradford880ebc72013-07-22 17:31:38 +0100632 struct wl_display *display = pointer->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400633 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +0100634 struct wl_list *focus_resource_list;
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -0800635 int refocus = 0;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500636
637 if ((!pointer->focus && view) ||
638 (pointer->focus && !view) ||
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -0800639 (pointer->focus && pointer->focus->surface != view->surface) ||
640 pointer->sx != sx || pointer->sy != sy)
641 refocus = 1;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400642
Neil Roberts96d790e2013-09-19 17:32:00 +0100643 focus_resource_list = &pointer->focus_resource_list;
644
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -0800645 if (!wl_list_empty(focus_resource_list) && refocus) {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400646 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +0100647 wl_resource_for_each(resource, focus_resource_list) {
648 wl_pointer_send_leave(resource, serial,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500649 pointer->focus->surface->resource);
Neil Roberts96d790e2013-09-19 17:32:00 +0100650 }
651
652 move_resources(&pointer->resource_list, focus_resource_list);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400653 }
654
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -0800655 if (find_resource_for_view(&pointer->resource_list, view) && refocus) {
Neil Roberts96d790e2013-09-19 17:32:00 +0100656 struct wl_client *surface_client =
Jason Ekstranda7af7042013-10-12 22:38:11 -0500657 wl_resource_get_client(view->surface->resource);
Neil Roberts96d790e2013-09-19 17:32:00 +0100658
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400659 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +0100660
Jason Ekstranda7af7042013-10-12 22:38:11 -0500661 if (kbd && kbd->focus != view->surface)
Kristian Høgsbergcb406f12013-10-09 10:54:03 -0700662 send_modifiers_to_client_in_list(surface_client,
663 &kbd->resource_list,
664 serial,
665 kbd);
666
Neil Roberts96d790e2013-09-19 17:32:00 +0100667 move_resources_for_client(focus_resource_list,
668 &pointer->resource_list,
669 surface_client);
670
671 wl_resource_for_each(resource, focus_resource_list) {
672 wl_pointer_send_enter(resource,
673 serial,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500674 view->surface->resource,
Neil Roberts96d790e2013-09-19 17:32:00 +0100675 sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400676 }
Neil Roberts96d790e2013-09-19 17:32:00 +0100677
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400678 pointer->focus_serial = serial;
679 }
680
Giulio Camuffo65a07f82013-12-06 12:46:27 +0100681 wl_list_remove(&pointer->focus_view_listener.link);
682 wl_list_init(&pointer->focus_view_listener.link);
683 wl_list_remove(&pointer->focus_resource_listener.link);
684 wl_list_init(&pointer->focus_resource_listener.link);
Emilio Pozuelo Monfortaa7a4762013-11-19 11:37:15 +0100685 if (view)
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100686 wl_signal_add(&view->destroy_signal, &pointer->focus_view_listener);
Giulio Camuffo65a07f82013-12-06 12:46:27 +0100687 if (view && view->surface->resource)
688 wl_resource_add_destroy_listener(view->surface->resource,
689 &pointer->focus_resource_listener);
690
691 pointer->focus = view;
692 pointer->focus_view_listener.notify = pointer_focus_view_destroyed;
Kristian Høgsbergdb1fccb2014-02-05 17:14:42 -0800693 pointer->sx = sx;
694 pointer->sy = sy;
695
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400696 wl_signal_emit(&pointer->focus_signal, pointer);
697}
698
Neil Roberts96d790e2013-09-19 17:32:00 +0100699static void
700send_enter_to_resource_list(struct wl_list *list,
701 struct weston_keyboard *keyboard,
702 struct weston_surface *surface,
703 uint32_t serial)
704{
705 struct wl_resource *resource;
706
707 wl_resource_for_each(resource, list) {
708 send_modifiers_to_resource(keyboard, resource, serial);
709 wl_keyboard_send_enter(resource, serial,
710 surface->resource,
711 &keyboard->keys);
712 }
713}
714
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400715WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400716weston_keyboard_set_focus(struct weston_keyboard *keyboard,
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400717 struct weston_surface *surface)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400718{
719 struct wl_resource *resource;
Rob Bradford880ebc72013-07-22 17:31:38 +0100720 struct wl_display *display = keyboard->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400721 uint32_t serial;
Neil Roberts96d790e2013-09-19 17:32:00 +0100722 struct wl_list *focus_resource_list;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400723
Neil Roberts96d790e2013-09-19 17:32:00 +0100724 focus_resource_list = &keyboard->focus_resource_list;
725
726 if (!wl_list_empty(focus_resource_list) && keyboard->focus != surface) {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400727 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +0100728 wl_resource_for_each(resource, focus_resource_list) {
729 wl_keyboard_send_leave(resource, serial,
730 keyboard->focus->resource);
731 }
732 move_resources(&keyboard->resource_list, focus_resource_list);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400733 }
734
Neil Roberts96d790e2013-09-19 17:32:00 +0100735 if (find_resource_for_surface(&keyboard->resource_list, surface) &&
736 keyboard->focus != surface) {
737 struct wl_client *surface_client =
738 wl_resource_get_client(surface->resource);
739
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400740 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +0100741
742 move_resources_for_client(focus_resource_list,
743 &keyboard->resource_list,
744 surface_client);
745 send_enter_to_resource_list(focus_resource_list,
746 keyboard,
747 surface,
748 serial);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400749 keyboard->focus_serial = serial;
Giulio Camuffo65a07f82013-12-06 12:46:27 +0100750 }
751
752 wl_list_remove(&keyboard->focus_resource_listener.link);
753 wl_list_init(&keyboard->focus_resource_listener.link);
754 if (surface && surface->resource)
Giulio Camuffo576fe2a2013-11-20 18:00:24 +0100755 wl_resource_add_destroy_listener(surface->resource,
756 &keyboard->focus_resource_listener);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400757
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400758 keyboard->focus = surface;
759 wl_signal_emit(&keyboard->focus_signal, keyboard);
760}
761
Giulio Camuffoa20ca812014-11-22 11:16:56 +0200762/* Users of this function must manually manage the keyboard focus */
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400763WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400764weston_keyboard_start_grab(struct weston_keyboard *keyboard,
765 struct weston_keyboard_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400766{
767 keyboard->grab = grab;
768 grab->keyboard = keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400769}
770
771WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400772weston_keyboard_end_grab(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400773{
774 keyboard->grab = &keyboard->default_grab;
775}
776
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200777static void
778weston_keyboard_cancel_grab(struct weston_keyboard *keyboard)
779{
780 keyboard->grab->interface->cancel(keyboard->grab);
781}
782
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400783WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400784weston_pointer_start_grab(struct weston_pointer *pointer,
785 struct weston_pointer_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400786{
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400787 pointer->grab = grab;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400788 grab->pointer = pointer;
Kristian Høgsbergda751b82013-07-04 00:58:07 -0400789 pointer->grab->interface->focus(pointer->grab);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400790}
791
792WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400793weston_pointer_end_grab(struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400794{
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400795 pointer->grab = &pointer->default_grab;
Kristian Høgsbergda751b82013-07-04 00:58:07 -0400796 pointer->grab->interface->focus(pointer->grab);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400797}
798
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200799static void
800weston_pointer_cancel_grab(struct weston_pointer *pointer)
801{
802 pointer->grab->interface->cancel(pointer->grab);
803}
804
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400805WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -0400806weston_touch_start_grab(struct weston_touch *touch, struct weston_touch_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400807{
808 touch->grab = grab;
809 grab->touch = touch;
810}
811
812WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -0400813weston_touch_end_grab(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400814{
815 touch->grab = &touch->default_grab;
816}
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400817
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200818static void
819weston_touch_cancel_grab(struct weston_touch *touch)
820{
821 touch->grab->interface->cancel(touch->grab);
822}
823
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +0200824static void
825weston_pointer_clamp_for_output(struct weston_pointer *pointer,
826 struct weston_output *output,
827 wl_fixed_t *fx, wl_fixed_t *fy)
828{
829 int x, y;
830
831 x = wl_fixed_to_int(*fx);
832 y = wl_fixed_to_int(*fy);
833
834 if (x < output->x)
835 *fx = wl_fixed_from_int(output->x);
836 else if (x >= output->x + output->width)
837 *fx = wl_fixed_from_int(output->x +
838 output->width - 1);
839 if (y < output->y)
840 *fy = wl_fixed_from_int(output->y);
841 else if (y >= output->y + output->height)
842 *fy = wl_fixed_from_int(output->y +
843 output->height - 1);
844}
845
Rob Bradford806d8c02013-06-25 18:56:41 +0100846WL_EXPORT void
847weston_pointer_clamp(struct weston_pointer *pointer, wl_fixed_t *fx, wl_fixed_t *fy)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400848{
Rob Bradford806d8c02013-06-25 18:56:41 +0100849 struct weston_compositor *ec = pointer->seat->compositor;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400850 struct weston_output *output, *prev = NULL;
851 int x, y, old_x, old_y, valid = 0;
852
853 x = wl_fixed_to_int(*fx);
854 y = wl_fixed_to_int(*fy);
Rob Bradford806d8c02013-06-25 18:56:41 +0100855 old_x = wl_fixed_to_int(pointer->x);
856 old_y = wl_fixed_to_int(pointer->y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400857
858 wl_list_for_each(output, &ec->output_list, link) {
Rob Bradford66bd9f52013-06-25 18:56:42 +0100859 if (pointer->seat->output && pointer->seat->output != output)
860 continue;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400861 if (pixman_region32_contains_point(&output->region,
862 x, y, NULL))
863 valid = 1;
864 if (pixman_region32_contains_point(&output->region,
865 old_x, old_y, NULL))
866 prev = output;
867 }
868
Rob Bradford66bd9f52013-06-25 18:56:42 +0100869 if (!prev)
870 prev = pointer->seat->output;
871
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +0200872 if (prev && !valid)
873 weston_pointer_clamp_for_output(pointer, prev, fx, fy);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400874}
875
876/* Takes absolute values */
Giulio Camuffo1959ab82013-11-14 23:42:52 +0100877WL_EXPORT void
878weston_pointer_move(struct weston_pointer *pointer, wl_fixed_t x, wl_fixed_t y)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400879{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400880 int32_t ix, iy;
881
Rob Bradford806d8c02013-06-25 18:56:41 +0100882 weston_pointer_clamp (pointer, &x, &y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400883
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400884 pointer->x = x;
885 pointer->y = y;
886
887 ix = wl_fixed_to_int(x);
888 iy = wl_fixed_to_int(y);
889
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400890 if (pointer->sprite) {
Jason Ekstranda7af7042013-10-12 22:38:11 -0500891 weston_view_set_position(pointer->sprite,
892 ix - pointer->hotspot_x,
893 iy - pointer->hotspot_y);
894 weston_view_schedule_repaint(pointer->sprite);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400895 }
Giulio Camuffo6fcb3782013-11-14 23:42:50 +0100896
Giulio Camuffo1959ab82013-11-14 23:42:52 +0100897 pointer->grab->interface->focus(pointer->grab);
Giulio Camuffo6fcb3782013-11-14 23:42:50 +0100898 wl_signal_emit(&pointer->motion_signal, pointer);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400899}
900
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +0200901/** Verify if the pointer is in a valid position and move it if it isn't.
902 */
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +0200903static void
904weston_pointer_handle_output_destroy(struct wl_listener *listener, void *data)
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +0200905{
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +0200906 struct weston_pointer *pointer;
907 struct weston_compositor *ec;
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +0200908 struct weston_output *output, *closest = NULL;
909 int x, y, distance, min = INT_MAX;
910 wl_fixed_t fx, fy;
911
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +0200912 pointer = container_of(listener, struct weston_pointer,
913 output_destroy_listener);
914 ec = pointer->seat->compositor;
915
Ander Conselvan de Oliveira54e90c72013-12-13 22:10:56 +0200916 x = wl_fixed_to_int(pointer->x);
917 y = wl_fixed_to_int(pointer->y);
918
919 wl_list_for_each(output, &ec->output_list, link) {
920 if (pixman_region32_contains_point(&output->region,
921 x, y, NULL))
922 return;
923
924 /* Aproximante the distance from the pointer to the center of
925 * the output. */
926 distance = abs(output->x + output->width / 2 - x) +
927 abs(output->y + output->height / 2 - y);
928 if (distance < min) {
929 min = distance;
930 closest = output;
931 }
932 }
933
934 /* Nothing to do if there's no output left. */
935 if (!closest)
936 return;
937
938 fx = pointer->x;
939 fy = pointer->y;
940
941 weston_pointer_clamp_for_output(pointer, closest, &fx, &fy);
942 weston_pointer_move(pointer, fx, fy);
943}
944
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400945WL_EXPORT void
946notify_motion(struct weston_seat *seat,
947 uint32_t time, wl_fixed_t dx, wl_fixed_t dy)
948{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400949 struct weston_compositor *ec = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -0500950 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400951
952 weston_compositor_wake(ec);
Giulio Camuffo1959ab82013-11-14 23:42:52 +0100953 pointer->grab->interface->motion(pointer->grab, time, pointer->x + dx, pointer->y + dy);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400954}
955
Daniel Stone96d47c02013-11-19 11:37:12 +0100956static void
957run_modifier_bindings(struct weston_seat *seat, uint32_t old, uint32_t new)
958{
959 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -0500960 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Daniel Stone96d47c02013-11-19 11:37:12 +0100961 uint32_t diff;
962 unsigned int i;
963 struct {
964 uint32_t xkb;
965 enum weston_keyboard_modifier weston;
966 } mods[] = {
Jonas Ådahl7395ea02013-12-03 09:14:26 +0100967 { keyboard->xkb_info->ctrl_mod, MODIFIER_CTRL },
968 { keyboard->xkb_info->alt_mod, MODIFIER_ALT },
969 { keyboard->xkb_info->super_mod, MODIFIER_SUPER },
970 { keyboard->xkb_info->shift_mod, MODIFIER_SHIFT },
Daniel Stone96d47c02013-11-19 11:37:12 +0100971 };
972
973 diff = new & ~old;
974 for (i = 0; i < ARRAY_LENGTH(mods); i++) {
975 if (diff & (1 << mods[i].xkb))
976 weston_compositor_run_modifier_binding(compositor,
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500977 keyboard,
Daniel Stone96d47c02013-11-19 11:37:12 +0100978 mods[i].weston,
979 WL_KEYBOARD_KEY_STATE_PRESSED);
980 }
981
982 diff = old & ~new;
983 for (i = 0; i < ARRAY_LENGTH(mods); i++) {
984 if (diff & (1 << mods[i].xkb))
985 weston_compositor_run_modifier_binding(compositor,
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500986 keyboard,
Daniel Stone96d47c02013-11-19 11:37:12 +0100987 mods[i].weston,
988 WL_KEYBOARD_KEY_STATE_RELEASED);
989 }
990}
991
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400992WL_EXPORT void
993notify_motion_absolute(struct weston_seat *seat,
994 uint32_t time, wl_fixed_t x, wl_fixed_t y)
995{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400996 struct weston_compositor *ec = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -0500997 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400998
999 weston_compositor_wake(ec);
Giulio Camuffo1959ab82013-11-14 23:42:52 +01001000 pointer->grab->interface->motion(pointer->grab, time, x, y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001001}
1002
1003WL_EXPORT void
1004weston_surface_activate(struct weston_surface *surface,
1005 struct weston_seat *seat)
1006{
1007 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001008 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001009
Derek Foreman1281a362015-07-31 16:55:32 -05001010 if (keyboard) {
1011 weston_keyboard_set_focus(keyboard, surface);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001012 wl_data_device_set_keyboard_focus(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001013 }
1014
1015 wl_signal_emit(&compositor->activate_signal, surface);
1016}
1017
1018WL_EXPORT void
1019notify_button(struct weston_seat *seat, uint32_t time, int32_t button,
1020 enum wl_pointer_button_state state)
1021{
1022 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001023 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001024
1025 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001026 weston_compositor_idle_inhibit(compositor);
1027 if (pointer->button_count == 0) {
1028 pointer->grab_button = button;
1029 pointer->grab_time = time;
1030 pointer->grab_x = pointer->x;
1031 pointer->grab_y = pointer->y;
1032 }
1033 pointer->button_count++;
1034 } else {
1035 weston_compositor_idle_release(compositor);
1036 pointer->button_count--;
1037 }
1038
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001039 weston_compositor_run_button_binding(compositor, pointer, time, button,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001040 state);
1041
1042 pointer->grab->interface->button(pointer->grab, time, button, state);
1043
1044 if (pointer->button_count == 1)
1045 pointer->grab_serial =
1046 wl_display_get_serial(compositor->wl_display);
1047}
1048
1049WL_EXPORT void
1050notify_axis(struct weston_seat *seat, uint32_t time, uint32_t axis,
1051 wl_fixed_t value)
1052{
1053 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001054 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Neil Roberts96d790e2013-09-19 17:32:00 +01001055 struct wl_resource *resource;
1056 struct wl_list *resource_list;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001057
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001058 weston_compositor_wake(compositor);
1059
1060 if (!value)
1061 return;
1062
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001063 if (weston_compositor_run_axis_binding(compositor, pointer,
1064 time, axis, value))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001065 return;
1066
Neil Roberts96d790e2013-09-19 17:32:00 +01001067 resource_list = &pointer->focus_resource_list;
1068 wl_resource_for_each(resource, resource_list)
1069 wl_pointer_send_axis(resource, time, axis,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001070 value);
1071}
1072
Giulio Camuffo6ef444d2014-08-28 19:44:09 +03001073WL_EXPORT int
1074weston_keyboard_set_locks(struct weston_keyboard *keyboard,
1075 uint32_t mask, uint32_t value)
1076{
1077#ifdef ENABLE_XKBCOMMON
1078 uint32_t serial;
1079 xkb_mod_mask_t mods_depressed, mods_latched, mods_locked, group;
1080 xkb_mod_mask_t num, caps;
1081
1082 /* We don't want the leds to go out of sync with the actual state
1083 * so if the backend has no way to change the leds don't try to
1084 * change the state */
1085 if (!keyboard->seat->led_update)
1086 return -1;
1087
1088 mods_depressed = xkb_state_serialize_mods(keyboard->xkb_state.state,
1089 XKB_STATE_DEPRESSED);
1090 mods_latched = xkb_state_serialize_mods(keyboard->xkb_state.state,
1091 XKB_STATE_LATCHED);
1092 mods_locked = xkb_state_serialize_mods(keyboard->xkb_state.state,
1093 XKB_STATE_LOCKED);
1094 group = xkb_state_serialize_group(keyboard->xkb_state.state,
1095 XKB_STATE_EFFECTIVE);
1096
1097 num = (1 << keyboard->xkb_info->mod2_mod);
1098 caps = (1 << keyboard->xkb_info->caps_mod);
1099 if (mask & WESTON_NUM_LOCK) {
1100 if (value & WESTON_NUM_LOCK)
1101 mods_locked |= num;
1102 else
1103 mods_locked &= ~num;
1104 }
1105 if (mask & WESTON_CAPS_LOCK) {
1106 if (value & WESTON_CAPS_LOCK)
1107 mods_locked |= caps;
1108 else
1109 mods_locked &= ~caps;
1110 }
1111
1112 xkb_state_update_mask(keyboard->xkb_state.state, mods_depressed,
1113 mods_latched, mods_locked, 0, 0, group);
1114
1115 serial = wl_display_next_serial(
1116 keyboard->seat->compositor->wl_display);
1117 notify_modifiers(keyboard->seat, serial);
1118
1119 return 0;
1120#else
1121 return -1;
1122#endif
1123}
1124
Rob Bradford382ff462013-06-24 16:52:45 +01001125#ifdef ENABLE_XKBCOMMON
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001126WL_EXPORT void
1127notify_modifiers(struct weston_seat *seat, uint32_t serial)
1128{
Derek Foreman1281a362015-07-31 16:55:32 -05001129 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001130 struct weston_keyboard_grab *grab = keyboard->grab;
1131 uint32_t mods_depressed, mods_latched, mods_locked, group;
1132 uint32_t mods_lookup;
1133 enum weston_led leds = 0;
1134 int changed = 0;
1135
1136 /* Serialize and update our internal state, checking to see if it's
1137 * different to the previous state. */
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001138 mods_depressed = xkb_state_serialize_mods(keyboard->xkb_state.state,
Ran Benita2e1968f2014-08-19 23:59:51 +03001139 XKB_STATE_MODS_DEPRESSED);
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001140 mods_latched = xkb_state_serialize_mods(keyboard->xkb_state.state,
Ran Benita2e1968f2014-08-19 23:59:51 +03001141 XKB_STATE_MODS_LATCHED);
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001142 mods_locked = xkb_state_serialize_mods(keyboard->xkb_state.state,
Ran Benita2e1968f2014-08-19 23:59:51 +03001143 XKB_STATE_MODS_LOCKED);
1144 group = xkb_state_serialize_layout(keyboard->xkb_state.state,
1145 XKB_STATE_LAYOUT_EFFECTIVE);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001146
Derek Foreman244e99e2015-06-03 15:53:26 -05001147 if (mods_depressed != keyboard->modifiers.mods_depressed ||
1148 mods_latched != keyboard->modifiers.mods_latched ||
1149 mods_locked != keyboard->modifiers.mods_locked ||
1150 group != keyboard->modifiers.group)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001151 changed = 1;
1152
Derek Foreman244e99e2015-06-03 15:53:26 -05001153 run_modifier_bindings(seat, keyboard->modifiers.mods_depressed,
Daniel Stone96d47c02013-11-19 11:37:12 +01001154 mods_depressed);
1155
Derek Foreman244e99e2015-06-03 15:53:26 -05001156 keyboard->modifiers.mods_depressed = mods_depressed;
1157 keyboard->modifiers.mods_latched = mods_latched;
1158 keyboard->modifiers.mods_locked = mods_locked;
1159 keyboard->modifiers.group = group;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001160
1161 /* And update the modifier_state for bindings. */
1162 mods_lookup = mods_depressed | mods_latched;
1163 seat->modifier_state = 0;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001164 if (mods_lookup & (1 << keyboard->xkb_info->ctrl_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001165 seat->modifier_state |= MODIFIER_CTRL;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001166 if (mods_lookup & (1 << keyboard->xkb_info->alt_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001167 seat->modifier_state |= MODIFIER_ALT;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001168 if (mods_lookup & (1 << keyboard->xkb_info->super_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001169 seat->modifier_state |= MODIFIER_SUPER;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001170 if (mods_lookup & (1 << keyboard->xkb_info->shift_mod))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001171 seat->modifier_state |= MODIFIER_SHIFT;
1172
1173 /* Finally, notify the compositor that LEDs have changed. */
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001174 if (xkb_state_led_index_is_active(keyboard->xkb_state.state,
1175 keyboard->xkb_info->num_led))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001176 leds |= LED_NUM_LOCK;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001177 if (xkb_state_led_index_is_active(keyboard->xkb_state.state,
1178 keyboard->xkb_info->caps_led))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001179 leds |= LED_CAPS_LOCK;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001180 if (xkb_state_led_index_is_active(keyboard->xkb_state.state,
1181 keyboard->xkb_info->scroll_led))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001182 leds |= LED_SCROLL_LOCK;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001183 if (leds != keyboard->xkb_state.leds && seat->led_update)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001184 seat->led_update(seat, leds);
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001185 keyboard->xkb_state.leds = leds;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001186
1187 if (changed) {
1188 grab->interface->modifiers(grab,
1189 serial,
1190 keyboard->modifiers.mods_depressed,
1191 keyboard->modifiers.mods_latched,
1192 keyboard->modifiers.mods_locked,
1193 keyboard->modifiers.group);
1194 }
1195}
1196
1197static void
1198update_modifier_state(struct weston_seat *seat, uint32_t serial, uint32_t key,
1199 enum wl_keyboard_key_state state)
1200{
Derek Foreman1281a362015-07-31 16:55:32 -05001201 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001202 enum xkb_key_direction direction;
1203
Matt Roper01a92732013-06-24 16:52:44 +01001204 /* Keyboard modifiers don't exist in raw keyboard mode */
1205 if (!seat->compositor->use_xkbcommon)
1206 return;
1207
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001208 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
1209 direction = XKB_KEY_DOWN;
1210 else
1211 direction = XKB_KEY_UP;
1212
1213 /* Offset the keycode by 8, as the evdev XKB rules reflect X's
1214 * broken keycode system, which starts at 8. */
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001215 xkb_state_update_key(keyboard->xkb_state.state, key + 8, direction);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001216
1217 notify_modifiers(seat, serial);
1218}
Rui Matos65196bc2013-10-10 19:44:19 +02001219
1220static void
1221send_keymap(struct wl_resource *resource, struct weston_xkb_info *xkb_info)
1222{
1223 wl_keyboard_send_keymap(resource,
1224 WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
1225 xkb_info->keymap_fd,
1226 xkb_info->keymap_size);
1227}
1228
1229static void
1230send_modifiers(struct wl_resource *resource, uint32_t serial, struct weston_keyboard *keyboard)
1231{
1232 wl_keyboard_send_modifiers(resource, serial,
1233 keyboard->modifiers.mods_depressed,
1234 keyboard->modifiers.mods_latched,
1235 keyboard->modifiers.mods_locked,
1236 keyboard->modifiers.group);
1237}
1238
1239static struct weston_xkb_info *
1240weston_xkb_info_create(struct xkb_keymap *keymap);
Rui Matos65196bc2013-10-10 19:44:19 +02001241
1242static void
1243update_keymap(struct weston_seat *seat)
1244{
Derek Foreman1281a362015-07-31 16:55:32 -05001245 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Rui Matos65196bc2013-10-10 19:44:19 +02001246 struct wl_resource *resource;
1247 struct weston_xkb_info *xkb_info;
1248 struct xkb_state *state;
1249 xkb_mod_mask_t latched_mods;
1250 xkb_mod_mask_t locked_mods;
1251
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001252 xkb_info = weston_xkb_info_create(keyboard->pending_keymap);
Rui Matos65196bc2013-10-10 19:44:19 +02001253
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001254 xkb_keymap_unref(keyboard->pending_keymap);
1255 keyboard->pending_keymap = NULL;
Rui Matos65196bc2013-10-10 19:44:19 +02001256
1257 if (!xkb_info) {
1258 weston_log("failed to create XKB info\n");
1259 return;
1260 }
1261
1262 state = xkb_state_new(xkb_info->keymap);
1263 if (!state) {
1264 weston_log("failed to initialise XKB state\n");
1265 weston_xkb_info_destroy(xkb_info);
1266 return;
1267 }
1268
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001269 latched_mods = xkb_state_serialize_mods(keyboard->xkb_state.state,
1270 XKB_STATE_MODS_LATCHED);
1271 locked_mods = xkb_state_serialize_mods(keyboard->xkb_state.state,
1272 XKB_STATE_MODS_LOCKED);
Rui Matos65196bc2013-10-10 19:44:19 +02001273 xkb_state_update_mask(state,
1274 0, /* depressed */
1275 latched_mods,
1276 locked_mods,
1277 0, 0, 0);
1278
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001279 weston_xkb_info_destroy(keyboard->xkb_info);
1280 keyboard->xkb_info = xkb_info;
Rui Matos65196bc2013-10-10 19:44:19 +02001281
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001282 xkb_state_unref(keyboard->xkb_state.state);
1283 keyboard->xkb_state.state = state;
Rui Matos65196bc2013-10-10 19:44:19 +02001284
Derek Foremanbc91e542015-06-03 15:53:27 -05001285 wl_resource_for_each(resource, &keyboard->resource_list)
Rui Matos65196bc2013-10-10 19:44:19 +02001286 send_keymap(resource, xkb_info);
Derek Foremanbc91e542015-06-03 15:53:27 -05001287 wl_resource_for_each(resource, &keyboard->focus_resource_list)
Rui Matos65196bc2013-10-10 19:44:19 +02001288 send_keymap(resource, xkb_info);
1289
1290 notify_modifiers(seat, wl_display_next_serial(seat->compositor->wl_display));
1291
1292 if (!latched_mods && !locked_mods)
1293 return;
1294
Derek Foremanbc91e542015-06-03 15:53:27 -05001295 wl_resource_for_each(resource, &keyboard->resource_list)
1296 send_modifiers(resource, wl_display_get_serial(seat->compositor->wl_display), keyboard);
1297 wl_resource_for_each(resource, &keyboard->focus_resource_list)
1298 send_modifiers(resource, wl_display_get_serial(seat->compositor->wl_display), keyboard);
Rui Matos65196bc2013-10-10 19:44:19 +02001299}
Rob Bradford382ff462013-06-24 16:52:45 +01001300#else
1301WL_EXPORT void
1302notify_modifiers(struct weston_seat *seat, uint32_t serial)
1303{
1304}
1305
1306static void
1307update_modifier_state(struct weston_seat *seat, uint32_t serial, uint32_t key,
1308 enum wl_keyboard_key_state state)
1309{
1310}
Rui Matos65196bc2013-10-10 19:44:19 +02001311
1312static void
1313update_keymap(struct weston_seat *seat)
1314{
1315}
Rob Bradford382ff462013-06-24 16:52:45 +01001316#endif
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001317
1318WL_EXPORT void
1319notify_key(struct weston_seat *seat, uint32_t time, uint32_t key,
1320 enum wl_keyboard_key_state state,
1321 enum weston_key_state_update update_state)
1322{
1323 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001324 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001325 struct weston_keyboard_grab *grab = keyboard->grab;
Pekka Paalanen86b53962014-11-19 13:43:32 +02001326 uint32_t *k, *end;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001327
1328 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001329 weston_compositor_idle_inhibit(compositor);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001330 } else {
1331 weston_compositor_idle_release(compositor);
1332 }
1333
Pekka Paalanen86b53962014-11-19 13:43:32 +02001334 end = keyboard->keys.data + keyboard->keys.size;
1335 for (k = keyboard->keys.data; k < end; k++) {
1336 if (*k == key) {
1337 /* Ignore server-generated repeats. */
1338 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
1339 return;
1340 *k = *--end;
1341 }
1342 }
1343 keyboard->keys.size = (void *) end - keyboard->keys.data;
1344 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
1345 k = wl_array_add(&keyboard->keys, sizeof *k);
1346 *k = key;
1347 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001348
1349 if (grab == &keyboard->default_grab ||
1350 grab == &keyboard->input_method_grab) {
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001351 weston_compositor_run_key_binding(compositor, keyboard, time,
1352 key, state);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001353 grab = keyboard->grab;
1354 }
1355
1356 grab->interface->key(grab, time, key, state);
1357
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001358 if (keyboard->pending_keymap &&
Pekka Paalanen86b53962014-11-19 13:43:32 +02001359 keyboard->keys.size == 0)
Rui Matos65196bc2013-10-10 19:44:19 +02001360 update_keymap(seat);
1361
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001362 if (update_state == STATE_UPDATE_AUTOMATIC) {
1363 update_modifier_state(seat,
1364 wl_display_get_serial(compositor->wl_display),
1365 key,
1366 state);
1367 }
Giulio Camuffob6ddf6c2015-02-06 19:06:54 +02001368
1369 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
1370 keyboard->grab_serial =
1371 wl_display_get_serial(compositor->wl_display);
1372 keyboard->grab_time = time;
1373 keyboard->grab_key = key;
1374 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001375}
1376
1377WL_EXPORT void
1378notify_pointer_focus(struct weston_seat *seat, struct weston_output *output,
1379 wl_fixed_t x, wl_fixed_t y)
1380{
Derek Foreman1281a362015-07-31 16:55:32 -05001381 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1382
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001383 if (output) {
Derek Foreman1281a362015-07-31 16:55:32 -05001384 weston_pointer_move(pointer, x, y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001385 } else {
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001386 /* FIXME: We should call weston_pointer_set_focus(seat,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001387 * NULL) here, but somehow that breaks re-entry... */
1388 }
1389}
1390
1391static void
1392destroy_device_saved_kbd_focus(struct wl_listener *listener, void *data)
1393{
1394 struct weston_seat *ws;
1395
1396 ws = container_of(listener, struct weston_seat,
1397 saved_kbd_focus_listener);
1398
1399 ws->saved_kbd_focus = NULL;
1400}
1401
1402WL_EXPORT void
1403notify_keyboard_focus_in(struct weston_seat *seat, struct wl_array *keys,
1404 enum weston_key_state_update update_state)
1405{
1406 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001407 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -04001408 struct weston_surface *surface;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001409 uint32_t *k, serial;
1410
1411 serial = wl_display_next_serial(compositor->wl_display);
1412 wl_array_copy(&keyboard->keys, keys);
1413 wl_array_for_each(k, &keyboard->keys) {
1414 weston_compositor_idle_inhibit(compositor);
1415 if (update_state == STATE_UPDATE_AUTOMATIC)
1416 update_modifier_state(seat, serial, *k,
1417 WL_KEYBOARD_KEY_STATE_PRESSED);
1418 }
1419
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001420 surface = seat->saved_kbd_focus;
1421
1422 if (surface) {
1423 wl_list_remove(&seat->saved_kbd_focus_listener.link);
1424 weston_keyboard_set_focus(keyboard, surface);
1425 seat->saved_kbd_focus = NULL;
1426 }
1427}
1428
1429WL_EXPORT void
1430notify_keyboard_focus_out(struct weston_seat *seat)
1431{
1432 struct weston_compositor *compositor = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001433 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
1434 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001435 uint32_t *k, serial;
1436
1437 serial = wl_display_next_serial(compositor->wl_display);
1438 wl_array_for_each(k, &keyboard->keys) {
1439 weston_compositor_idle_release(compositor);
1440 update_modifier_state(seat, serial, *k,
1441 WL_KEYBOARD_KEY_STATE_RELEASED);
1442 }
1443
1444 seat->modifier_state = 0;
1445
1446 if (keyboard->focus) {
1447 seat->saved_kbd_focus = keyboard->focus;
1448 seat->saved_kbd_focus_listener.notify =
1449 destroy_device_saved_kbd_focus;
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05001450 wl_signal_add(&keyboard->focus->destroy_signal,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001451 &seat->saved_kbd_focus_listener);
1452 }
1453
1454 weston_keyboard_set_focus(keyboard, NULL);
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02001455 weston_keyboard_cancel_grab(keyboard);
Derek Foreman1281a362015-07-31 16:55:32 -05001456 if (pointer)
1457 weston_pointer_cancel_grab(pointer);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001458}
1459
Michael Fua2bb7912013-07-23 15:51:06 +08001460WL_EXPORT void
Derek Foreman4c93c082015-04-30 16:45:41 -05001461weston_touch_set_focus(struct weston_touch *touch, struct weston_view *view)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001462{
Neil Roberts96d790e2013-09-19 17:32:00 +01001463 struct wl_list *focus_resource_list;
1464
Derek Foreman4c93c082015-04-30 16:45:41 -05001465 focus_resource_list = &touch->focus_resource_list;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001466
Derek Foreman4c93c082015-04-30 16:45:41 -05001467 if (view && touch->focus &&
1468 touch->focus->surface == view->surface) {
1469 touch->focus = view;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001470 return;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001471 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001472
Derek Foreman4c93c082015-04-30 16:45:41 -05001473 wl_list_remove(&touch->focus_resource_listener.link);
1474 wl_list_init(&touch->focus_resource_listener.link);
1475 wl_list_remove(&touch->focus_view_listener.link);
1476 wl_list_init(&touch->focus_view_listener.link);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001477
Neil Roberts96d790e2013-09-19 17:32:00 +01001478 if (!wl_list_empty(focus_resource_list)) {
Derek Foreman4c93c082015-04-30 16:45:41 -05001479 move_resources(&touch->resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01001480 focus_resource_list);
1481 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001482
Jason Ekstranda7af7042013-10-12 22:38:11 -05001483 if (view) {
Derek Foreman362656b2014-09-04 10:23:05 -05001484 struct wl_client *surface_client;
1485
1486 if (!view->surface->resource) {
Derek Foreman4c93c082015-04-30 16:45:41 -05001487 touch->focus = NULL;
Derek Foreman362656b2014-09-04 10:23:05 -05001488 return;
1489 }
1490
1491 surface_client = wl_resource_get_client(view->surface->resource);
Neil Roberts96d790e2013-09-19 17:32:00 +01001492 move_resources_for_client(focus_resource_list,
Derek Foreman4c93c082015-04-30 16:45:41 -05001493 &touch->resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01001494 surface_client);
Giulio Camuffo576fe2a2013-11-20 18:00:24 +01001495 wl_resource_add_destroy_listener(view->surface->resource,
Derek Foreman4c93c082015-04-30 16:45:41 -05001496 &touch->focus_resource_listener);
1497 wl_signal_add(&view->destroy_signal, &touch->focus_view_listener);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001498 }
Derek Foreman4c93c082015-04-30 16:45:41 -05001499 touch->focus = view;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001500}
1501
1502/**
1503 * notify_touch - emulates button touches and notifies surfaces accordingly.
1504 *
1505 * It assumes always the correct cycle sequence until it gets here: touch_down
1506 * → touch_update → ... → touch_update → touch_end. The driver is responsible
1507 * for sending along such order.
1508 *
1509 */
1510WL_EXPORT void
1511notify_touch(struct weston_seat *seat, uint32_t time, int touch_id,
1512 wl_fixed_t x, wl_fixed_t y, int touch_type)
1513{
1514 struct weston_compositor *ec = seat->compositor;
Derek Foreman1281a362015-07-31 16:55:32 -05001515 struct weston_touch *touch = weston_seat_get_touch(seat);
Kristian Høgsberge329f362013-05-06 22:19:57 -04001516 struct weston_touch_grab *grab = touch->grab;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001517 struct weston_view *ev;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001518 wl_fixed_t sx, sy;
1519
1520 /* Update grab's global coordinates. */
Neil Roberts306fe082013-10-03 16:43:06 +01001521 if (touch_id == touch->grab_touch_id && touch_type != WL_TOUCH_UP) {
1522 touch->grab_x = x;
1523 touch->grab_y = y;
1524 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001525
1526 switch (touch_type) {
1527 case WL_TOUCH_DOWN:
1528 weston_compositor_idle_inhibit(ec);
1529
Jonas Ådahl9484b692013-12-02 22:05:03 +01001530 touch->num_tp++;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001531
Jason Ekstranda7af7042013-10-12 22:38:11 -05001532 /* the first finger down picks the view, and all further go
1533 * to that view for the remainder of the touch session i.e.
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001534 * until all touch points are up again. */
Jonas Ådahl9484b692013-12-02 22:05:03 +01001535 if (touch->num_tp == 1) {
Jason Ekstranda7af7042013-10-12 22:38:11 -05001536 ev = weston_compositor_pick_view(ec, x, y, &sx, &sy);
Derek Foreman4c93c082015-04-30 16:45:41 -05001537 weston_touch_set_focus(touch, ev);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001538 } else if (touch->focus) {
Jason Ekstranda7af7042013-10-12 22:38:11 -05001539 ev = touch->focus;
1540 weston_view_from_global_fixed(ev, x, y, &sx, &sy);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001541 } else {
1542 /* Unexpected condition: We have non-initial touch but
1543 * there is no focused surface.
1544 */
1545 weston_log("touch event received with %d points down"
Jonas Ådahl9484b692013-12-02 22:05:03 +01001546 "but no surface focused\n", touch->num_tp);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001547 return;
1548 }
1549
Derek Foreman99a6a2d2015-07-15 13:00:43 -05001550 weston_compositor_run_touch_binding(ec, touch,
Kristian Høgsbergc8964012014-02-05 14:25:18 -08001551 time, touch_type);
1552
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001553 grab->interface->down(grab, time, touch_id, sx, sy);
Jonas Ådahl9484b692013-12-02 22:05:03 +01001554 if (touch->num_tp == 1) {
Rusty Lynchf1407ff2013-08-08 21:13:57 -07001555 touch->grab_serial =
1556 wl_display_get_serial(ec->wl_display);
Neil Roberts306fe082013-10-03 16:43:06 +01001557 touch->grab_touch_id = touch_id;
Rusty Lynchf1407ff2013-08-08 21:13:57 -07001558 touch->grab_time = time;
1559 touch->grab_x = x;
1560 touch->grab_y = y;
1561 }
1562
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001563 break;
1564 case WL_TOUCH_MOTION:
Jason Ekstranda7af7042013-10-12 22:38:11 -05001565 ev = touch->focus;
1566 if (!ev)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001567 break;
1568
Jason Ekstranda7af7042013-10-12 22:38:11 -05001569 weston_view_from_global_fixed(ev, x, y, &sx, &sy);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001570 grab->interface->motion(grab, time, touch_id, sx, sy);
1571 break;
1572 case WL_TOUCH_UP:
Kristian Høgsberga30e29a2014-01-08 22:29:20 -08001573 if (touch->num_tp == 0) {
1574 /* This can happen if we start out with one or
1575 * more fingers on the touch screen, in which
1576 * case we didn't get the corresponding down
1577 * event. */
1578 weston_log("unmatched touch up event\n");
1579 break;
1580 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001581 weston_compositor_idle_release(ec);
Jonas Ådahl9484b692013-12-02 22:05:03 +01001582 touch->num_tp--;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001583
1584 grab->interface->up(grab, time, touch_id);
Jonas Ådahl9484b692013-12-02 22:05:03 +01001585 if (touch->num_tp == 0)
Derek Foreman4c93c082015-04-30 16:45:41 -05001586 weston_touch_set_focus(touch, NULL);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001587 break;
1588 }
1589}
1590
Jonas Ådahl1679f232014-04-12 09:39:51 +02001591WL_EXPORT void
1592notify_touch_frame(struct weston_seat *seat)
1593{
Derek Foreman1281a362015-07-31 16:55:32 -05001594 struct weston_touch *touch = weston_seat_get_touch(seat);
Jonas Ådahl1679f232014-04-12 09:39:51 +02001595 struct weston_touch_grab *grab = touch->grab;
1596
1597 grab->interface->frame(grab);
1598}
1599
Pekka Paalanen8274d902014-08-06 19:36:51 +03001600static int
1601pointer_cursor_surface_get_label(struct weston_surface *surface,
1602 char *buf, size_t len)
1603{
1604 return snprintf(buf, len, "cursor");
1605}
1606
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001607static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001608pointer_cursor_surface_configure(struct weston_surface *es,
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06001609 int32_t dx, int32_t dy)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001610{
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001611 struct weston_pointer *pointer = es->configure_private;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001612 int x, y;
1613
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06001614 if (es->width == 0)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001615 return;
1616
Jason Ekstranda7af7042013-10-12 22:38:11 -05001617 assert(es == pointer->sprite->surface);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001618
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001619 pointer->hotspot_x -= dx;
1620 pointer->hotspot_y -= dy;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001621
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001622 x = wl_fixed_to_int(pointer->x) - pointer->hotspot_x;
1623 y = wl_fixed_to_int(pointer->y) - pointer->hotspot_y;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001624
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06001625 weston_view_set_position(pointer->sprite, x, y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001626
1627 empty_region(&es->pending.input);
Ander Conselvan de Oliveira23900f72014-01-31 16:07:51 +02001628 empty_region(&es->input);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001629
1630 if (!weston_surface_is_mapped(es)) {
Giulio Camuffo412e6a52014-07-09 22:12:56 +03001631 weston_layer_entry_insert(&es->compositor->cursor_layer.view_list,
1632 &pointer->sprite->layer_link);
Jason Ekstranda7af7042013-10-12 22:38:11 -05001633 weston_view_update_transform(pointer->sprite);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001634 }
1635}
1636
1637static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001638pointer_set_cursor(struct wl_client *client, struct wl_resource *resource,
1639 uint32_t serial, struct wl_resource *surface_resource,
1640 int32_t x, int32_t y)
1641{
Jason Ekstrand44a38632013-06-14 10:08:00 -05001642 struct weston_pointer *pointer = wl_resource_get_user_data(resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001643 struct weston_surface *surface = NULL;
1644
1645 if (surface_resource)
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05001646 surface = wl_resource_get_user_data(surface_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001647
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001648 if (pointer->focus == NULL)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001649 return;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001650 /* pointer->focus->surface->resource can be NULL. Surfaces like the
Giulio Camuffo1fd4b012013-06-20 18:13:07 +02001651 black_surface used in shell.c for fullscreen don't have
1652 a resource, but can still have focus */
Jason Ekstranda7af7042013-10-12 22:38:11 -05001653 if (pointer->focus->surface->resource == NULL)
Giulio Camuffo1fd4b012013-06-20 18:13:07 +02001654 return;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001655 if (wl_resource_get_client(pointer->focus->surface->resource) != client)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001656 return;
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001657 if (pointer->focus_serial - serial > UINT32_MAX / 2)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001658 return;
1659
Derek Foreman4e53c532015-03-23 10:55:32 -05001660 if (!surface) {
1661 if (pointer->sprite)
1662 pointer_unmap_sprite(pointer);
1663 return;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001664 }
1665
Jonas Ådahlb4070242015-03-18 15:08:03 +08001666 if (pointer->sprite && pointer->sprite->surface == surface &&
1667 pointer->hotspot_x == x && pointer->hotspot_y == y)
1668 return;
1669
Derek Foreman4e53c532015-03-23 10:55:32 -05001670 if (!pointer->sprite || pointer->sprite->surface != surface) {
1671 if (weston_surface_set_role(surface, "wl_pointer-cursor",
1672 resource,
1673 WL_POINTER_ERROR_ROLE) < 0)
1674 return;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001675
Derek Foreman4e53c532015-03-23 10:55:32 -05001676 if (pointer->sprite)
1677 pointer_unmap_sprite(pointer);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001678
Derek Foreman4e53c532015-03-23 10:55:32 -05001679 wl_signal_add(&surface->destroy_signal,
1680 &pointer->sprite_destroy_listener);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001681
Derek Foreman4e53c532015-03-23 10:55:32 -05001682 surface->configure = pointer_cursor_surface_configure;
1683 surface->configure_private = pointer;
1684 weston_surface_set_label_func(surface,
1685 pointer_cursor_surface_get_label);
1686 pointer->sprite = weston_view_create(surface);
1687 }
1688
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001689 pointer->hotspot_x = x;
1690 pointer->hotspot_y = y;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001691
Jonas Ådahl16fe4dc2014-09-08 19:33:41 +02001692 if (surface->buffer_ref.buffer) {
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06001693 pointer_cursor_surface_configure(surface, 0, 0);
Jonas Ådahl16fe4dc2014-09-08 19:33:41 +02001694 weston_view_schedule_repaint(pointer->sprite);
1695 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001696}
1697
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01001698static void
1699pointer_release(struct wl_client *client, struct wl_resource *resource)
1700{
1701 wl_resource_destroy(resource);
1702}
1703
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001704static const struct wl_pointer_interface pointer_interface = {
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01001705 pointer_set_cursor,
1706 pointer_release
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001707};
1708
1709static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001710seat_get_pointer(struct wl_client *client, struct wl_resource *resource,
1711 uint32_t id)
1712{
Jason Ekstrand44a38632013-06-14 10:08:00 -05001713 struct weston_seat *seat = wl_resource_get_user_data(resource);
Derek Foreman1281a362015-07-31 16:55:32 -05001714 /* We use the pointer_state directly, which means we'll
1715 * give a wl_pointer if the seat has ever had one - even though
1716 * the spec explicitly states that this request only takes effect
1717 * if the seat has the pointer capability.
1718 *
1719 * This prevents a race between the compositor sending new
1720 * capabilities and the client trying to use the old ones.
1721 */
1722 struct weston_pointer *pointer = seat->pointer_state;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001723 struct wl_resource *cr;
1724
Derek Foreman1281a362015-07-31 16:55:32 -05001725 if (!pointer)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001726 return;
1727
Jason Ekstranda85118c2013-06-27 20:17:02 -05001728 cr = wl_resource_create(client, &wl_pointer_interface,
1729 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07001730 if (cr == NULL) {
1731 wl_client_post_no_memory(client);
1732 return;
1733 }
1734
Neil Roberts96d790e2013-09-19 17:32:00 +01001735 /* May be moved to focused list later by either
1736 * weston_pointer_set_focus or directly if this client is already
1737 * focused */
Derek Foreman1281a362015-07-31 16:55:32 -05001738 wl_list_insert(&pointer->resource_list, wl_resource_get_link(cr));
1739 wl_resource_set_implementation(cr, &pointer_interface, pointer,
Jason Ekstranda85118c2013-06-27 20:17:02 -05001740 unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001741
Derek Foreman1281a362015-07-31 16:55:32 -05001742 if (pointer->focus && pointer->focus->surface->resource &&
1743 wl_resource_get_client(pointer->focus->surface->resource) == client) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001744 wl_fixed_t sx, sy;
1745
Derek Foreman1281a362015-07-31 16:55:32 -05001746 weston_view_from_global_fixed(pointer->focus,
1747 pointer->x,
1748 pointer->y,
Jason Ekstranda7af7042013-10-12 22:38:11 -05001749 &sx, &sy);
Neil Roberts96d790e2013-09-19 17:32:00 +01001750
1751 wl_list_remove(wl_resource_get_link(cr));
Derek Foreman1281a362015-07-31 16:55:32 -05001752 wl_list_insert(&pointer->focus_resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01001753 wl_resource_get_link(cr));
1754 wl_pointer_send_enter(cr,
Derek Foreman1281a362015-07-31 16:55:32 -05001755 pointer->focus_serial,
1756 pointer->focus->surface->resource,
Neil Roberts96d790e2013-09-19 17:32:00 +01001757 sx, sy);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001758 }
1759}
1760
1761static void
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01001762keyboard_release(struct wl_client *client, struct wl_resource *resource)
1763{
1764 wl_resource_destroy(resource);
1765}
1766
1767static const struct wl_keyboard_interface keyboard_interface = {
1768 keyboard_release
1769};
1770
Derek Foreman280e7dd2014-10-03 13:13:42 -05001771static bool
Neil Roberts96d790e2013-09-19 17:32:00 +01001772should_send_modifiers_to_client(struct weston_seat *seat,
1773 struct wl_client *client)
1774{
Derek Foreman1281a362015-07-31 16:55:32 -05001775 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
1776 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1777
1778 if (keyboard &&
1779 keyboard->focus &&
1780 keyboard->focus->resource &&
1781 wl_resource_get_client(keyboard->focus->resource) == client)
Derek Foreman280e7dd2014-10-03 13:13:42 -05001782 return true;
Neil Roberts96d790e2013-09-19 17:32:00 +01001783
Derek Foreman1281a362015-07-31 16:55:32 -05001784 if (pointer &&
1785 pointer->focus &&
1786 pointer->focus->surface->resource &&
1787 wl_resource_get_client(pointer->focus->surface->resource) == client)
Derek Foreman280e7dd2014-10-03 13:13:42 -05001788 return true;
Neil Roberts96d790e2013-09-19 17:32:00 +01001789
Derek Foreman280e7dd2014-10-03 13:13:42 -05001790 return false;
Neil Roberts96d790e2013-09-19 17:32:00 +01001791}
1792
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01001793static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001794seat_get_keyboard(struct wl_client *client, struct wl_resource *resource,
1795 uint32_t id)
1796{
Jason Ekstrand44a38632013-06-14 10:08:00 -05001797 struct weston_seat *seat = wl_resource_get_user_data(resource);
Derek Foreman1281a362015-07-31 16:55:32 -05001798 /* We use the keyboard_state directly, which means we'll
1799 * give a wl_keyboard if the seat has ever had one - even though
1800 * the spec explicitly states that this request only takes effect
1801 * if the seat has the keyboard capability.
1802 *
1803 * This prevents a race between the compositor sending new
1804 * capabilities and the client trying to use the old ones.
1805 */
1806 struct weston_keyboard *keyboard = seat->keyboard_state;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001807 struct wl_resource *cr;
1808
Derek Foreman345c9f32015-06-03 15:53:28 -05001809 if (!keyboard)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001810 return;
1811
Jason Ekstranda85118c2013-06-27 20:17:02 -05001812 cr = wl_resource_create(client, &wl_keyboard_interface,
1813 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07001814 if (cr == NULL) {
1815 wl_client_post_no_memory(client);
1816 return;
1817 }
1818
Neil Roberts96d790e2013-09-19 17:32:00 +01001819 /* May be moved to focused list later by either
1820 * weston_keyboard_set_focus or directly if this client is already
1821 * focused */
Derek Foreman345c9f32015-06-03 15:53:28 -05001822 wl_list_insert(&keyboard->resource_list, wl_resource_get_link(cr));
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01001823 wl_resource_set_implementation(cr, &keyboard_interface,
1824 seat, unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001825
Jonny Lamb66a41a02014-08-12 14:58:25 +02001826 if (wl_resource_get_version(cr) >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) {
1827 wl_keyboard_send_repeat_info(cr,
1828 seat->compositor->kb_repeat_rate,
1829 seat->compositor->kb_repeat_delay);
1830 }
Jasper St. Pierred8c6aeb2014-08-04 13:43:24 -04001831
Matt Roper01a92732013-06-24 16:52:44 +01001832 if (seat->compositor->use_xkbcommon) {
1833 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
Jonas Ådahl7395ea02013-12-03 09:14:26 +01001834 keyboard->xkb_info->keymap_fd,
1835 keyboard->xkb_info->keymap_size);
Matt Roper01a92732013-06-24 16:52:44 +01001836 } else {
1837 int null_fd = open("/dev/null", O_RDONLY);
1838 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP,
1839 null_fd,
1840 0);
1841 close(null_fd);
1842 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001843
Neil Roberts96d790e2013-09-19 17:32:00 +01001844 if (should_send_modifiers_to_client(seat, client)) {
Derek Foreman345c9f32015-06-03 15:53:28 -05001845 send_modifiers_to_resource(keyboard,
Neil Roberts96d790e2013-09-19 17:32:00 +01001846 cr,
Derek Foreman345c9f32015-06-03 15:53:28 -05001847 keyboard->focus_serial);
Neil Roberts96d790e2013-09-19 17:32:00 +01001848 }
1849
Derek Foreman345c9f32015-06-03 15:53:28 -05001850 if (keyboard->focus && keyboard->focus->resource &&
1851 wl_resource_get_client(keyboard->focus->resource) == client) {
Neil Roberts96d790e2013-09-19 17:32:00 +01001852 struct weston_surface *surface =
Derek Foreman345c9f32015-06-03 15:53:28 -05001853 (struct weston_surface *)keyboard->focus;
Neil Roberts96d790e2013-09-19 17:32:00 +01001854
1855 wl_list_remove(wl_resource_get_link(cr));
Derek Foreman345c9f32015-06-03 15:53:28 -05001856 wl_list_insert(&keyboard->focus_resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01001857 wl_resource_get_link(cr));
1858 wl_keyboard_send_enter(cr,
Derek Foreman345c9f32015-06-03 15:53:28 -05001859 keyboard->focus_serial,
Neil Roberts96d790e2013-09-19 17:32:00 +01001860 surface->resource,
Derek Foreman345c9f32015-06-03 15:53:28 -05001861 &keyboard->keys);
Neil Roberts96d790e2013-09-19 17:32:00 +01001862
1863 /* If this is the first keyboard resource for this
1864 * client... */
Derek Foreman345c9f32015-06-03 15:53:28 -05001865 if (keyboard->focus_resource_list.prev ==
Neil Roberts96d790e2013-09-19 17:32:00 +01001866 wl_resource_get_link(cr))
1867 wl_data_device_set_keyboard_focus(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001868 }
1869}
1870
1871static void
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01001872touch_release(struct wl_client *client, struct wl_resource *resource)
1873{
1874 wl_resource_destroy(resource);
1875}
1876
1877static const struct wl_touch_interface touch_interface = {
1878 touch_release
1879};
1880
1881static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001882seat_get_touch(struct wl_client *client, struct wl_resource *resource,
1883 uint32_t id)
1884{
Jason Ekstrand44a38632013-06-14 10:08:00 -05001885 struct weston_seat *seat = wl_resource_get_user_data(resource);
Derek Foreman1281a362015-07-31 16:55:32 -05001886 /* We use the touch_state directly, which means we'll
1887 * give a wl_touch if the seat has ever had one - even though
1888 * the spec explicitly states that this request only takes effect
1889 * if the seat has the touch capability.
1890 *
1891 * This prevents a race between the compositor sending new
1892 * capabilities and the client trying to use the old ones.
1893 */
1894 struct weston_touch *touch = seat->touch_state;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001895 struct wl_resource *cr;
1896
Derek Foreman1281a362015-07-31 16:55:32 -05001897 if (!touch)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001898 return;
1899
Jason Ekstranda85118c2013-06-27 20:17:02 -05001900 cr = wl_resource_create(client, &wl_touch_interface,
1901 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07001902 if (cr == NULL) {
1903 wl_client_post_no_memory(client);
1904 return;
1905 }
1906
Derek Foreman1281a362015-07-31 16:55:32 -05001907 if (touch->focus &&
1908 wl_resource_get_client(touch->focus->surface->resource) == client) {
1909 wl_list_insert(&touch->resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01001910 wl_resource_get_link(cr));
1911 } else {
Derek Foreman1281a362015-07-31 16:55:32 -05001912 wl_list_insert(&touch->focus_resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01001913 wl_resource_get_link(cr));
1914 }
Kristian Høgsberg69e25fc2013-08-13 20:11:02 +01001915 wl_resource_set_implementation(cr, &touch_interface,
1916 seat, unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001917}
1918
1919static const struct wl_seat_interface seat_interface = {
1920 seat_get_pointer,
1921 seat_get_keyboard,
1922 seat_get_touch,
1923};
1924
1925static void
1926bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
1927{
Kristian Høgsberge3148752013-05-06 23:19:49 -04001928 struct weston_seat *seat = data;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001929 struct wl_resource *resource;
1930 enum wl_seat_capability caps = 0;
1931
Jason Ekstranda85118c2013-06-27 20:17:02 -05001932 resource = wl_resource_create(client,
Jonny Lamb66a41a02014-08-12 14:58:25 +02001933 &wl_seat_interface, MIN(version, 4), id);
Jason Ekstrand44a38632013-06-14 10:08:00 -05001934 wl_list_insert(&seat->base_resource_list, wl_resource_get_link(resource));
Jason Ekstranda85118c2013-06-27 20:17:02 -05001935 wl_resource_set_implementation(resource, &seat_interface, data,
1936 unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001937
Derek Foreman1281a362015-07-31 16:55:32 -05001938 if (weston_seat_get_pointer(seat))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001939 caps |= WL_SEAT_CAPABILITY_POINTER;
Derek Foreman1281a362015-07-31 16:55:32 -05001940 if (weston_seat_get_keyboard(seat))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001941 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
Derek Foreman1281a362015-07-31 16:55:32 -05001942 if (weston_seat_get_touch(seat))
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001943 caps |= WL_SEAT_CAPABILITY_TOUCH;
1944
1945 wl_seat_send_capabilities(resource, caps);
Jasper St. Pierre0013a292014-08-07 16:43:11 -04001946 if (version >= WL_SEAT_NAME_SINCE_VERSION)
Rob Bradforde445ae62013-05-31 18:09:51 +01001947 wl_seat_send_name(resource, seat->seat_name);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001948}
1949
Rob Bradford382ff462013-06-24 16:52:45 +01001950#ifdef ENABLE_XKBCOMMON
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001951int
1952weston_compositor_xkb_init(struct weston_compositor *ec,
1953 struct xkb_rule_names *names)
1954{
Rob Bradford382ff462013-06-24 16:52:45 +01001955 ec->use_xkbcommon = 1;
Matt Roper01a92732013-06-24 16:52:44 +01001956
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001957 if (ec->xkb_context == NULL) {
1958 ec->xkb_context = xkb_context_new(0);
1959 if (ec->xkb_context == NULL) {
1960 weston_log("failed to create XKB context\n");
1961 return -1;
1962 }
1963 }
1964
1965 if (names)
1966 ec->xkb_names = *names;
1967 if (!ec->xkb_names.rules)
1968 ec->xkb_names.rules = strdup("evdev");
1969 if (!ec->xkb_names.model)
1970 ec->xkb_names.model = strdup("pc105");
1971 if (!ec->xkb_names.layout)
1972 ec->xkb_names.layout = strdup("us");
1973
1974 return 0;
1975}
1976
Stefan Schmidtfda26522013-09-17 10:54:09 +01001977static void
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00001978weston_xkb_info_destroy(struct weston_xkb_info *xkb_info)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001979{
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00001980 if (--xkb_info->ref_count > 0)
1981 return;
1982
Ran Benitac9c74152014-08-19 23:59:52 +03001983 xkb_keymap_unref(xkb_info->keymap);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001984
1985 if (xkb_info->keymap_area)
1986 munmap(xkb_info->keymap_area, xkb_info->keymap_size);
1987 if (xkb_info->keymap_fd >= 0)
1988 close(xkb_info->keymap_fd);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00001989 free(xkb_info);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001990}
1991
1992void
1993weston_compositor_xkb_destroy(struct weston_compositor *ec)
1994{
Matt Roper01a92732013-06-24 16:52:44 +01001995 /*
1996 * If we're operating in raw keyboard mode, we never initialized
1997 * libxkbcommon so there's no cleanup to do either.
1998 */
1999 if (!ec->use_xkbcommon)
2000 return;
2001
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002002 free((char *) ec->xkb_names.rules);
2003 free((char *) ec->xkb_names.model);
2004 free((char *) ec->xkb_names.layout);
2005 free((char *) ec->xkb_names.variant);
2006 free((char *) ec->xkb_names.options);
Stefan Schmidtfda26522013-09-17 10:54:09 +01002007
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002008 if (ec->xkb_info)
2009 weston_xkb_info_destroy(ec->xkb_info);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002010 xkb_context_unref(ec->xkb_context);
2011}
2012
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002013static struct weston_xkb_info *
2014weston_xkb_info_create(struct xkb_keymap *keymap)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002015{
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002016 struct weston_xkb_info *xkb_info = zalloc(sizeof *xkb_info);
2017 if (xkb_info == NULL)
2018 return NULL;
2019
Ran Benita2e1968f2014-08-19 23:59:51 +03002020 xkb_info->keymap = xkb_keymap_ref(keymap);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002021 xkb_info->ref_count = 1;
2022
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002023 char *keymap_str;
2024
Ran Benita2e1968f2014-08-19 23:59:51 +03002025 xkb_info->shift_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2026 XKB_MOD_NAME_SHIFT);
2027 xkb_info->caps_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2028 XKB_MOD_NAME_CAPS);
2029 xkb_info->ctrl_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2030 XKB_MOD_NAME_CTRL);
2031 xkb_info->alt_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2032 XKB_MOD_NAME_ALT);
2033 xkb_info->mod2_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2034 "Mod2");
2035 xkb_info->mod3_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2036 "Mod3");
2037 xkb_info->super_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2038 XKB_MOD_NAME_LOGO);
2039 xkb_info->mod5_mod = xkb_keymap_mod_get_index(xkb_info->keymap,
2040 "Mod5");
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002041
Ran Benita2e1968f2014-08-19 23:59:51 +03002042 xkb_info->num_led = xkb_keymap_led_get_index(xkb_info->keymap,
2043 XKB_LED_NAME_NUM);
2044 xkb_info->caps_led = xkb_keymap_led_get_index(xkb_info->keymap,
2045 XKB_LED_NAME_CAPS);
2046 xkb_info->scroll_led = xkb_keymap_led_get_index(xkb_info->keymap,
2047 XKB_LED_NAME_SCROLL);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002048
Ran Benita2e1968f2014-08-19 23:59:51 +03002049 keymap_str = xkb_keymap_get_as_string(xkb_info->keymap,
2050 XKB_KEYMAP_FORMAT_TEXT_V1);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002051 if (keymap_str == NULL) {
2052 weston_log("failed to get string version of keymap\n");
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002053 goto err_keymap;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002054 }
2055 xkb_info->keymap_size = strlen(keymap_str) + 1;
2056
2057 xkb_info->keymap_fd = os_create_anonymous_file(xkb_info->keymap_size);
2058 if (xkb_info->keymap_fd < 0) {
2059 weston_log("creating a keymap file for %lu bytes failed: %m\n",
2060 (unsigned long) xkb_info->keymap_size);
2061 goto err_keymap_str;
2062 }
2063
2064 xkb_info->keymap_area = mmap(NULL, xkb_info->keymap_size,
2065 PROT_READ | PROT_WRITE,
2066 MAP_SHARED, xkb_info->keymap_fd, 0);
2067 if (xkb_info->keymap_area == MAP_FAILED) {
2068 weston_log("failed to mmap() %lu bytes\n",
2069 (unsigned long) xkb_info->keymap_size);
2070 goto err_dev_zero;
2071 }
2072 strcpy(xkb_info->keymap_area, keymap_str);
2073 free(keymap_str);
2074
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002075 return xkb_info;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002076
2077err_dev_zero:
2078 close(xkb_info->keymap_fd);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002079err_keymap_str:
2080 free(keymap_str);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002081err_keymap:
Ran Benita2e1968f2014-08-19 23:59:51 +03002082 xkb_keymap_unref(xkb_info->keymap);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002083 free(xkb_info);
2084 return NULL;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002085}
2086
2087static int
2088weston_compositor_build_global_keymap(struct weston_compositor *ec)
2089{
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002090 struct xkb_keymap *keymap;
2091
2092 if (ec->xkb_info != NULL)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002093 return 0;
2094
Ran Benita2e1968f2014-08-19 23:59:51 +03002095 keymap = xkb_keymap_new_from_names(ec->xkb_context,
2096 &ec->xkb_names,
2097 0);
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002098 if (keymap == NULL) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002099 weston_log("failed to compile global XKB keymap\n");
2100 weston_log(" tried rules %s, model %s, layout %s, variant %s, "
2101 "options %s\n",
2102 ec->xkb_names.rules, ec->xkb_names.model,
2103 ec->xkb_names.layout, ec->xkb_names.variant,
2104 ec->xkb_names.options);
2105 return -1;
2106 }
2107
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +00002108 ec->xkb_info = weston_xkb_info_create(keymap);
Rui Matos73d93952013-10-24 19:28:41 +02002109 xkb_keymap_unref(keymap);
Stefan Schmidtfda26522013-09-17 10:54:09 +01002110 if (ec->xkb_info == NULL)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002111 return -1;
2112
2113 return 0;
2114}
Rob Bradford382ff462013-06-24 16:52:45 +01002115#else
2116int
2117weston_compositor_xkb_init(struct weston_compositor *ec,
2118 struct xkb_rule_names *names)
2119{
2120 return 0;
2121}
2122
2123void
2124weston_compositor_xkb_destroy(struct weston_compositor *ec)
2125{
2126}
2127#endif
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002128
Rui Matos65196bc2013-10-10 19:44:19 +02002129WL_EXPORT void
2130weston_seat_update_keymap(struct weston_seat *seat, struct xkb_keymap *keymap)
2131{
Derek Foreman1281a362015-07-31 16:55:32 -05002132 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
2133
2134 if (!keyboard || !keymap)
Rui Matos65196bc2013-10-10 19:44:19 +02002135 return;
2136
2137#ifdef ENABLE_XKBCOMMON
2138 if (!seat->compositor->use_xkbcommon)
2139 return;
2140
Derek Foreman1281a362015-07-31 16:55:32 -05002141 xkb_keymap_unref(keyboard->pending_keymap);
2142 keyboard->pending_keymap = xkb_keymap_ref(keymap);
Rui Matos65196bc2013-10-10 19:44:19 +02002143
Derek Foreman1281a362015-07-31 16:55:32 -05002144 if (keyboard->keys.size == 0)
Rui Matos65196bc2013-10-10 19:44:19 +02002145 update_keymap(seat);
2146#endif
2147}
2148
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002149WL_EXPORT int
2150weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap)
2151{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002152 struct weston_keyboard *keyboard;
2153
Derek Foreman1281a362015-07-31 16:55:32 -05002154 if (seat->keyboard_state) {
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002155 seat->keyboard_device_count += 1;
2156 if (seat->keyboard_device_count == 1)
2157 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002158 return 0;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002159 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002160
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002161 keyboard = weston_keyboard_create();
2162 if (keyboard == NULL) {
2163 weston_log("failed to allocate weston keyboard struct\n");
2164 return -1;
2165 }
2166
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002167#ifdef ENABLE_XKBCOMMON
2168 if (seat->compositor->use_xkbcommon) {
2169 if (keymap != NULL) {
2170 keyboard->xkb_info = weston_xkb_info_create(keymap);
2171 if (keyboard->xkb_info == NULL)
Ander Conselvan de Oliveira4d363cf2014-01-31 17:35:45 +02002172 goto err;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002173 } else {
2174 if (weston_compositor_build_global_keymap(seat->compositor) < 0)
Ander Conselvan de Oliveira4d363cf2014-01-31 17:35:45 +02002175 goto err;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002176 keyboard->xkb_info = seat->compositor->xkb_info;
2177 keyboard->xkb_info->ref_count++;
2178 }
2179
2180 keyboard->xkb_state.state = xkb_state_new(keyboard->xkb_info->keymap);
2181 if (keyboard->xkb_state.state == NULL) {
2182 weston_log("failed to initialise XKB state\n");
Ander Conselvan de Oliveira4d363cf2014-01-31 17:35:45 +02002183 goto err;
Jonas Ådahl7395ea02013-12-03 09:14:26 +01002184 }
2185
2186 keyboard->xkb_state.leds = 0;
2187 }
2188#endif
2189
Derek Foreman1281a362015-07-31 16:55:32 -05002190 seat->keyboard_state = keyboard;
Ander Conselvan de Oliveira4d363cf2014-01-31 17:35:45 +02002191 seat->keyboard_device_count = 1;
2192 keyboard->seat = seat;
2193
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002194 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002195
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002196 return 0;
Ander Conselvan de Oliveira4d363cf2014-01-31 17:35:45 +02002197
2198err:
2199 if (keyboard->xkb_info)
2200 weston_xkb_info_destroy(keyboard->xkb_info);
2201 free(keyboard);
2202
2203 return -1;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002204}
2205
Jonas Ådahl91fed542013-12-03 09:14:27 +01002206static void
2207weston_keyboard_reset_state(struct weston_keyboard *keyboard)
2208{
2209 struct weston_seat *seat = keyboard->seat;
2210 struct xkb_state *state;
2211
2212#ifdef ENABLE_XKBCOMMON
2213 if (seat->compositor->use_xkbcommon) {
2214 state = xkb_state_new(keyboard->xkb_info->keymap);
2215 if (!state) {
2216 weston_log("failed to reset XKB state\n");
2217 return;
2218 }
2219 xkb_state_unref(keyboard->xkb_state.state);
2220 keyboard->xkb_state.state = state;
2221
2222 keyboard->xkb_state.leds = 0;
2223 }
2224#endif
2225
2226 seat->modifier_state = 0;
2227}
2228
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002229WL_EXPORT void
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002230weston_seat_release_keyboard(struct weston_seat *seat)
2231{
2232 seat->keyboard_device_count--;
Derek Foremand621df22014-11-19 11:04:12 -06002233 assert(seat->keyboard_device_count >= 0);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002234 if (seat->keyboard_device_count == 0) {
Derek Foreman1281a362015-07-31 16:55:32 -05002235 weston_keyboard_set_focus(seat->keyboard_state, NULL);
2236 weston_keyboard_cancel_grab(seat->keyboard_state);
2237 weston_keyboard_reset_state(seat->keyboard_state);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002238 seat_send_updated_caps(seat);
2239 }
2240}
2241
2242WL_EXPORT void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002243weston_seat_init_pointer(struct weston_seat *seat)
2244{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002245 struct weston_pointer *pointer;
2246
Derek Foreman1281a362015-07-31 16:55:32 -05002247 if (seat->pointer_state) {
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002248 seat->pointer_device_count += 1;
2249 if (seat->pointer_device_count == 1)
2250 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002251 return;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002252 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002253
Giulio Camuffocdb4d292013-11-14 23:42:53 +01002254 pointer = weston_pointer_create(seat);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002255 if (pointer == NULL)
2256 return;
2257
Derek Foreman1281a362015-07-31 16:55:32 -05002258 seat->pointer_state = pointer;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002259 seat->pointer_device_count = 1;
2260 pointer->seat = seat;
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002261
2262 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002263}
2264
2265WL_EXPORT void
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002266weston_seat_release_pointer(struct weston_seat *seat)
2267{
Derek Foreman1281a362015-07-31 16:55:32 -05002268 struct weston_pointer *pointer = seat->pointer_state;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002269
2270 seat->pointer_device_count--;
2271 if (seat->pointer_device_count == 0) {
Jonas Ådahl630bae82013-10-17 23:04:06 +02002272 weston_pointer_set_focus(pointer, NULL,
2273 wl_fixed_from_int(0),
2274 wl_fixed_from_int(0));
Jonas Ådahl1ea343e2013-10-25 23:18:05 +02002275 weston_pointer_cancel_grab(pointer);
Jonas Ådahl630bae82013-10-17 23:04:06 +02002276
Jonas Ådahla4932742013-10-17 23:04:07 +02002277 if (pointer->sprite)
2278 pointer_unmap_sprite(pointer);
2279
Jonas Ådahl3e12e632013-12-02 22:05:05 +01002280 weston_pointer_reset_state(pointer);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002281 seat_send_updated_caps(seat);
Derek Foremanfd5ca512015-01-07 15:00:25 -06002282
2283 /* seat->pointer is intentionally not destroyed so that
2284 * a newly attached pointer on this seat will retain
2285 * the previous cursor co-ordinates.
2286 */
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002287 }
2288}
2289
2290WL_EXPORT void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002291weston_seat_init_touch(struct weston_seat *seat)
2292{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002293 struct weston_touch *touch;
2294
Derek Foreman1281a362015-07-31 16:55:32 -05002295 if (seat->touch_state) {
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002296 seat->touch_device_count += 1;
2297 if (seat->touch_device_count == 1)
2298 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002299 return;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002300 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002301
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002302 touch = weston_touch_create();
2303 if (touch == NULL)
2304 return;
2305
Derek Foreman1281a362015-07-31 16:55:32 -05002306 seat->touch_state = touch;
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002307 seat->touch_device_count = 1;
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04002308 touch->seat = seat;
2309
2310 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002311}
2312
2313WL_EXPORT void
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002314weston_seat_release_touch(struct weston_seat *seat)
2315{
2316 seat->touch_device_count--;
2317 if (seat->touch_device_count == 0) {
Derek Foreman1281a362015-07-31 16:55:32 -05002318 weston_touch_set_focus(seat->touch_state, NULL);
2319 weston_touch_cancel_grab(seat->touch_state);
2320 weston_touch_reset_state(seat->touch_state);
Jonas Ådahld6e1c342013-10-17 23:04:05 +02002321 seat_send_updated_caps(seat);
2322 }
2323}
2324
2325WL_EXPORT void
Rob Bradford9af5f9e2013-05-31 18:09:50 +01002326weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec,
2327 const char *seat_name)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002328{
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04002329 memset(seat, 0, sizeof *seat);
2330
Kristian Høgsberge3148752013-05-06 23:19:49 -04002331 seat->selection_data_source = NULL;
2332 wl_list_init(&seat->base_resource_list);
2333 wl_signal_init(&seat->selection_signal);
2334 wl_list_init(&seat->drag_resource_list);
Kristian Høgsberge3148752013-05-06 23:19:49 -04002335 wl_signal_init(&seat->destroy_signal);
Jason Ekstranda4ab5422014-04-02 19:53:45 -05002336 wl_signal_init(&seat->updated_caps_signal);
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04002337
Jasper St. Pierred8c6aeb2014-08-04 13:43:24 -04002338 seat->global = wl_global_create(ec->wl_display, &wl_seat_interface, 4,
Kristian Høgsberg919cddb2013-07-08 19:03:57 -04002339 seat, bind_seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002340
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002341 seat->compositor = ec;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002342 seat->modifier_state = 0;
Rob Bradford9af5f9e2013-05-31 18:09:50 +01002343 seat->seat_name = strdup(seat_name);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002344
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002345 wl_list_insert(ec->seat_list.prev, &seat->link);
2346
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002347 clipboard_create(seat);
2348
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002349 wl_signal_emit(&ec->seat_created_signal, seat);
2350}
2351
2352WL_EXPORT void
2353weston_seat_release(struct weston_seat *seat)
2354{
2355 wl_list_remove(&seat->link);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002356
Jonas Ådahl1afb2382014-01-03 19:46:51 +01002357 if (seat->saved_kbd_focus)
2358 wl_list_remove(&seat->saved_kbd_focus_listener.link);
2359
Derek Foreman1281a362015-07-31 16:55:32 -05002360 if (seat->pointer_state)
2361 weston_pointer_destroy(seat->pointer_state);
2362 if (seat->keyboard_state)
2363 weston_keyboard_destroy(seat->keyboard_state);
2364 if (seat->touch_state)
2365 weston_touch_destroy(seat->touch_state);
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04002366
Rob Bradford9af5f9e2013-05-31 18:09:50 +01002367 free (seat->seat_name);
2368
Kristian Høgsberg919cddb2013-07-08 19:03:57 -04002369 wl_global_destroy(seat->global);
Kristian Høgsbergaaadc772013-07-08 16:20:31 -04002370
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04002371 wl_signal_emit(&seat->destroy_signal, seat);
2372}
Derek Foreman1281a362015-07-31 16:55:32 -05002373
2374/** Get a seat's keyboard pointer
2375 *
2376 * \param seat The seat to query
2377 * \return The seat's keyboard pointer, or NULL if no keyboard is present
2378 *
2379 * The keyboard pointer for a seat isn't freed when all keyboards are removed,
2380 * so it should only be used when the seat's keyboard_device_count is greater
2381 * than zero. This function does that test and only returns a pointer
2382 * when a keyboard is present.
2383 */
2384WL_EXPORT struct weston_keyboard *
2385weston_seat_get_keyboard(struct weston_seat *seat)
2386{
2387 if (!seat)
2388 return NULL;
2389
2390 if (seat->keyboard_device_count)
2391 return seat->keyboard_state;
2392
2393 return NULL;
2394}
2395
2396/** Get a seat's pointer pointer
2397 *
2398 * \param seat The seat to query
2399 * \return The seat's pointer pointer, or NULL if no pointer device is present
2400 *
2401 * The pointer pointer for a seat isn't freed when all mice are removed,
2402 * so it should only be used when the seat's pointer_device_count is greater
2403 * than zero. This function does that test and only returns a pointer
2404 * when a pointing device is present.
2405 */
2406WL_EXPORT struct weston_pointer *
2407weston_seat_get_pointer(struct weston_seat *seat)
2408{
2409 if (!seat)
2410 return NULL;
2411
2412 if (seat->pointer_device_count)
2413 return seat->pointer_state;
2414
2415 return NULL;
2416}
2417
2418/** Get a seat's touch pointer
2419 *
2420 * \param seat The seat to query
2421 * \return The seat's touch pointer, or NULL if no touch device is present
2422 *
2423 * The touch pointer for a seat isn't freed when all touch devices are removed,
2424 * so it should only be used when the seat's touch_device_count is greater
2425 * than zero. This function does that test and only returns a pointer
2426 * when a touch device is present.
2427 */
2428WL_EXPORT struct weston_touch *
2429weston_seat_get_touch(struct weston_seat *seat)
2430{
2431 if (!seat)
2432 return NULL;
2433
2434 if (seat->touch_device_count)
2435 return seat->touch_state;
2436
2437 return NULL;
2438}