blob: e533a588b8c3c252786ee05dadd6346bf29fc702 [file] [log] [blame]
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001/*
2 * Copyright © 2013 Intel Corporation
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#include <stdlib.h>
24#include <stdint.h>
25#include <string.h>
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040026#include <sys/mman.h>
27#include <assert.h>
28#include <unistd.h>
Matt Roper01a92732013-06-24 16:52:44 +010029#include <fcntl.h>
Kristian Høgsberg2158a882013-04-18 15:07:39 -040030
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040031#include "../shared/os-compatibility.h"
Kristian Høgsberg2158a882013-04-18 15:07:39 -040032#include "compositor.h"
33
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040034static void
35empty_region(pixman_region32_t *region)
36{
37 pixman_region32_fini(region);
38 pixman_region32_init(region);
39}
40
41static void unbind_resource(struct wl_resource *resource)
42{
Jason Ekstrand44a38632013-06-14 10:08:00 -050043 wl_list_remove(wl_resource_get_link(resource));
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040044}
45
46void
Kristian Høgsberga71e8b22013-05-06 21:51:21 -040047weston_seat_repick(struct weston_seat *seat)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040048{
Kristian Høgsbergda751b82013-07-04 00:58:07 -040049 const struct weston_pointer *pointer = seat->pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040050
Kristian Høgsbergda751b82013-07-04 00:58:07 -040051 if (pointer == NULL)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040052 return;
53
Kristian Høgsbergda751b82013-07-04 00:58:07 -040054 pointer->grab->interface->focus(seat->pointer->grab);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040055}
56
57static void
58weston_compositor_idle_inhibit(struct weston_compositor *compositor)
59{
60 weston_compositor_wake(compositor);
61 compositor->idle_inhibit++;
62}
63
64static void
65weston_compositor_idle_release(struct weston_compositor *compositor)
66{
67 compositor->idle_inhibit--;
68 weston_compositor_wake(compositor);
69}
70
Kristian Høgsberg2158a882013-04-18 15:07:39 -040071static void
72lose_pointer_focus(struct wl_listener *listener, void *data)
73{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -040074 struct weston_pointer *pointer =
75 container_of(listener, struct weston_pointer, focus_listener);
Kristian Høgsberg2158a882013-04-18 15:07:39 -040076
77 pointer->focus_resource = NULL;
78}
79
80static void
81lose_keyboard_focus(struct wl_listener *listener, void *data)
82{
Kristian Høgsberg29139d42013-04-18 15:25:39 -040083 struct weston_keyboard *keyboard =
84 container_of(listener, struct weston_keyboard, focus_listener);
Kristian Høgsberg2158a882013-04-18 15:07:39 -040085
86 keyboard->focus_resource = NULL;
87}
88
89static void
90lose_touch_focus(struct wl_listener *listener, void *data)
91{
Kristian Høgsberge329f362013-05-06 22:19:57 -040092 struct weston_touch *touch =
93 container_of(listener, struct weston_touch, focus_listener);
Kristian Høgsberg2158a882013-04-18 15:07:39 -040094
95 touch->focus_resource = NULL;
96}
97
98static void
Kristian Høgsberg6848c252013-05-08 22:02:59 -040099default_grab_focus(struct weston_pointer_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400100{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400101 struct weston_pointer *pointer = grab->pointer;
Kristian Høgsberg6848c252013-05-08 22:02:59 -0400102 struct weston_surface *surface;
103 wl_fixed_t sx, sy;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400104
105 if (pointer->button_count > 0)
106 return;
107
Kristian Høgsberg6848c252013-05-08 22:02:59 -0400108 surface = weston_compositor_pick_surface(pointer->seat->compositor,
109 pointer->x, pointer->y,
110 &sx, &sy);
111
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400112 if (pointer->focus != surface)
Kristian Høgsberg6848c252013-05-08 22:02:59 -0400113 weston_pointer_set_focus(pointer, surface, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400114}
115
116static void
Kristian Høgsbergbe6403e2013-05-08 21:03:21 -0400117default_grab_motion(struct weston_pointer_grab *grab, uint32_t time)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400118{
Kristian Høgsbergbe6403e2013-05-08 21:03:21 -0400119 struct weston_pointer *pointer = grab->pointer;
120 wl_fixed_t sx, sy;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400121
Kristian Høgsbergbe6403e2013-05-08 21:03:21 -0400122 if (pointer->focus_resource) {
123 weston_surface_from_global_fixed(pointer->focus,
124 pointer->x, pointer->y,
125 &sx, &sy);
126 wl_pointer_send_motion(pointer->focus_resource, time, sx, sy);
127 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400128}
129
130static void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400131default_grab_button(struct weston_pointer_grab *grab,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400132 uint32_t time, uint32_t button, uint32_t state_w)
133{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400134 struct weston_pointer *pointer = grab->pointer;
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400135 struct weston_compositor *compositor = pointer->seat->compositor;
136 struct weston_surface *surface;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400137 struct wl_resource *resource;
138 uint32_t serial;
139 enum wl_pointer_button_state state = state_w;
140 struct wl_display *display;
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400141 wl_fixed_t sx, sy;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400142
143 resource = pointer->focus_resource;
144 if (resource) {
Jason Ekstrand44a38632013-06-14 10:08:00 -0500145 display = wl_client_get_display(wl_resource_get_client(resource));
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400146 serial = wl_display_next_serial(display);
147 wl_pointer_send_button(resource, serial, time, button, state_w);
148 }
149
150 if (pointer->button_count == 0 &&
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400151 state == WL_POINTER_BUTTON_STATE_RELEASED) {
152 surface = weston_compositor_pick_surface(compositor,
153 pointer->x,
154 pointer->y,
155 &sx, &sy);
156
157 weston_pointer_set_focus(pointer, surface, sx, sy);
158 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400159}
160
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400161static const struct weston_pointer_grab_interface
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400162 default_pointer_grab_interface = {
163 default_grab_focus,
164 default_grab_motion,
165 default_grab_button
166};
167
Kristian Høgsberge329f362013-05-06 22:19:57 -0400168static void
169default_grab_touch_down(struct weston_touch_grab *grab, uint32_t time,
170 int touch_id, wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400171{
Kristian Høgsberge329f362013-05-06 22:19:57 -0400172 struct weston_touch *touch = grab->touch;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400173 struct wl_display *display;
174 uint32_t serial;
175
176 if (touch->focus_resource && touch->focus) {
Jason Ekstrand44a38632013-06-14 10:08:00 -0500177 display = wl_client_get_display(wl_resource_get_client(touch->focus_resource));
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400178 serial = wl_display_next_serial(display);
179 wl_touch_send_down(touch->focus_resource, serial, time,
Jason Ekstrand26ed73c2013-06-06 22:34:41 -0500180 touch->focus->resource,
Kristian Høgsberge329f362013-05-06 22:19:57 -0400181 touch_id, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400182 }
183}
184
Kristian Høgsberge329f362013-05-06 22:19:57 -0400185static void
186default_grab_touch_up(struct weston_touch_grab *grab,
187 uint32_t time, int touch_id)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400188{
Kristian Høgsberge329f362013-05-06 22:19:57 -0400189 struct weston_touch *touch = grab->touch;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400190 struct wl_display *display;
191 uint32_t serial;
192
193 if (touch->focus_resource) {
Jason Ekstrand44a38632013-06-14 10:08:00 -0500194 display = wl_client_get_display(wl_resource_get_client(touch->focus_resource));
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400195 serial = wl_display_next_serial(display);
196 wl_touch_send_up(touch->focus_resource, serial, time, touch_id);
197 }
198}
199
Kristian Høgsberge329f362013-05-06 22:19:57 -0400200static void
201default_grab_touch_motion(struct weston_touch_grab *grab, uint32_t time,
202 int touch_id, wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400203{
Kristian Høgsberge329f362013-05-06 22:19:57 -0400204 struct weston_touch *touch = grab->touch;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400205
206 if (touch->focus_resource) {
207 wl_touch_send_motion(touch->focus_resource, time,
Kristian Høgsberge329f362013-05-06 22:19:57 -0400208 touch_id, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400209 }
210}
211
Kristian Høgsberge329f362013-05-06 22:19:57 -0400212static const struct weston_touch_grab_interface default_touch_grab_interface = {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400213 default_grab_touch_down,
214 default_grab_touch_up,
215 default_grab_touch_motion
216};
217
218static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400219default_grab_key(struct weston_keyboard_grab *grab,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400220 uint32_t time, uint32_t key, uint32_t state)
221{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400222 struct weston_keyboard *keyboard = grab->keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400223 struct wl_resource *resource;
224 struct wl_display *display;
225 uint32_t serial;
226
227 resource = keyboard->focus_resource;
228 if (resource) {
Jason Ekstrand44a38632013-06-14 10:08:00 -0500229 display = wl_client_get_display(wl_resource_get_client(resource));
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400230 serial = wl_display_next_serial(display);
231 wl_keyboard_send_key(resource, serial, time, key, state);
232 }
233}
234
235static struct wl_resource *
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400236find_resource_for_surface(struct wl_list *list, struct weston_surface *surface)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400237{
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400238 if (!surface)
239 return NULL;
240
Jason Ekstrand44a38632013-06-14 10:08:00 -0500241 if (!surface->resource)
242 return NULL;
243
244 return wl_resource_find_for_client(list, wl_resource_get_client(surface->resource));
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400245}
246
247static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400248default_grab_modifiers(struct weston_keyboard_grab *grab, uint32_t serial,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400249 uint32_t mods_depressed, uint32_t mods_latched,
250 uint32_t mods_locked, uint32_t group)
251{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400252 struct weston_keyboard *keyboard = grab->keyboard;
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400253 struct weston_pointer *pointer = keyboard->seat->pointer;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400254 struct wl_resource *resource, *pr;
255
256 resource = keyboard->focus_resource;
257 if (!resource)
258 return;
259
260 wl_keyboard_send_modifiers(resource, serial, mods_depressed,
261 mods_latched, mods_locked, group);
262
263 if (pointer && pointer->focus && pointer->focus != keyboard->focus) {
264 pr = find_resource_for_surface(&keyboard->resource_list,
265 pointer->focus);
266 if (pr) {
267 wl_keyboard_send_modifiers(pr,
268 serial,
269 keyboard->modifiers.mods_depressed,
270 keyboard->modifiers.mods_latched,
271 keyboard->modifiers.mods_locked,
272 keyboard->modifiers.group);
273 }
274 }
275}
276
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400277static const struct weston_keyboard_grab_interface
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400278 default_keyboard_grab_interface = {
279 default_grab_key,
280 default_grab_modifiers,
281};
282
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400283static void
284pointer_unmap_sprite(struct weston_pointer *pointer)
285{
286 if (weston_surface_is_mapped(pointer->sprite))
287 weston_surface_unmap(pointer->sprite);
288
289 wl_list_remove(&pointer->sprite_destroy_listener.link);
290 pointer->sprite->configure = NULL;
291 pointer->sprite->configure_private = NULL;
292 pointer->sprite = NULL;
293}
294
295static void
296pointer_handle_sprite_destroy(struct wl_listener *listener, void *data)
297{
298 struct weston_pointer *pointer =
299 container_of(listener, struct weston_pointer,
300 sprite_destroy_listener);
301
302 pointer->sprite = NULL;
303}
304
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400305WL_EXPORT struct weston_pointer *
306weston_pointer_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400307{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400308 struct weston_pointer *pointer;
309
Peter Huttererf3d62272013-08-08 11:57:05 +1000310 pointer = zalloc(sizeof *pointer);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400311 if (pointer == NULL)
312 return NULL;
313
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400314 wl_list_init(&pointer->resource_list);
315 pointer->focus_listener.notify = lose_pointer_focus;
316 pointer->default_grab.interface = &default_pointer_grab_interface;
317 pointer->default_grab.pointer = pointer;
318 pointer->grab = &pointer->default_grab;
319 wl_signal_init(&pointer->focus_signal);
320
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400321 pointer->sprite_destroy_listener.notify = pointer_handle_sprite_destroy;
322
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400323 /* FIXME: Pick better co-ords. */
324 pointer->x = wl_fixed_from_int(100);
325 pointer->y = wl_fixed_from_int(100);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400326
327 return pointer;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400328}
329
330WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400331weston_pointer_destroy(struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400332{
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400333 if (pointer->sprite)
334 pointer_unmap_sprite(pointer);
335
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400336 /* XXX: What about pointer->resource_list? */
337 if (pointer->focus_resource)
338 wl_list_remove(&pointer->focus_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400339 free(pointer);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400340}
341
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400342WL_EXPORT struct weston_keyboard *
343weston_keyboard_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400344{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400345 struct weston_keyboard *keyboard;
346
Peter Huttererf3d62272013-08-08 11:57:05 +1000347 keyboard = zalloc(sizeof *keyboard);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400348 if (keyboard == NULL)
349 return NULL;
350
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400351 wl_list_init(&keyboard->resource_list);
352 wl_array_init(&keyboard->keys);
353 keyboard->focus_listener.notify = lose_keyboard_focus;
354 keyboard->default_grab.interface = &default_keyboard_grab_interface;
355 keyboard->default_grab.keyboard = keyboard;
356 keyboard->grab = &keyboard->default_grab;
357 wl_signal_init(&keyboard->focus_signal);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400358
359 return keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400360}
361
362WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400363weston_keyboard_destroy(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400364{
365 /* XXX: What about keyboard->resource_list? */
366 if (keyboard->focus_resource)
367 wl_list_remove(&keyboard->focus_listener.link);
368 wl_array_release(&keyboard->keys);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400369 free(keyboard);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400370}
371
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400372WL_EXPORT struct weston_touch *
373weston_touch_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400374{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400375 struct weston_touch *touch;
376
Peter Huttererf3d62272013-08-08 11:57:05 +1000377 touch = zalloc(sizeof *touch);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400378 if (touch == NULL)
379 return NULL;
380
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400381 wl_list_init(&touch->resource_list);
382 touch->focus_listener.notify = lose_touch_focus;
383 touch->default_grab.interface = &default_touch_grab_interface;
384 touch->default_grab.touch = touch;
385 touch->grab = &touch->default_grab;
386 wl_signal_init(&touch->focus_signal);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400387
388 return touch;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400389}
390
391WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400392weston_touch_destroy(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400393{
394 /* XXX: What about touch->resource_list? */
395 if (touch->focus_resource)
396 wl_list_remove(&touch->focus_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400397 free(touch);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400398}
399
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400400static void
Kristian Høgsberge3148752013-05-06 23:19:49 -0400401seat_send_updated_caps(struct weston_seat *seat)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400402{
Jason Ekstrand44a38632013-06-14 10:08:00 -0500403 struct wl_list *link;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400404 enum wl_seat_capability caps = 0;
405
406 if (seat->pointer)
407 caps |= WL_SEAT_CAPABILITY_POINTER;
408 if (seat->keyboard)
409 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
410 if (seat->touch)
411 caps |= WL_SEAT_CAPABILITY_TOUCH;
412
Jason Ekstrand44a38632013-06-14 10:08:00 -0500413 for (link = seat->base_resource_list.next;
414 link != &seat->base_resource_list; link = link->next) {
415 wl_seat_send_capabilities(wl_resource_from_link(link), caps);
416 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400417}
418
419WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400420weston_pointer_set_focus(struct weston_pointer *pointer,
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400421 struct weston_surface *surface,
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400422 wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400423{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400424 struct weston_keyboard *kbd = pointer->seat->keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400425 struct wl_resource *resource, *kr;
426 struct wl_display *display;
427 uint32_t serial;
428
429 resource = pointer->focus_resource;
430 if (resource && pointer->focus != surface) {
Jason Ekstrand44a38632013-06-14 10:08:00 -0500431 display = wl_client_get_display(wl_resource_get_client(resource));
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400432 serial = wl_display_next_serial(display);
433 wl_pointer_send_leave(resource, serial,
Jason Ekstrand26ed73c2013-06-06 22:34:41 -0500434 pointer->focus->resource);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400435 wl_list_remove(&pointer->focus_listener.link);
436 }
437
438 resource = find_resource_for_surface(&pointer->resource_list,
439 surface);
440 if (resource &&
441 (pointer->focus != surface ||
442 pointer->focus_resource != resource)) {
Jason Ekstrand44a38632013-06-14 10:08:00 -0500443 display = wl_client_get_display(wl_resource_get_client(resource));
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400444 serial = wl_display_next_serial(display);
445 if (kbd) {
446 kr = find_resource_for_surface(&kbd->resource_list,
447 surface);
448 if (kr) {
449 wl_keyboard_send_modifiers(kr,
450 serial,
451 kbd->modifiers.mods_depressed,
452 kbd->modifiers.mods_latched,
453 kbd->modifiers.mods_locked,
454 kbd->modifiers.group);
455 }
456 }
Jason Ekstrand26ed73c2013-06-06 22:34:41 -0500457 wl_pointer_send_enter(resource, serial, surface->resource,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400458 sx, sy);
Jason Ekstrand44a38632013-06-14 10:08:00 -0500459 wl_resource_add_destroy_listener(resource,
460 &pointer->focus_listener);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400461 pointer->focus_serial = serial;
462 }
463
464 pointer->focus_resource = resource;
465 pointer->focus = surface;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400466 wl_signal_emit(&pointer->focus_signal, pointer);
467}
468
469WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400470weston_keyboard_set_focus(struct weston_keyboard *keyboard,
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400471 struct weston_surface *surface)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400472{
473 struct wl_resource *resource;
474 struct wl_display *display;
475 uint32_t serial;
476
477 if (keyboard->focus_resource && keyboard->focus != surface) {
478 resource = keyboard->focus_resource;
Jason Ekstrand44a38632013-06-14 10:08:00 -0500479 display = wl_client_get_display(wl_resource_get_client(resource));
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400480 serial = wl_display_next_serial(display);
481 wl_keyboard_send_leave(resource, serial,
Jason Ekstrand26ed73c2013-06-06 22:34:41 -0500482 keyboard->focus->resource);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400483 wl_list_remove(&keyboard->focus_listener.link);
484 }
485
486 resource = find_resource_for_surface(&keyboard->resource_list,
487 surface);
488 if (resource &&
489 (keyboard->focus != surface ||
490 keyboard->focus_resource != resource)) {
Jason Ekstrand44a38632013-06-14 10:08:00 -0500491 display = wl_client_get_display(wl_resource_get_client(resource));
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400492 serial = wl_display_next_serial(display);
493 wl_keyboard_send_modifiers(resource, serial,
494 keyboard->modifiers.mods_depressed,
495 keyboard->modifiers.mods_latched,
496 keyboard->modifiers.mods_locked,
497 keyboard->modifiers.group);
Jason Ekstrand26ed73c2013-06-06 22:34:41 -0500498 wl_keyboard_send_enter(resource, serial, surface->resource,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400499 &keyboard->keys);
Jason Ekstrand44a38632013-06-14 10:08:00 -0500500 wl_resource_add_destroy_listener(resource,
501 &keyboard->focus_listener);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400502 keyboard->focus_serial = serial;
503 }
504
505 keyboard->focus_resource = resource;
506 keyboard->focus = surface;
507 wl_signal_emit(&keyboard->focus_signal, keyboard);
508}
509
510WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400511weston_keyboard_start_grab(struct weston_keyboard *keyboard,
512 struct weston_keyboard_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400513{
514 keyboard->grab = grab;
515 grab->keyboard = keyboard;
516
517 /* XXX focus? */
518}
519
520WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400521weston_keyboard_end_grab(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400522{
523 keyboard->grab = &keyboard->default_grab;
524}
525
526WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400527weston_pointer_start_grab(struct weston_pointer *pointer,
528 struct weston_pointer_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400529{
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400530 pointer->grab = grab;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400531 grab->pointer = pointer;
Kristian Høgsbergda751b82013-07-04 00:58:07 -0400532 pointer->grab->interface->focus(pointer->grab);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400533}
534
535WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400536weston_pointer_end_grab(struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400537{
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400538 pointer->grab = &pointer->default_grab;
Kristian Høgsbergda751b82013-07-04 00:58:07 -0400539 pointer->grab->interface->focus(pointer->grab);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400540}
541
542WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -0400543weston_touch_start_grab(struct weston_touch *touch, struct weston_touch_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400544{
545 touch->grab = grab;
546 grab->touch = touch;
547}
548
549WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -0400550weston_touch_end_grab(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400551{
552 touch->grab = &touch->default_grab;
553}
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400554
Rob Bradford806d8c02013-06-25 18:56:41 +0100555WL_EXPORT void
556weston_pointer_clamp(struct weston_pointer *pointer, wl_fixed_t *fx, wl_fixed_t *fy)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400557{
Rob Bradford806d8c02013-06-25 18:56:41 +0100558 struct weston_compositor *ec = pointer->seat->compositor;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400559 struct weston_output *output, *prev = NULL;
560 int x, y, old_x, old_y, valid = 0;
561
562 x = wl_fixed_to_int(*fx);
563 y = wl_fixed_to_int(*fy);
Rob Bradford806d8c02013-06-25 18:56:41 +0100564 old_x = wl_fixed_to_int(pointer->x);
565 old_y = wl_fixed_to_int(pointer->y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400566
567 wl_list_for_each(output, &ec->output_list, link) {
Rob Bradford66bd9f52013-06-25 18:56:42 +0100568 if (pointer->seat->output && pointer->seat->output != output)
569 continue;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400570 if (pixman_region32_contains_point(&output->region,
571 x, y, NULL))
572 valid = 1;
573 if (pixman_region32_contains_point(&output->region,
574 old_x, old_y, NULL))
575 prev = output;
576 }
577
Rob Bradford66bd9f52013-06-25 18:56:42 +0100578 if (!prev)
579 prev = pointer->seat->output;
580
581 if (prev && !valid) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400582 if (x < prev->x)
583 *fx = wl_fixed_from_int(prev->x);
584 else if (x >= prev->x + prev->width)
585 *fx = wl_fixed_from_int(prev->x +
586 prev->width - 1);
587 if (y < prev->y)
588 *fy = wl_fixed_from_int(prev->y);
Alexander Larssonbcd18d92013-05-28 16:23:33 +0200589 else if (y >= prev->y + prev->height)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400590 *fy = wl_fixed_from_int(prev->y +
591 prev->height - 1);
592 }
593}
594
595/* Takes absolute values */
596static void
597move_pointer(struct weston_seat *seat, wl_fixed_t x, wl_fixed_t y)
598{
599 struct weston_compositor *ec = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400600 struct weston_pointer *pointer = seat->pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400601 struct weston_output *output;
602 int32_t ix, iy;
603
Rob Bradford806d8c02013-06-25 18:56:41 +0100604 weston_pointer_clamp (pointer, &x, &y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400605
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400606 pointer->x = x;
607 pointer->y = y;
608
609 ix = wl_fixed_to_int(x);
610 iy = wl_fixed_to_int(y);
611
612 wl_list_for_each(output, &ec->output_list, link)
613 if (output->zoom.active &&
614 pixman_region32_contains_point(&output->region,
615 ix, iy, NULL))
616 weston_output_update_zoom(output, ZOOM_FOCUS_POINTER);
617
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400618 if (pointer->sprite) {
619 weston_surface_set_position(pointer->sprite,
620 ix - pointer->hotspot_x,
621 iy - pointer->hotspot_y);
622 weston_surface_schedule_repaint(pointer->sprite);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400623 }
624}
625
626WL_EXPORT void
627notify_motion(struct weston_seat *seat,
628 uint32_t time, wl_fixed_t dx, wl_fixed_t dy)
629{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400630 struct weston_compositor *ec = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400631 struct weston_pointer *pointer = seat->pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400632
633 weston_compositor_wake(ec);
634
635 move_pointer(seat, pointer->x + dx, pointer->y + dy);
636
Kristian Høgsbergda751b82013-07-04 00:58:07 -0400637 pointer->grab->interface->focus(pointer->grab);
638 pointer->grab->interface->motion(pointer->grab, time);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400639}
640
641WL_EXPORT void
642notify_motion_absolute(struct weston_seat *seat,
643 uint32_t time, wl_fixed_t x, wl_fixed_t y)
644{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400645 struct weston_compositor *ec = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400646 struct weston_pointer *pointer = seat->pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400647
648 weston_compositor_wake(ec);
649
650 move_pointer(seat, x, y);
651
Kristian Høgsbergda751b82013-07-04 00:58:07 -0400652 pointer->grab->interface->focus(pointer->grab);
653 pointer->grab->interface->motion(pointer->grab, time);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400654}
655
656WL_EXPORT void
657weston_surface_activate(struct weston_surface *surface,
658 struct weston_seat *seat)
659{
660 struct weston_compositor *compositor = seat->compositor;
661
Kristian Høgsberge3148752013-05-06 23:19:49 -0400662 if (seat->keyboard) {
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400663 weston_keyboard_set_focus(seat->keyboard, surface);
Kristian Høgsberge3148752013-05-06 23:19:49 -0400664 wl_data_device_set_keyboard_focus(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400665 }
666
667 wl_signal_emit(&compositor->activate_signal, surface);
668}
669
670WL_EXPORT void
671notify_button(struct weston_seat *seat, uint32_t time, int32_t button,
672 enum wl_pointer_button_state state)
673{
674 struct weston_compositor *compositor = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400675 struct weston_pointer *pointer = seat->pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400676 struct weston_surface *focus =
677 (struct weston_surface *) pointer->focus;
678 uint32_t serial = wl_display_next_serial(compositor->wl_display);
679
680 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
681 if (compositor->ping_handler && focus)
682 compositor->ping_handler(focus, serial);
683 weston_compositor_idle_inhibit(compositor);
684 if (pointer->button_count == 0) {
685 pointer->grab_button = button;
686 pointer->grab_time = time;
687 pointer->grab_x = pointer->x;
688 pointer->grab_y = pointer->y;
689 }
690 pointer->button_count++;
691 } else {
692 weston_compositor_idle_release(compositor);
693 pointer->button_count--;
694 }
695
696 weston_compositor_run_button_binding(compositor, seat, time, button,
697 state);
698
699 pointer->grab->interface->button(pointer->grab, time, button, state);
700
701 if (pointer->button_count == 1)
702 pointer->grab_serial =
703 wl_display_get_serial(compositor->wl_display);
704}
705
706WL_EXPORT void
707notify_axis(struct weston_seat *seat, uint32_t time, uint32_t axis,
708 wl_fixed_t value)
709{
710 struct weston_compositor *compositor = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400711 struct weston_pointer *pointer = seat->pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400712 struct weston_surface *focus =
713 (struct weston_surface *) pointer->focus;
714 uint32_t serial = wl_display_next_serial(compositor->wl_display);
715
716 if (compositor->ping_handler && focus)
717 compositor->ping_handler(focus, serial);
718
719 weston_compositor_wake(compositor);
720
721 if (!value)
722 return;
723
724 if (weston_compositor_run_axis_binding(compositor, seat,
725 time, axis, value))
726 return;
727
728 if (pointer->focus_resource)
729 wl_pointer_send_axis(pointer->focus_resource, time, axis,
730 value);
731}
732
Rob Bradford382ff462013-06-24 16:52:45 +0100733#ifdef ENABLE_XKBCOMMON
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400734WL_EXPORT void
735notify_modifiers(struct weston_seat *seat, uint32_t serial)
736{
Kristian Høgsberge3148752013-05-06 23:19:49 -0400737 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400738 struct weston_keyboard_grab *grab = keyboard->grab;
739 uint32_t mods_depressed, mods_latched, mods_locked, group;
740 uint32_t mods_lookup;
741 enum weston_led leds = 0;
742 int changed = 0;
743
744 /* Serialize and update our internal state, checking to see if it's
745 * different to the previous state. */
746 mods_depressed = xkb_state_serialize_mods(seat->xkb_state.state,
747 XKB_STATE_DEPRESSED);
748 mods_latched = xkb_state_serialize_mods(seat->xkb_state.state,
749 XKB_STATE_LATCHED);
750 mods_locked = xkb_state_serialize_mods(seat->xkb_state.state,
751 XKB_STATE_LOCKED);
752 group = xkb_state_serialize_group(seat->xkb_state.state,
753 XKB_STATE_EFFECTIVE);
754
Kristian Høgsberge3148752013-05-06 23:19:49 -0400755 if (mods_depressed != seat->keyboard->modifiers.mods_depressed ||
756 mods_latched != seat->keyboard->modifiers.mods_latched ||
757 mods_locked != seat->keyboard->modifiers.mods_locked ||
758 group != seat->keyboard->modifiers.group)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400759 changed = 1;
760
Kristian Høgsberge3148752013-05-06 23:19:49 -0400761 seat->keyboard->modifiers.mods_depressed = mods_depressed;
762 seat->keyboard->modifiers.mods_latched = mods_latched;
763 seat->keyboard->modifiers.mods_locked = mods_locked;
764 seat->keyboard->modifiers.group = group;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400765
766 /* And update the modifier_state for bindings. */
767 mods_lookup = mods_depressed | mods_latched;
768 seat->modifier_state = 0;
769 if (mods_lookup & (1 << seat->xkb_info.ctrl_mod))
770 seat->modifier_state |= MODIFIER_CTRL;
771 if (mods_lookup & (1 << seat->xkb_info.alt_mod))
772 seat->modifier_state |= MODIFIER_ALT;
773 if (mods_lookup & (1 << seat->xkb_info.super_mod))
774 seat->modifier_state |= MODIFIER_SUPER;
775 if (mods_lookup & (1 << seat->xkb_info.shift_mod))
776 seat->modifier_state |= MODIFIER_SHIFT;
777
778 /* Finally, notify the compositor that LEDs have changed. */
779 if (xkb_state_led_index_is_active(seat->xkb_state.state,
780 seat->xkb_info.num_led))
781 leds |= LED_NUM_LOCK;
782 if (xkb_state_led_index_is_active(seat->xkb_state.state,
783 seat->xkb_info.caps_led))
784 leds |= LED_CAPS_LOCK;
785 if (xkb_state_led_index_is_active(seat->xkb_state.state,
786 seat->xkb_info.scroll_led))
787 leds |= LED_SCROLL_LOCK;
788 if (leds != seat->xkb_state.leds && seat->led_update)
789 seat->led_update(seat, leds);
790 seat->xkb_state.leds = leds;
791
792 if (changed) {
793 grab->interface->modifiers(grab,
794 serial,
795 keyboard->modifiers.mods_depressed,
796 keyboard->modifiers.mods_latched,
797 keyboard->modifiers.mods_locked,
798 keyboard->modifiers.group);
799 }
800}
801
802static void
803update_modifier_state(struct weston_seat *seat, uint32_t serial, uint32_t key,
804 enum wl_keyboard_key_state state)
805{
806 enum xkb_key_direction direction;
807
Matt Roper01a92732013-06-24 16:52:44 +0100808 /* Keyboard modifiers don't exist in raw keyboard mode */
809 if (!seat->compositor->use_xkbcommon)
810 return;
811
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400812 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
813 direction = XKB_KEY_DOWN;
814 else
815 direction = XKB_KEY_UP;
816
817 /* Offset the keycode by 8, as the evdev XKB rules reflect X's
818 * broken keycode system, which starts at 8. */
819 xkb_state_update_key(seat->xkb_state.state, key + 8, direction);
820
821 notify_modifiers(seat, serial);
822}
Rob Bradford382ff462013-06-24 16:52:45 +0100823#else
824WL_EXPORT void
825notify_modifiers(struct weston_seat *seat, uint32_t serial)
826{
827}
828
829static void
830update_modifier_state(struct weston_seat *seat, uint32_t serial, uint32_t key,
831 enum wl_keyboard_key_state state)
832{
833}
834#endif
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400835
836WL_EXPORT void
837notify_key(struct weston_seat *seat, uint32_t time, uint32_t key,
838 enum wl_keyboard_key_state state,
839 enum weston_key_state_update update_state)
840{
841 struct weston_compositor *compositor = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400842 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400843 struct weston_surface *focus =
844 (struct weston_surface *) keyboard->focus;
845 struct weston_keyboard_grab *grab = keyboard->grab;
846 uint32_t serial = wl_display_next_serial(compositor->wl_display);
847 uint32_t *k, *end;
848
849 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
850 if (compositor->ping_handler && focus)
851 compositor->ping_handler(focus, serial);
852
853 weston_compositor_idle_inhibit(compositor);
854 keyboard->grab_key = key;
855 keyboard->grab_time = time;
856 } else {
857 weston_compositor_idle_release(compositor);
858 }
859
860 end = keyboard->keys.data + keyboard->keys.size;
861 for (k = keyboard->keys.data; k < end; k++) {
862 if (*k == key) {
863 /* Ignore server-generated repeats. */
864 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
865 return;
866 *k = *--end;
867 }
868 }
869 keyboard->keys.size = (void *) end - keyboard->keys.data;
870 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
871 k = wl_array_add(&keyboard->keys, sizeof *k);
872 *k = key;
873 }
874
875 if (grab == &keyboard->default_grab ||
876 grab == &keyboard->input_method_grab) {
877 weston_compositor_run_key_binding(compositor, seat, time, key,
878 state);
879 grab = keyboard->grab;
880 }
881
882 grab->interface->key(grab, time, key, state);
883
884 if (update_state == STATE_UPDATE_AUTOMATIC) {
885 update_modifier_state(seat,
886 wl_display_get_serial(compositor->wl_display),
887 key,
888 state);
889 }
890}
891
892WL_EXPORT void
893notify_pointer_focus(struct weston_seat *seat, struct weston_output *output,
894 wl_fixed_t x, wl_fixed_t y)
895{
896 struct weston_compositor *compositor = seat->compositor;
897
898 if (output) {
899 move_pointer(seat, x, y);
900 compositor->focus = 1;
901 } else {
902 compositor->focus = 0;
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400903 /* FIXME: We should call weston_pointer_set_focus(seat,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400904 * NULL) here, but somehow that breaks re-entry... */
905 }
906}
907
908static void
909destroy_device_saved_kbd_focus(struct wl_listener *listener, void *data)
910{
911 struct weston_seat *ws;
912
913 ws = container_of(listener, struct weston_seat,
914 saved_kbd_focus_listener);
915
916 ws->saved_kbd_focus = NULL;
917}
918
919WL_EXPORT void
920notify_keyboard_focus_in(struct weston_seat *seat, struct wl_array *keys,
921 enum weston_key_state_update update_state)
922{
923 struct weston_compositor *compositor = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400924 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400925 struct weston_surface *surface;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400926 uint32_t *k, serial;
927
928 serial = wl_display_next_serial(compositor->wl_display);
929 wl_array_copy(&keyboard->keys, keys);
930 wl_array_for_each(k, &keyboard->keys) {
931 weston_compositor_idle_inhibit(compositor);
932 if (update_state == STATE_UPDATE_AUTOMATIC)
933 update_modifier_state(seat, serial, *k,
934 WL_KEYBOARD_KEY_STATE_PRESSED);
935 }
936
937 /* Run key bindings after we've updated the state. */
938 wl_array_for_each(k, &keyboard->keys) {
939 weston_compositor_run_key_binding(compositor, seat, 0, *k,
940 WL_KEYBOARD_KEY_STATE_PRESSED);
941 }
942
943 surface = seat->saved_kbd_focus;
944
945 if (surface) {
946 wl_list_remove(&seat->saved_kbd_focus_listener.link);
947 weston_keyboard_set_focus(keyboard, surface);
948 seat->saved_kbd_focus = NULL;
949 }
950}
951
952WL_EXPORT void
953notify_keyboard_focus_out(struct weston_seat *seat)
954{
955 struct weston_compositor *compositor = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400956 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400957 uint32_t *k, serial;
958
959 serial = wl_display_next_serial(compositor->wl_display);
960 wl_array_for_each(k, &keyboard->keys) {
961 weston_compositor_idle_release(compositor);
962 update_modifier_state(seat, serial, *k,
963 WL_KEYBOARD_KEY_STATE_RELEASED);
964 }
965
966 seat->modifier_state = 0;
967
968 if (keyboard->focus) {
969 seat->saved_kbd_focus = keyboard->focus;
970 seat->saved_kbd_focus_listener.notify =
971 destroy_device_saved_kbd_focus;
Jason Ekstrand26ed73c2013-06-06 22:34:41 -0500972 wl_signal_add(&keyboard->focus->destroy_signal,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400973 &seat->saved_kbd_focus_listener);
974 }
975
976 weston_keyboard_set_focus(keyboard, NULL);
977 /* FIXME: We really need keyboard grab cancel here to
978 * let the grab shut down properly. As it is we leak
979 * the grab data. */
980 weston_keyboard_end_grab(keyboard);
981}
982
Michael Fua2bb7912013-07-23 15:51:06 +0800983WL_EXPORT void
984weston_touch_set_focus(struct weston_seat *seat, struct weston_surface *surface)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400985{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400986 struct wl_resource *resource;
987
988 if (seat->touch->focus == surface)
989 return;
990
991 if (seat->touch->focus_resource)
992 wl_list_remove(&seat->touch->focus_listener.link);
993 seat->touch->focus = NULL;
994 seat->touch->focus_resource = NULL;
995
996 if (surface) {
997 resource =
Kristian Høgsberg80fb82d2013-05-06 21:49:55 -0400998 find_resource_for_surface(&seat->touch->resource_list,
999 surface);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001000 if (!resource) {
1001 weston_log("couldn't find resource\n");
1002 return;
1003 }
1004
1005 seat->touch->focus = surface;
1006 seat->touch->focus_resource = resource;
Jason Ekstrand44a38632013-06-14 10:08:00 -05001007 wl_resource_add_destroy_listener(resource,
1008 &seat->touch->focus_listener);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001009 }
1010}
1011
1012/**
1013 * notify_touch - emulates button touches and notifies surfaces accordingly.
1014 *
1015 * It assumes always the correct cycle sequence until it gets here: touch_down
1016 * → touch_update → ... → touch_update → touch_end. The driver is responsible
1017 * for sending along such order.
1018 *
1019 */
1020WL_EXPORT void
1021notify_touch(struct weston_seat *seat, uint32_t time, int touch_id,
1022 wl_fixed_t x, wl_fixed_t y, int touch_type)
1023{
1024 struct weston_compositor *ec = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -04001025 struct weston_touch *touch = seat->touch;
Kristian Høgsberge329f362013-05-06 22:19:57 -04001026 struct weston_touch_grab *grab = touch->grab;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001027 struct weston_surface *es;
1028 wl_fixed_t sx, sy;
1029
1030 /* Update grab's global coordinates. */
1031 touch->grab_x = x;
1032 touch->grab_y = y;
1033
1034 switch (touch_type) {
1035 case WL_TOUCH_DOWN:
1036 weston_compositor_idle_inhibit(ec);
1037
1038 seat->num_tp++;
1039
1040 /* the first finger down picks the surface, and all further go
1041 * to that surface for the remainder of the touch session i.e.
1042 * until all touch points are up again. */
1043 if (seat->num_tp == 1) {
1044 es = weston_compositor_pick_surface(ec, x, y, &sx, &sy);
Michael Fua2bb7912013-07-23 15:51:06 +08001045 weston_touch_set_focus(seat, es);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001046 } else if (touch->focus) {
1047 es = (struct weston_surface *) touch->focus;
1048 weston_surface_from_global_fixed(es, x, y, &sx, &sy);
1049 } else {
1050 /* Unexpected condition: We have non-initial touch but
1051 * there is no focused surface.
1052 */
1053 weston_log("touch event received with %d points down"
1054 "but no surface focused\n", seat->num_tp);
1055 return;
1056 }
1057
1058 grab->interface->down(grab, time, touch_id, sx, sy);
1059 break;
1060 case WL_TOUCH_MOTION:
1061 es = (struct weston_surface *) touch->focus;
1062 if (!es)
1063 break;
1064
1065 weston_surface_from_global_fixed(es, x, y, &sx, &sy);
1066 grab->interface->motion(grab, time, touch_id, sx, sy);
1067 break;
1068 case WL_TOUCH_UP:
1069 weston_compositor_idle_release(ec);
1070 seat->num_tp--;
1071
1072 grab->interface->up(grab, time, touch_id);
1073 if (seat->num_tp == 0)
Michael Fua2bb7912013-07-23 15:51:06 +08001074 weston_touch_set_focus(seat, NULL);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001075 break;
1076 }
1077}
1078
1079static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001080pointer_cursor_surface_configure(struct weston_surface *es,
1081 int32_t dx, int32_t dy, int32_t width, int32_t height)
1082{
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001083 struct weston_pointer *pointer = es->configure_private;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001084 int x, y;
1085
1086 if (width == 0)
1087 return;
1088
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001089 assert(es == pointer->sprite);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001090
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001091 pointer->hotspot_x -= dx;
1092 pointer->hotspot_y -= dy;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001093
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001094 x = wl_fixed_to_int(pointer->x) - pointer->hotspot_x;
1095 y = wl_fixed_to_int(pointer->y) - pointer->hotspot_y;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001096
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001097 weston_surface_configure(pointer->sprite, x, y, width, height);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001098
1099 empty_region(&es->pending.input);
1100
1101 if (!weston_surface_is_mapped(es)) {
1102 wl_list_insert(&es->compositor->cursor_layer.surface_list,
1103 &es->layer_link);
1104 weston_surface_update_transform(es);
1105 }
1106}
1107
1108static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001109pointer_set_cursor(struct wl_client *client, struct wl_resource *resource,
1110 uint32_t serial, struct wl_resource *surface_resource,
1111 int32_t x, int32_t y)
1112{
Jason Ekstrand44a38632013-06-14 10:08:00 -05001113 struct weston_pointer *pointer = wl_resource_get_user_data(resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001114 struct weston_surface *surface = NULL;
1115
1116 if (surface_resource)
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05001117 surface = wl_resource_get_user_data(surface_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001118
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001119 if (pointer->focus == NULL)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001120 return;
Giulio Camuffo1fd4b012013-06-20 18:13:07 +02001121 /* pointer->focus->resource can be NULL. Surfaces like the
1122 black_surface used in shell.c for fullscreen don't have
1123 a resource, but can still have focus */
1124 if (pointer->focus->resource == NULL)
1125 return;
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05001126 if (wl_resource_get_client(pointer->focus->resource) != client)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001127 return;
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001128 if (pointer->focus_serial - serial > UINT32_MAX / 2)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001129 return;
1130
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001131 if (surface && surface != pointer->sprite) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001132 if (surface->configure) {
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05001133 wl_resource_post_error(surface->resource,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001134 WL_DISPLAY_ERROR_INVALID_OBJECT,
1135 "surface->configure already "
1136 "set");
1137 return;
1138 }
1139 }
1140
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001141 if (pointer->sprite)
1142 pointer_unmap_sprite(pointer);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001143
1144 if (!surface)
1145 return;
1146
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05001147 wl_signal_add(&surface->destroy_signal,
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001148 &pointer->sprite_destroy_listener);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001149
1150 surface->configure = pointer_cursor_surface_configure;
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001151 surface->configure_private = pointer;
1152 pointer->sprite = surface;
1153 pointer->hotspot_x = x;
1154 pointer->hotspot_y = y;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001155
1156 if (surface->buffer_ref.buffer)
1157 pointer_cursor_surface_configure(surface, 0, 0, weston_surface_buffer_width(surface),
1158 weston_surface_buffer_height(surface));
1159}
1160
1161static const struct wl_pointer_interface pointer_interface = {
1162 pointer_set_cursor
1163};
1164
1165static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001166seat_get_pointer(struct wl_client *client, struct wl_resource *resource,
1167 uint32_t id)
1168{
Jason Ekstrand44a38632013-06-14 10:08:00 -05001169 struct weston_seat *seat = wl_resource_get_user_data(resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001170 struct wl_resource *cr;
1171
Kristian Høgsberge3148752013-05-06 23:19:49 -04001172 if (!seat->pointer)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001173 return;
1174
Jason Ekstranda85118c2013-06-27 20:17:02 -05001175 cr = wl_resource_create(client, &wl_pointer_interface,
1176 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07001177 if (cr == NULL) {
1178 wl_client_post_no_memory(client);
1179 return;
1180 }
1181
Jason Ekstrand44a38632013-06-14 10:08:00 -05001182 wl_list_insert(&seat->pointer->resource_list, wl_resource_get_link(cr));
Jason Ekstranda85118c2013-06-27 20:17:02 -05001183 wl_resource_set_implementation(cr, &pointer_interface, seat->pointer,
1184 unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001185
Giulio Camuffo708b8af2013-07-07 17:38:50 +02001186 if (seat->pointer->focus && seat->pointer->focus->resource &&
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05001187 wl_resource_get_client(seat->pointer->focus->resource) == client) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001188 struct weston_surface *surface;
1189 wl_fixed_t sx, sy;
1190
Kristian Høgsberge3148752013-05-06 23:19:49 -04001191 surface = (struct weston_surface *) seat->pointer->focus;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001192 weston_surface_from_global_fixed(surface,
Kristian Høgsberge3148752013-05-06 23:19:49 -04001193 seat->pointer->x,
1194 seat->pointer->y,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001195 &sx,
1196 &sy);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001197 weston_pointer_set_focus(seat->pointer,
1198 seat->pointer->focus,
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001199 sx,
1200 sy);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001201 }
1202}
1203
1204static void
1205seat_get_keyboard(struct wl_client *client, struct wl_resource *resource,
1206 uint32_t id)
1207{
Jason Ekstrand44a38632013-06-14 10:08:00 -05001208 struct weston_seat *seat = wl_resource_get_user_data(resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001209 struct wl_resource *cr;
1210
Kristian Høgsberge3148752013-05-06 23:19:49 -04001211 if (!seat->keyboard)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001212 return;
1213
Jason Ekstranda85118c2013-06-27 20:17:02 -05001214 cr = wl_resource_create(client, &wl_keyboard_interface,
1215 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07001216 if (cr == NULL) {
1217 wl_client_post_no_memory(client);
1218 return;
1219 }
1220
Jason Ekstrand44a38632013-06-14 10:08:00 -05001221 wl_list_insert(&seat->keyboard->resource_list, wl_resource_get_link(cr));
Jason Ekstranda85118c2013-06-27 20:17:02 -05001222 wl_resource_set_implementation(cr, NULL, seat, unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001223
Matt Roper01a92732013-06-24 16:52:44 +01001224 if (seat->compositor->use_xkbcommon) {
1225 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
1226 seat->xkb_info.keymap_fd,
1227 seat->xkb_info.keymap_size);
1228 } else {
1229 int null_fd = open("/dev/null", O_RDONLY);
1230 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP,
1231 null_fd,
1232 0);
1233 close(null_fd);
1234 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001235
Kristian Høgsberge3148752013-05-06 23:19:49 -04001236 if (seat->keyboard->focus &&
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05001237 wl_resource_get_client(seat->keyboard->focus->resource) == client) {
Kristian Høgsberge3148752013-05-06 23:19:49 -04001238 weston_keyboard_set_focus(seat->keyboard,
1239 seat->keyboard->focus);
1240 wl_data_device_set_keyboard_focus(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001241 }
1242}
1243
1244static void
1245seat_get_touch(struct wl_client *client, struct wl_resource *resource,
1246 uint32_t id)
1247{
Jason Ekstrand44a38632013-06-14 10:08:00 -05001248 struct weston_seat *seat = wl_resource_get_user_data(resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001249 struct wl_resource *cr;
1250
Kristian Høgsberge3148752013-05-06 23:19:49 -04001251 if (!seat->touch)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001252 return;
1253
Jason Ekstranda85118c2013-06-27 20:17:02 -05001254 cr = wl_resource_create(client, &wl_touch_interface,
1255 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07001256 if (cr == NULL) {
1257 wl_client_post_no_memory(client);
1258 return;
1259 }
1260
Jason Ekstrand44a38632013-06-14 10:08:00 -05001261 wl_list_insert(&seat->touch->resource_list, wl_resource_get_link(cr));
Jason Ekstranda85118c2013-06-27 20:17:02 -05001262 wl_resource_set_implementation(cr, NULL, seat, unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001263}
1264
1265static const struct wl_seat_interface seat_interface = {
1266 seat_get_pointer,
1267 seat_get_keyboard,
1268 seat_get_touch,
1269};
1270
1271static void
1272bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
1273{
Kristian Høgsberge3148752013-05-06 23:19:49 -04001274 struct weston_seat *seat = data;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001275 struct wl_resource *resource;
1276 enum wl_seat_capability caps = 0;
1277
Jason Ekstranda85118c2013-06-27 20:17:02 -05001278 resource = wl_resource_create(client,
1279 &wl_seat_interface, MIN(version, 2), id);
Jason Ekstrand44a38632013-06-14 10:08:00 -05001280 wl_list_insert(&seat->base_resource_list, wl_resource_get_link(resource));
Jason Ekstranda85118c2013-06-27 20:17:02 -05001281 wl_resource_set_implementation(resource, &seat_interface, data,
1282 unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001283
1284 if (seat->pointer)
1285 caps |= WL_SEAT_CAPABILITY_POINTER;
1286 if (seat->keyboard)
1287 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
1288 if (seat->touch)
1289 caps |= WL_SEAT_CAPABILITY_TOUCH;
1290
1291 wl_seat_send_capabilities(resource, caps);
Rob Bradforde445ae62013-05-31 18:09:51 +01001292 if (version >= 2)
1293 wl_seat_send_name(resource, seat->seat_name);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001294}
1295
Rob Bradford382ff462013-06-24 16:52:45 +01001296#ifdef ENABLE_XKBCOMMON
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001297int
1298weston_compositor_xkb_init(struct weston_compositor *ec,
1299 struct xkb_rule_names *names)
1300{
Rob Bradford382ff462013-06-24 16:52:45 +01001301 ec->use_xkbcommon = 1;
Matt Roper01a92732013-06-24 16:52:44 +01001302
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001303 if (ec->xkb_context == NULL) {
1304 ec->xkb_context = xkb_context_new(0);
1305 if (ec->xkb_context == NULL) {
1306 weston_log("failed to create XKB context\n");
1307 return -1;
1308 }
1309 }
1310
1311 if (names)
1312 ec->xkb_names = *names;
1313 if (!ec->xkb_names.rules)
1314 ec->xkb_names.rules = strdup("evdev");
1315 if (!ec->xkb_names.model)
1316 ec->xkb_names.model = strdup("pc105");
1317 if (!ec->xkb_names.layout)
1318 ec->xkb_names.layout = strdup("us");
1319
1320 return 0;
1321}
1322
1323static void xkb_info_destroy(struct weston_xkb_info *xkb_info)
1324{
1325 if (xkb_info->keymap)
1326 xkb_map_unref(xkb_info->keymap);
1327
1328 if (xkb_info->keymap_area)
1329 munmap(xkb_info->keymap_area, xkb_info->keymap_size);
1330 if (xkb_info->keymap_fd >= 0)
1331 close(xkb_info->keymap_fd);
1332}
1333
1334void
1335weston_compositor_xkb_destroy(struct weston_compositor *ec)
1336{
Matt Roper01a92732013-06-24 16:52:44 +01001337 /*
1338 * If we're operating in raw keyboard mode, we never initialized
1339 * libxkbcommon so there's no cleanup to do either.
1340 */
1341 if (!ec->use_xkbcommon)
1342 return;
1343
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001344 free((char *) ec->xkb_names.rules);
1345 free((char *) ec->xkb_names.model);
1346 free((char *) ec->xkb_names.layout);
1347 free((char *) ec->xkb_names.variant);
1348 free((char *) ec->xkb_names.options);
1349
1350 xkb_info_destroy(&ec->xkb_info);
1351 xkb_context_unref(ec->xkb_context);
1352}
1353
1354static int
1355weston_xkb_info_new_keymap(struct weston_xkb_info *xkb_info)
1356{
1357 char *keymap_str;
1358
1359 xkb_info->shift_mod = xkb_map_mod_get_index(xkb_info->keymap,
1360 XKB_MOD_NAME_SHIFT);
1361 xkb_info->caps_mod = xkb_map_mod_get_index(xkb_info->keymap,
1362 XKB_MOD_NAME_CAPS);
1363 xkb_info->ctrl_mod = xkb_map_mod_get_index(xkb_info->keymap,
1364 XKB_MOD_NAME_CTRL);
1365 xkb_info->alt_mod = xkb_map_mod_get_index(xkb_info->keymap,
1366 XKB_MOD_NAME_ALT);
1367 xkb_info->mod2_mod = xkb_map_mod_get_index(xkb_info->keymap, "Mod2");
1368 xkb_info->mod3_mod = xkb_map_mod_get_index(xkb_info->keymap, "Mod3");
1369 xkb_info->super_mod = xkb_map_mod_get_index(xkb_info->keymap,
1370 XKB_MOD_NAME_LOGO);
1371 xkb_info->mod5_mod = xkb_map_mod_get_index(xkb_info->keymap, "Mod5");
1372
1373 xkb_info->num_led = xkb_map_led_get_index(xkb_info->keymap,
1374 XKB_LED_NAME_NUM);
1375 xkb_info->caps_led = xkb_map_led_get_index(xkb_info->keymap,
1376 XKB_LED_NAME_CAPS);
1377 xkb_info->scroll_led = xkb_map_led_get_index(xkb_info->keymap,
1378 XKB_LED_NAME_SCROLL);
1379
1380 keymap_str = xkb_map_get_as_string(xkb_info->keymap);
1381 if (keymap_str == NULL) {
1382 weston_log("failed to get string version of keymap\n");
1383 return -1;
1384 }
1385 xkb_info->keymap_size = strlen(keymap_str) + 1;
1386
1387 xkb_info->keymap_fd = os_create_anonymous_file(xkb_info->keymap_size);
1388 if (xkb_info->keymap_fd < 0) {
1389 weston_log("creating a keymap file for %lu bytes failed: %m\n",
1390 (unsigned long) xkb_info->keymap_size);
1391 goto err_keymap_str;
1392 }
1393
1394 xkb_info->keymap_area = mmap(NULL, xkb_info->keymap_size,
1395 PROT_READ | PROT_WRITE,
1396 MAP_SHARED, xkb_info->keymap_fd, 0);
1397 if (xkb_info->keymap_area == MAP_FAILED) {
1398 weston_log("failed to mmap() %lu bytes\n",
1399 (unsigned long) xkb_info->keymap_size);
1400 goto err_dev_zero;
1401 }
1402 strcpy(xkb_info->keymap_area, keymap_str);
1403 free(keymap_str);
1404
1405 return 0;
1406
1407err_dev_zero:
1408 close(xkb_info->keymap_fd);
1409 xkb_info->keymap_fd = -1;
1410err_keymap_str:
1411 free(keymap_str);
1412 return -1;
1413}
1414
1415static int
1416weston_compositor_build_global_keymap(struct weston_compositor *ec)
1417{
1418 if (ec->xkb_info.keymap != NULL)
1419 return 0;
1420
1421 ec->xkb_info.keymap = xkb_map_new_from_names(ec->xkb_context,
1422 &ec->xkb_names,
1423 0);
1424 if (ec->xkb_info.keymap == NULL) {
1425 weston_log("failed to compile global XKB keymap\n");
1426 weston_log(" tried rules %s, model %s, layout %s, variant %s, "
1427 "options %s\n",
1428 ec->xkb_names.rules, ec->xkb_names.model,
1429 ec->xkb_names.layout, ec->xkb_names.variant,
1430 ec->xkb_names.options);
1431 return -1;
1432 }
1433
1434 if (weston_xkb_info_new_keymap(&ec->xkb_info) < 0)
1435 return -1;
1436
1437 return 0;
1438}
Rob Bradford382ff462013-06-24 16:52:45 +01001439#else
1440int
1441weston_compositor_xkb_init(struct weston_compositor *ec,
1442 struct xkb_rule_names *names)
1443{
1444 return 0;
1445}
1446
1447void
1448weston_compositor_xkb_destroy(struct weston_compositor *ec)
1449{
1450}
1451#endif
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001452
1453WL_EXPORT int
1454weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap)
1455{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001456 struct weston_keyboard *keyboard;
1457
Kristian Høgsberg2bf87622013-05-07 23:17:41 -04001458 if (seat->keyboard)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001459 return 0;
1460
Rob Bradford382ff462013-06-24 16:52:45 +01001461#ifdef ENABLE_XKBCOMMON
Matt Roper01a92732013-06-24 16:52:44 +01001462 if (seat->compositor->use_xkbcommon) {
1463 if (keymap != NULL) {
1464 seat->xkb_info.keymap = xkb_map_ref(keymap);
1465 if (weston_xkb_info_new_keymap(&seat->xkb_info) < 0)
1466 return -1;
1467 } else {
1468 if (weston_compositor_build_global_keymap(seat->compositor) < 0)
1469 return -1;
1470 seat->xkb_info = seat->compositor->xkb_info;
1471 seat->xkb_info.keymap = xkb_map_ref(seat->xkb_info.keymap);
1472 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001473
Matt Roper01a92732013-06-24 16:52:44 +01001474 seat->xkb_state.state = xkb_state_new(seat->xkb_info.keymap);
1475 if (seat->xkb_state.state == NULL) {
1476 weston_log("failed to initialise XKB state\n");
1477 return -1;
1478 }
1479
1480 seat->xkb_state.leds = 0;
1481 }
Rob Bradford382ff462013-06-24 16:52:45 +01001482#endif
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001483
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001484 keyboard = weston_keyboard_create();
1485 if (keyboard == NULL) {
1486 weston_log("failed to allocate weston keyboard struct\n");
1487 return -1;
1488 }
1489
1490 seat->keyboard = keyboard;
1491 keyboard->seat = seat;
1492
1493 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001494
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001495 return 0;
1496}
1497
1498WL_EXPORT void
1499weston_seat_init_pointer(struct weston_seat *seat)
1500{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001501 struct weston_pointer *pointer;
1502
Kristian Høgsberg2bf87622013-05-07 23:17:41 -04001503 if (seat->pointer)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001504 return;
1505
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001506 pointer = weston_pointer_create();
1507 if (pointer == NULL)
1508 return;
1509
1510 seat->pointer = pointer;
1511 pointer->seat = seat;
1512
1513 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001514}
1515
1516WL_EXPORT void
1517weston_seat_init_touch(struct weston_seat *seat)
1518{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001519 struct weston_touch *touch;
1520
Kristian Høgsberg2bf87622013-05-07 23:17:41 -04001521 if (seat->touch)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001522 return;
1523
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001524 touch = weston_touch_create();
1525 if (touch == NULL)
1526 return;
1527
1528 seat->touch = touch;
1529 touch->seat = seat;
1530
1531 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001532}
1533
1534WL_EXPORT void
Rob Bradford9af5f9e2013-05-31 18:09:50 +01001535weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec,
1536 const char *seat_name)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001537{
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04001538 memset(seat, 0, sizeof *seat);
1539
Kristian Høgsberge3148752013-05-06 23:19:49 -04001540 seat->selection_data_source = NULL;
1541 wl_list_init(&seat->base_resource_list);
1542 wl_signal_init(&seat->selection_signal);
1543 wl_list_init(&seat->drag_resource_list);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001544 wl_signal_init(&seat->destroy_signal);
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04001545
Kristian Høgsberg919cddb2013-07-08 19:03:57 -04001546 seat->global = wl_global_create(ec->wl_display, &wl_seat_interface, 2,
1547 seat, bind_seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001548
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001549 seat->compositor = ec;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001550 seat->modifier_state = 0;
1551 seat->num_tp = 0;
Rob Bradford9af5f9e2013-05-31 18:09:50 +01001552 seat->seat_name = strdup(seat_name);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001553
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001554 wl_list_insert(ec->seat_list.prev, &seat->link);
1555
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001556 clipboard_create(seat);
1557
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001558 wl_signal_emit(&ec->seat_created_signal, seat);
1559}
1560
1561WL_EXPORT void
1562weston_seat_release(struct weston_seat *seat)
1563{
1564 wl_list_remove(&seat->link);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001565
Rob Bradford382ff462013-06-24 16:52:45 +01001566#ifdef ENABLE_XKBCOMMON
Matt Roper01a92732013-06-24 16:52:44 +01001567 if (seat->compositor->use_xkbcommon) {
1568 if (seat->xkb_state.state != NULL)
1569 xkb_state_unref(seat->xkb_state.state);
1570 xkb_info_destroy(&seat->xkb_info);
1571 }
Rob Bradford382ff462013-06-24 16:52:45 +01001572#endif
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001573
Kristian Høgsberge3148752013-05-06 23:19:49 -04001574 if (seat->pointer)
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001575 weston_pointer_destroy(seat->pointer);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001576 if (seat->keyboard)
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001577 weston_keyboard_destroy(seat->keyboard);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001578 if (seat->touch)
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001579 weston_touch_destroy(seat->touch);
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04001580
Rob Bradford9af5f9e2013-05-31 18:09:50 +01001581 free (seat->seat_name);
1582
Kristian Høgsberg919cddb2013-07-08 19:03:57 -04001583 wl_global_destroy(seat->global);
Kristian Høgsbergaaadc772013-07-08 16:20:31 -04001584
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001585 wl_signal_emit(&seat->destroy_signal, seat);
1586}