blob: f76fcb941dd07da03a85802382be8ac96f2a13fc [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);
Rusty Lynchf1407ff2013-08-08 21:13:57 -07001059 if (seat->num_tp == 1) {
1060 touch->grab_serial =
1061 wl_display_get_serial(ec->wl_display);
1062 touch->grab_time = time;
1063 touch->grab_x = x;
1064 touch->grab_y = y;
1065 }
1066
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001067 break;
1068 case WL_TOUCH_MOTION:
1069 es = (struct weston_surface *) touch->focus;
1070 if (!es)
1071 break;
1072
1073 weston_surface_from_global_fixed(es, x, y, &sx, &sy);
1074 grab->interface->motion(grab, time, touch_id, sx, sy);
1075 break;
1076 case WL_TOUCH_UP:
1077 weston_compositor_idle_release(ec);
1078 seat->num_tp--;
1079
1080 grab->interface->up(grab, time, touch_id);
1081 if (seat->num_tp == 0)
Michael Fua2bb7912013-07-23 15:51:06 +08001082 weston_touch_set_focus(seat, NULL);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001083 break;
1084 }
1085}
1086
1087static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001088pointer_cursor_surface_configure(struct weston_surface *es,
1089 int32_t dx, int32_t dy, int32_t width, int32_t height)
1090{
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001091 struct weston_pointer *pointer = es->configure_private;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001092 int x, y;
1093
1094 if (width == 0)
1095 return;
1096
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001097 assert(es == pointer->sprite);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001098
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001099 pointer->hotspot_x -= dx;
1100 pointer->hotspot_y -= dy;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001101
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001102 x = wl_fixed_to_int(pointer->x) - pointer->hotspot_x;
1103 y = wl_fixed_to_int(pointer->y) - pointer->hotspot_y;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001104
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001105 weston_surface_configure(pointer->sprite, x, y, width, height);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001106
1107 empty_region(&es->pending.input);
1108
1109 if (!weston_surface_is_mapped(es)) {
1110 wl_list_insert(&es->compositor->cursor_layer.surface_list,
1111 &es->layer_link);
1112 weston_surface_update_transform(es);
1113 }
1114}
1115
1116static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001117pointer_set_cursor(struct wl_client *client, struct wl_resource *resource,
1118 uint32_t serial, struct wl_resource *surface_resource,
1119 int32_t x, int32_t y)
1120{
Jason Ekstrand44a38632013-06-14 10:08:00 -05001121 struct weston_pointer *pointer = wl_resource_get_user_data(resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001122 struct weston_surface *surface = NULL;
1123
1124 if (surface_resource)
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05001125 surface = wl_resource_get_user_data(surface_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001126
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001127 if (pointer->focus == NULL)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001128 return;
Giulio Camuffo1fd4b012013-06-20 18:13:07 +02001129 /* pointer->focus->resource can be NULL. Surfaces like the
1130 black_surface used in shell.c for fullscreen don't have
1131 a resource, but can still have focus */
1132 if (pointer->focus->resource == NULL)
1133 return;
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05001134 if (wl_resource_get_client(pointer->focus->resource) != client)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001135 return;
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001136 if (pointer->focus_serial - serial > UINT32_MAX / 2)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001137 return;
1138
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001139 if (surface && surface != pointer->sprite) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001140 if (surface->configure) {
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05001141 wl_resource_post_error(surface->resource,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001142 WL_DISPLAY_ERROR_INVALID_OBJECT,
1143 "surface->configure already "
1144 "set");
1145 return;
1146 }
1147 }
1148
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001149 if (pointer->sprite)
1150 pointer_unmap_sprite(pointer);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001151
1152 if (!surface)
1153 return;
1154
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05001155 wl_signal_add(&surface->destroy_signal,
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001156 &pointer->sprite_destroy_listener);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001157
1158 surface->configure = pointer_cursor_surface_configure;
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001159 surface->configure_private = pointer;
1160 pointer->sprite = surface;
1161 pointer->hotspot_x = x;
1162 pointer->hotspot_y = y;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001163
1164 if (surface->buffer_ref.buffer)
1165 pointer_cursor_surface_configure(surface, 0, 0, weston_surface_buffer_width(surface),
1166 weston_surface_buffer_height(surface));
1167}
1168
1169static const struct wl_pointer_interface pointer_interface = {
1170 pointer_set_cursor
1171};
1172
1173static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001174seat_get_pointer(struct wl_client *client, struct wl_resource *resource,
1175 uint32_t id)
1176{
Jason Ekstrand44a38632013-06-14 10:08:00 -05001177 struct weston_seat *seat = wl_resource_get_user_data(resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001178 struct wl_resource *cr;
1179
Kristian Høgsberge3148752013-05-06 23:19:49 -04001180 if (!seat->pointer)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001181 return;
1182
Jason Ekstranda85118c2013-06-27 20:17:02 -05001183 cr = wl_resource_create(client, &wl_pointer_interface,
1184 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07001185 if (cr == NULL) {
1186 wl_client_post_no_memory(client);
1187 return;
1188 }
1189
Jason Ekstrand44a38632013-06-14 10:08:00 -05001190 wl_list_insert(&seat->pointer->resource_list, wl_resource_get_link(cr));
Jason Ekstranda85118c2013-06-27 20:17:02 -05001191 wl_resource_set_implementation(cr, &pointer_interface, seat->pointer,
1192 unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001193
Giulio Camuffo708b8af2013-07-07 17:38:50 +02001194 if (seat->pointer->focus && seat->pointer->focus->resource &&
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05001195 wl_resource_get_client(seat->pointer->focus->resource) == client) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001196 struct weston_surface *surface;
1197 wl_fixed_t sx, sy;
1198
Kristian Høgsberge3148752013-05-06 23:19:49 -04001199 surface = (struct weston_surface *) seat->pointer->focus;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001200 weston_surface_from_global_fixed(surface,
Kristian Høgsberge3148752013-05-06 23:19:49 -04001201 seat->pointer->x,
1202 seat->pointer->y,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001203 &sx,
1204 &sy);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001205 weston_pointer_set_focus(seat->pointer,
1206 seat->pointer->focus,
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001207 sx,
1208 sy);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001209 }
1210}
1211
1212static void
1213seat_get_keyboard(struct wl_client *client, struct wl_resource *resource,
1214 uint32_t id)
1215{
Jason Ekstrand44a38632013-06-14 10:08:00 -05001216 struct weston_seat *seat = wl_resource_get_user_data(resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001217 struct wl_resource *cr;
1218
Kristian Høgsberge3148752013-05-06 23:19:49 -04001219 if (!seat->keyboard)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001220 return;
1221
Jason Ekstranda85118c2013-06-27 20:17:02 -05001222 cr = wl_resource_create(client, &wl_keyboard_interface,
1223 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07001224 if (cr == NULL) {
1225 wl_client_post_no_memory(client);
1226 return;
1227 }
1228
Jason Ekstrand44a38632013-06-14 10:08:00 -05001229 wl_list_insert(&seat->keyboard->resource_list, wl_resource_get_link(cr));
Jason Ekstranda85118c2013-06-27 20:17:02 -05001230 wl_resource_set_implementation(cr, NULL, seat, unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001231
Matt Roper01a92732013-06-24 16:52:44 +01001232 if (seat->compositor->use_xkbcommon) {
1233 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
1234 seat->xkb_info.keymap_fd,
1235 seat->xkb_info.keymap_size);
1236 } else {
1237 int null_fd = open("/dev/null", O_RDONLY);
1238 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP,
1239 null_fd,
1240 0);
1241 close(null_fd);
1242 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001243
Kristian Høgsberge3148752013-05-06 23:19:49 -04001244 if (seat->keyboard->focus &&
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05001245 wl_resource_get_client(seat->keyboard->focus->resource) == client) {
Kristian Høgsberge3148752013-05-06 23:19:49 -04001246 weston_keyboard_set_focus(seat->keyboard,
1247 seat->keyboard->focus);
1248 wl_data_device_set_keyboard_focus(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001249 }
1250}
1251
1252static void
1253seat_get_touch(struct wl_client *client, struct wl_resource *resource,
1254 uint32_t id)
1255{
Jason Ekstrand44a38632013-06-14 10:08:00 -05001256 struct weston_seat *seat = wl_resource_get_user_data(resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001257 struct wl_resource *cr;
1258
Kristian Høgsberge3148752013-05-06 23:19:49 -04001259 if (!seat->touch)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001260 return;
1261
Jason Ekstranda85118c2013-06-27 20:17:02 -05001262 cr = wl_resource_create(client, &wl_touch_interface,
1263 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07001264 if (cr == NULL) {
1265 wl_client_post_no_memory(client);
1266 return;
1267 }
1268
Jason Ekstrand44a38632013-06-14 10:08:00 -05001269 wl_list_insert(&seat->touch->resource_list, wl_resource_get_link(cr));
Jason Ekstranda85118c2013-06-27 20:17:02 -05001270 wl_resource_set_implementation(cr, NULL, seat, unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001271}
1272
1273static const struct wl_seat_interface seat_interface = {
1274 seat_get_pointer,
1275 seat_get_keyboard,
1276 seat_get_touch,
1277};
1278
1279static void
1280bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
1281{
Kristian Høgsberge3148752013-05-06 23:19:49 -04001282 struct weston_seat *seat = data;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001283 struct wl_resource *resource;
1284 enum wl_seat_capability caps = 0;
1285
Jason Ekstranda85118c2013-06-27 20:17:02 -05001286 resource = wl_resource_create(client,
1287 &wl_seat_interface, MIN(version, 2), id);
Jason Ekstrand44a38632013-06-14 10:08:00 -05001288 wl_list_insert(&seat->base_resource_list, wl_resource_get_link(resource));
Jason Ekstranda85118c2013-06-27 20:17:02 -05001289 wl_resource_set_implementation(resource, &seat_interface, data,
1290 unbind_resource);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001291
1292 if (seat->pointer)
1293 caps |= WL_SEAT_CAPABILITY_POINTER;
1294 if (seat->keyboard)
1295 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
1296 if (seat->touch)
1297 caps |= WL_SEAT_CAPABILITY_TOUCH;
1298
1299 wl_seat_send_capabilities(resource, caps);
Rob Bradforde445ae62013-05-31 18:09:51 +01001300 if (version >= 2)
1301 wl_seat_send_name(resource, seat->seat_name);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001302}
1303
Rob Bradford382ff462013-06-24 16:52:45 +01001304#ifdef ENABLE_XKBCOMMON
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001305int
1306weston_compositor_xkb_init(struct weston_compositor *ec,
1307 struct xkb_rule_names *names)
1308{
Rob Bradford382ff462013-06-24 16:52:45 +01001309 ec->use_xkbcommon = 1;
Matt Roper01a92732013-06-24 16:52:44 +01001310
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001311 if (ec->xkb_context == NULL) {
1312 ec->xkb_context = xkb_context_new(0);
1313 if (ec->xkb_context == NULL) {
1314 weston_log("failed to create XKB context\n");
1315 return -1;
1316 }
1317 }
1318
1319 if (names)
1320 ec->xkb_names = *names;
1321 if (!ec->xkb_names.rules)
1322 ec->xkb_names.rules = strdup("evdev");
1323 if (!ec->xkb_names.model)
1324 ec->xkb_names.model = strdup("pc105");
1325 if (!ec->xkb_names.layout)
1326 ec->xkb_names.layout = strdup("us");
1327
1328 return 0;
1329}
1330
1331static void xkb_info_destroy(struct weston_xkb_info *xkb_info)
1332{
1333 if (xkb_info->keymap)
1334 xkb_map_unref(xkb_info->keymap);
1335
1336 if (xkb_info->keymap_area)
1337 munmap(xkb_info->keymap_area, xkb_info->keymap_size);
1338 if (xkb_info->keymap_fd >= 0)
1339 close(xkb_info->keymap_fd);
1340}
1341
1342void
1343weston_compositor_xkb_destroy(struct weston_compositor *ec)
1344{
Matt Roper01a92732013-06-24 16:52:44 +01001345 /*
1346 * If we're operating in raw keyboard mode, we never initialized
1347 * libxkbcommon so there's no cleanup to do either.
1348 */
1349 if (!ec->use_xkbcommon)
1350 return;
1351
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001352 free((char *) ec->xkb_names.rules);
1353 free((char *) ec->xkb_names.model);
1354 free((char *) ec->xkb_names.layout);
1355 free((char *) ec->xkb_names.variant);
1356 free((char *) ec->xkb_names.options);
1357
1358 xkb_info_destroy(&ec->xkb_info);
1359 xkb_context_unref(ec->xkb_context);
1360}
1361
1362static int
1363weston_xkb_info_new_keymap(struct weston_xkb_info *xkb_info)
1364{
1365 char *keymap_str;
1366
1367 xkb_info->shift_mod = xkb_map_mod_get_index(xkb_info->keymap,
1368 XKB_MOD_NAME_SHIFT);
1369 xkb_info->caps_mod = xkb_map_mod_get_index(xkb_info->keymap,
1370 XKB_MOD_NAME_CAPS);
1371 xkb_info->ctrl_mod = xkb_map_mod_get_index(xkb_info->keymap,
1372 XKB_MOD_NAME_CTRL);
1373 xkb_info->alt_mod = xkb_map_mod_get_index(xkb_info->keymap,
1374 XKB_MOD_NAME_ALT);
1375 xkb_info->mod2_mod = xkb_map_mod_get_index(xkb_info->keymap, "Mod2");
1376 xkb_info->mod3_mod = xkb_map_mod_get_index(xkb_info->keymap, "Mod3");
1377 xkb_info->super_mod = xkb_map_mod_get_index(xkb_info->keymap,
1378 XKB_MOD_NAME_LOGO);
1379 xkb_info->mod5_mod = xkb_map_mod_get_index(xkb_info->keymap, "Mod5");
1380
1381 xkb_info->num_led = xkb_map_led_get_index(xkb_info->keymap,
1382 XKB_LED_NAME_NUM);
1383 xkb_info->caps_led = xkb_map_led_get_index(xkb_info->keymap,
1384 XKB_LED_NAME_CAPS);
1385 xkb_info->scroll_led = xkb_map_led_get_index(xkb_info->keymap,
1386 XKB_LED_NAME_SCROLL);
1387
1388 keymap_str = xkb_map_get_as_string(xkb_info->keymap);
1389 if (keymap_str == NULL) {
1390 weston_log("failed to get string version of keymap\n");
1391 return -1;
1392 }
1393 xkb_info->keymap_size = strlen(keymap_str) + 1;
1394
1395 xkb_info->keymap_fd = os_create_anonymous_file(xkb_info->keymap_size);
1396 if (xkb_info->keymap_fd < 0) {
1397 weston_log("creating a keymap file for %lu bytes failed: %m\n",
1398 (unsigned long) xkb_info->keymap_size);
1399 goto err_keymap_str;
1400 }
1401
1402 xkb_info->keymap_area = mmap(NULL, xkb_info->keymap_size,
1403 PROT_READ | PROT_WRITE,
1404 MAP_SHARED, xkb_info->keymap_fd, 0);
1405 if (xkb_info->keymap_area == MAP_FAILED) {
1406 weston_log("failed to mmap() %lu bytes\n",
1407 (unsigned long) xkb_info->keymap_size);
1408 goto err_dev_zero;
1409 }
1410 strcpy(xkb_info->keymap_area, keymap_str);
1411 free(keymap_str);
1412
1413 return 0;
1414
1415err_dev_zero:
1416 close(xkb_info->keymap_fd);
1417 xkb_info->keymap_fd = -1;
1418err_keymap_str:
1419 free(keymap_str);
1420 return -1;
1421}
1422
1423static int
1424weston_compositor_build_global_keymap(struct weston_compositor *ec)
1425{
1426 if (ec->xkb_info.keymap != NULL)
1427 return 0;
1428
1429 ec->xkb_info.keymap = xkb_map_new_from_names(ec->xkb_context,
1430 &ec->xkb_names,
1431 0);
1432 if (ec->xkb_info.keymap == NULL) {
1433 weston_log("failed to compile global XKB keymap\n");
1434 weston_log(" tried rules %s, model %s, layout %s, variant %s, "
1435 "options %s\n",
1436 ec->xkb_names.rules, ec->xkb_names.model,
1437 ec->xkb_names.layout, ec->xkb_names.variant,
1438 ec->xkb_names.options);
1439 return -1;
1440 }
1441
1442 if (weston_xkb_info_new_keymap(&ec->xkb_info) < 0)
1443 return -1;
1444
1445 return 0;
1446}
Rob Bradford382ff462013-06-24 16:52:45 +01001447#else
1448int
1449weston_compositor_xkb_init(struct weston_compositor *ec,
1450 struct xkb_rule_names *names)
1451{
1452 return 0;
1453}
1454
1455void
1456weston_compositor_xkb_destroy(struct weston_compositor *ec)
1457{
1458}
1459#endif
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001460
1461WL_EXPORT int
1462weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap)
1463{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001464 struct weston_keyboard *keyboard;
1465
Kristian Høgsberg2bf87622013-05-07 23:17:41 -04001466 if (seat->keyboard)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001467 return 0;
1468
Rob Bradford382ff462013-06-24 16:52:45 +01001469#ifdef ENABLE_XKBCOMMON
Matt Roper01a92732013-06-24 16:52:44 +01001470 if (seat->compositor->use_xkbcommon) {
1471 if (keymap != NULL) {
1472 seat->xkb_info.keymap = xkb_map_ref(keymap);
1473 if (weston_xkb_info_new_keymap(&seat->xkb_info) < 0)
1474 return -1;
1475 } else {
1476 if (weston_compositor_build_global_keymap(seat->compositor) < 0)
1477 return -1;
1478 seat->xkb_info = seat->compositor->xkb_info;
1479 seat->xkb_info.keymap = xkb_map_ref(seat->xkb_info.keymap);
1480 }
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001481
Matt Roper01a92732013-06-24 16:52:44 +01001482 seat->xkb_state.state = xkb_state_new(seat->xkb_info.keymap);
1483 if (seat->xkb_state.state == NULL) {
1484 weston_log("failed to initialise XKB state\n");
1485 return -1;
1486 }
1487
1488 seat->xkb_state.leds = 0;
1489 }
Rob Bradford382ff462013-06-24 16:52:45 +01001490#endif
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001491
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001492 keyboard = weston_keyboard_create();
1493 if (keyboard == NULL) {
1494 weston_log("failed to allocate weston keyboard struct\n");
1495 return -1;
1496 }
1497
1498 seat->keyboard = keyboard;
1499 keyboard->seat = seat;
1500
1501 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001502
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001503 return 0;
1504}
1505
1506WL_EXPORT void
1507weston_seat_init_pointer(struct weston_seat *seat)
1508{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001509 struct weston_pointer *pointer;
1510
Kristian Høgsberg2bf87622013-05-07 23:17:41 -04001511 if (seat->pointer)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001512 return;
1513
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001514 pointer = weston_pointer_create();
1515 if (pointer == NULL)
1516 return;
1517
1518 seat->pointer = pointer;
1519 pointer->seat = seat;
1520
1521 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001522}
1523
1524WL_EXPORT void
1525weston_seat_init_touch(struct weston_seat *seat)
1526{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001527 struct weston_touch *touch;
1528
Kristian Høgsberg2bf87622013-05-07 23:17:41 -04001529 if (seat->touch)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001530 return;
1531
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001532 touch = weston_touch_create();
1533 if (touch == NULL)
1534 return;
1535
1536 seat->touch = touch;
1537 touch->seat = seat;
1538
1539 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001540}
1541
1542WL_EXPORT void
Rob Bradford9af5f9e2013-05-31 18:09:50 +01001543weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec,
1544 const char *seat_name)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001545{
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04001546 memset(seat, 0, sizeof *seat);
1547
Kristian Høgsberge3148752013-05-06 23:19:49 -04001548 seat->selection_data_source = NULL;
1549 wl_list_init(&seat->base_resource_list);
1550 wl_signal_init(&seat->selection_signal);
1551 wl_list_init(&seat->drag_resource_list);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001552 wl_signal_init(&seat->destroy_signal);
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04001553
Kristian Høgsberg919cddb2013-07-08 19:03:57 -04001554 seat->global = wl_global_create(ec->wl_display, &wl_seat_interface, 2,
1555 seat, bind_seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001556
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001557 seat->compositor = ec;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001558 seat->modifier_state = 0;
1559 seat->num_tp = 0;
Rob Bradford9af5f9e2013-05-31 18:09:50 +01001560 seat->seat_name = strdup(seat_name);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001561
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001562 wl_list_insert(ec->seat_list.prev, &seat->link);
1563
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001564 clipboard_create(seat);
1565
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001566 wl_signal_emit(&ec->seat_created_signal, seat);
1567}
1568
1569WL_EXPORT void
1570weston_seat_release(struct weston_seat *seat)
1571{
1572 wl_list_remove(&seat->link);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001573
Rob Bradford382ff462013-06-24 16:52:45 +01001574#ifdef ENABLE_XKBCOMMON
Matt Roper01a92732013-06-24 16:52:44 +01001575 if (seat->compositor->use_xkbcommon) {
1576 if (seat->xkb_state.state != NULL)
1577 xkb_state_unref(seat->xkb_state.state);
1578 xkb_info_destroy(&seat->xkb_info);
1579 }
Rob Bradford382ff462013-06-24 16:52:45 +01001580#endif
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001581
Kristian Høgsberge3148752013-05-06 23:19:49 -04001582 if (seat->pointer)
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001583 weston_pointer_destroy(seat->pointer);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001584 if (seat->keyboard)
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001585 weston_keyboard_destroy(seat->keyboard);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001586 if (seat->touch)
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001587 weston_touch_destroy(seat->touch);
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04001588
Rob Bradford9af5f9e2013-05-31 18:09:50 +01001589 free (seat->seat_name);
1590
Kristian Høgsberg919cddb2013-07-08 19:03:57 -04001591 wl_global_destroy(seat->global);
Kristian Høgsbergaaadc772013-07-08 16:20:31 -04001592
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001593 wl_signal_emit(&seat->destroy_signal, seat);
1594}