blob: 68cbbc8281cf409b663d36f4f22eb94efdb1ff18 [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;
Rob Bradford880ebc72013-07-22 17:31:38 +0100140 struct wl_display *display = compositor->wl_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) {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400145 serial = wl_display_next_serial(display);
146 wl_pointer_send_button(resource, serial, time, button, state_w);
147 }
148
149 if (pointer->button_count == 0 &&
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400150 state == WL_POINTER_BUTTON_STATE_RELEASED) {
151 surface = weston_compositor_pick_surface(compositor,
152 pointer->x,
153 pointer->y,
154 &sx, &sy);
155
156 weston_pointer_set_focus(pointer, surface, sx, sy);
157 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400158}
159
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400160static const struct weston_pointer_grab_interface
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400161 default_pointer_grab_interface = {
162 default_grab_focus,
163 default_grab_motion,
164 default_grab_button
165};
166
Kristian Høgsberge329f362013-05-06 22:19:57 -0400167static void
168default_grab_touch_down(struct weston_touch_grab *grab, uint32_t time,
169 int touch_id, wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400170{
Kristian Høgsberge329f362013-05-06 22:19:57 -0400171 struct weston_touch *touch = grab->touch;
Rob Bradford880ebc72013-07-22 17:31:38 +0100172 struct wl_display *display = touch->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400173 uint32_t serial;
174
175 if (touch->focus_resource && touch->focus) {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400176 serial = wl_display_next_serial(display);
177 wl_touch_send_down(touch->focus_resource, serial, time,
Jason Ekstrand26ed73c2013-06-06 22:34:41 -0500178 touch->focus->resource,
Kristian Høgsberge329f362013-05-06 22:19:57 -0400179 touch_id, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400180 }
181}
182
Kristian Høgsberge329f362013-05-06 22:19:57 -0400183static void
184default_grab_touch_up(struct weston_touch_grab *grab,
185 uint32_t time, int touch_id)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400186{
Kristian Høgsberge329f362013-05-06 22:19:57 -0400187 struct weston_touch *touch = grab->touch;
Rob Bradford880ebc72013-07-22 17:31:38 +0100188 struct wl_display *display = touch->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400189 uint32_t serial;
190
191 if (touch->focus_resource) {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400192 serial = wl_display_next_serial(display);
193 wl_touch_send_up(touch->focus_resource, serial, time, touch_id);
194 }
195}
196
Kristian Høgsberge329f362013-05-06 22:19:57 -0400197static void
198default_grab_touch_motion(struct weston_touch_grab *grab, uint32_t time,
199 int touch_id, wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400200{
Kristian Høgsberge329f362013-05-06 22:19:57 -0400201 struct weston_touch *touch = grab->touch;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400202
203 if (touch->focus_resource) {
204 wl_touch_send_motion(touch->focus_resource, time,
Kristian Høgsberge329f362013-05-06 22:19:57 -0400205 touch_id, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400206 }
207}
208
Kristian Høgsberge329f362013-05-06 22:19:57 -0400209static const struct weston_touch_grab_interface default_touch_grab_interface = {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400210 default_grab_touch_down,
211 default_grab_touch_up,
212 default_grab_touch_motion
213};
214
215static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400216default_grab_key(struct weston_keyboard_grab *grab,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400217 uint32_t time, uint32_t key, uint32_t state)
218{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400219 struct weston_keyboard *keyboard = grab->keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400220 struct wl_resource *resource;
Rob Bradford880ebc72013-07-22 17:31:38 +0100221 struct wl_display *display = keyboard->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400222 uint32_t serial;
223
224 resource = keyboard->focus_resource;
225 if (resource) {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400226 serial = wl_display_next_serial(display);
227 wl_keyboard_send_key(resource, serial, time, key, state);
228 }
229}
230
231static struct wl_resource *
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400232find_resource_for_surface(struct wl_list *list, struct weston_surface *surface)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400233{
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400234 if (!surface)
235 return NULL;
236
Jason Ekstrand44a38632013-06-14 10:08:00 -0500237 if (!surface->resource)
238 return NULL;
239
240 return wl_resource_find_for_client(list, wl_resource_get_client(surface->resource));
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400241}
242
243static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400244default_grab_modifiers(struct weston_keyboard_grab *grab, uint32_t serial,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400245 uint32_t mods_depressed, uint32_t mods_latched,
246 uint32_t mods_locked, uint32_t group)
247{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400248 struct weston_keyboard *keyboard = grab->keyboard;
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400249 struct weston_pointer *pointer = keyboard->seat->pointer;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400250 struct wl_resource *resource, *pr;
251
252 resource = keyboard->focus_resource;
253 if (!resource)
254 return;
255
256 wl_keyboard_send_modifiers(resource, serial, mods_depressed,
257 mods_latched, mods_locked, group);
258
259 if (pointer && pointer->focus && pointer->focus != keyboard->focus) {
260 pr = find_resource_for_surface(&keyboard->resource_list,
261 pointer->focus);
262 if (pr) {
263 wl_keyboard_send_modifiers(pr,
264 serial,
265 keyboard->modifiers.mods_depressed,
266 keyboard->modifiers.mods_latched,
267 keyboard->modifiers.mods_locked,
268 keyboard->modifiers.group);
269 }
270 }
271}
272
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400273static const struct weston_keyboard_grab_interface
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400274 default_keyboard_grab_interface = {
275 default_grab_key,
276 default_grab_modifiers,
277};
278
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400279static void
280pointer_unmap_sprite(struct weston_pointer *pointer)
281{
282 if (weston_surface_is_mapped(pointer->sprite))
283 weston_surface_unmap(pointer->sprite);
284
285 wl_list_remove(&pointer->sprite_destroy_listener.link);
286 pointer->sprite->configure = NULL;
287 pointer->sprite->configure_private = NULL;
288 pointer->sprite = NULL;
289}
290
291static void
292pointer_handle_sprite_destroy(struct wl_listener *listener, void *data)
293{
294 struct weston_pointer *pointer =
295 container_of(listener, struct weston_pointer,
296 sprite_destroy_listener);
297
298 pointer->sprite = NULL;
299}
300
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400301WL_EXPORT struct weston_pointer *
302weston_pointer_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400303{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400304 struct weston_pointer *pointer;
305
Peter Huttererf3d62272013-08-08 11:57:05 +1000306 pointer = zalloc(sizeof *pointer);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400307 if (pointer == NULL)
308 return NULL;
309
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400310 wl_list_init(&pointer->resource_list);
311 pointer->focus_listener.notify = lose_pointer_focus;
312 pointer->default_grab.interface = &default_pointer_grab_interface;
313 pointer->default_grab.pointer = pointer;
314 pointer->grab = &pointer->default_grab;
315 wl_signal_init(&pointer->focus_signal);
316
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400317 pointer->sprite_destroy_listener.notify = pointer_handle_sprite_destroy;
318
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400319 /* FIXME: Pick better co-ords. */
320 pointer->x = wl_fixed_from_int(100);
321 pointer->y = wl_fixed_from_int(100);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400322
323 return pointer;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400324}
325
326WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400327weston_pointer_destroy(struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400328{
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400329 if (pointer->sprite)
330 pointer_unmap_sprite(pointer);
331
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400332 /* XXX: What about pointer->resource_list? */
333 if (pointer->focus_resource)
334 wl_list_remove(&pointer->focus_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400335 free(pointer);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400336}
337
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400338WL_EXPORT struct weston_keyboard *
339weston_keyboard_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400340{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400341 struct weston_keyboard *keyboard;
342
Peter Huttererf3d62272013-08-08 11:57:05 +1000343 keyboard = zalloc(sizeof *keyboard);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400344 if (keyboard == NULL)
345 return NULL;
346
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400347 wl_list_init(&keyboard->resource_list);
348 wl_array_init(&keyboard->keys);
349 keyboard->focus_listener.notify = lose_keyboard_focus;
350 keyboard->default_grab.interface = &default_keyboard_grab_interface;
351 keyboard->default_grab.keyboard = keyboard;
352 keyboard->grab = &keyboard->default_grab;
353 wl_signal_init(&keyboard->focus_signal);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400354
355 return keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400356}
357
358WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400359weston_keyboard_destroy(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400360{
361 /* XXX: What about keyboard->resource_list? */
362 if (keyboard->focus_resource)
363 wl_list_remove(&keyboard->focus_listener.link);
364 wl_array_release(&keyboard->keys);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400365 free(keyboard);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400366}
367
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400368WL_EXPORT struct weston_touch *
369weston_touch_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400370{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400371 struct weston_touch *touch;
372
Peter Huttererf3d62272013-08-08 11:57:05 +1000373 touch = zalloc(sizeof *touch);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400374 if (touch == NULL)
375 return NULL;
376
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400377 wl_list_init(&touch->resource_list);
378 touch->focus_listener.notify = lose_touch_focus;
379 touch->default_grab.interface = &default_touch_grab_interface;
380 touch->default_grab.touch = touch;
381 touch->grab = &touch->default_grab;
382 wl_signal_init(&touch->focus_signal);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400383
384 return touch;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400385}
386
387WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400388weston_touch_destroy(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400389{
390 /* XXX: What about touch->resource_list? */
391 if (touch->focus_resource)
392 wl_list_remove(&touch->focus_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400393 free(touch);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400394}
395
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400396static void
Kristian Høgsberge3148752013-05-06 23:19:49 -0400397seat_send_updated_caps(struct weston_seat *seat)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400398{
Jason Ekstrand44a38632013-06-14 10:08:00 -0500399 struct wl_list *link;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400400 enum wl_seat_capability caps = 0;
401
402 if (seat->pointer)
403 caps |= WL_SEAT_CAPABILITY_POINTER;
404 if (seat->keyboard)
405 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
406 if (seat->touch)
407 caps |= WL_SEAT_CAPABILITY_TOUCH;
408
Jason Ekstrand44a38632013-06-14 10:08:00 -0500409 for (link = seat->base_resource_list.next;
410 link != &seat->base_resource_list; link = link->next) {
411 wl_seat_send_capabilities(wl_resource_from_link(link), caps);
412 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400413}
414
415WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400416weston_pointer_set_focus(struct weston_pointer *pointer,
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400417 struct weston_surface *surface,
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400418 wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400419{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400420 struct weston_keyboard *kbd = pointer->seat->keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400421 struct wl_resource *resource, *kr;
Rob Bradford880ebc72013-07-22 17:31:38 +0100422 struct wl_display *display = pointer->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400423 uint32_t serial;
424
425 resource = pointer->focus_resource;
426 if (resource && pointer->focus != surface) {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400427 serial = wl_display_next_serial(display);
428 wl_pointer_send_leave(resource, serial,
Jason Ekstrand26ed73c2013-06-06 22:34:41 -0500429 pointer->focus->resource);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400430 wl_list_remove(&pointer->focus_listener.link);
431 }
432
433 resource = find_resource_for_surface(&pointer->resource_list,
434 surface);
435 if (resource &&
436 (pointer->focus != surface ||
437 pointer->focus_resource != resource)) {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400438 serial = wl_display_next_serial(display);
439 if (kbd) {
440 kr = find_resource_for_surface(&kbd->resource_list,
441 surface);
442 if (kr) {
443 wl_keyboard_send_modifiers(kr,
444 serial,
445 kbd->modifiers.mods_depressed,
446 kbd->modifiers.mods_latched,
447 kbd->modifiers.mods_locked,
448 kbd->modifiers.group);
449 }
450 }
Jason Ekstrand26ed73c2013-06-06 22:34:41 -0500451 wl_pointer_send_enter(resource, serial, surface->resource,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400452 sx, sy);
Jason Ekstrand44a38632013-06-14 10:08:00 -0500453 wl_resource_add_destroy_listener(resource,
454 &pointer->focus_listener);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400455 pointer->focus_serial = serial;
456 }
457
458 pointer->focus_resource = resource;
459 pointer->focus = surface;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400460 wl_signal_emit(&pointer->focus_signal, pointer);
461}
462
463WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400464weston_keyboard_set_focus(struct weston_keyboard *keyboard,
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400465 struct weston_surface *surface)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400466{
467 struct wl_resource *resource;
Rob Bradford880ebc72013-07-22 17:31:38 +0100468 struct wl_display *display = keyboard->seat->compositor->wl_display;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400469 uint32_t serial;
470
471 if (keyboard->focus_resource && keyboard->focus != surface) {
472 resource = keyboard->focus_resource;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400473 serial = wl_display_next_serial(display);
474 wl_keyboard_send_leave(resource, serial,
Jason Ekstrand26ed73c2013-06-06 22:34:41 -0500475 keyboard->focus->resource);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400476 wl_list_remove(&keyboard->focus_listener.link);
477 }
478
479 resource = find_resource_for_surface(&keyboard->resource_list,
480 surface);
481 if (resource &&
482 (keyboard->focus != surface ||
483 keyboard->focus_resource != resource)) {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400484 serial = wl_display_next_serial(display);
485 wl_keyboard_send_modifiers(resource, serial,
486 keyboard->modifiers.mods_depressed,
487 keyboard->modifiers.mods_latched,
488 keyboard->modifiers.mods_locked,
489 keyboard->modifiers.group);
Jason Ekstrand26ed73c2013-06-06 22:34:41 -0500490 wl_keyboard_send_enter(resource, serial, surface->resource,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400491 &keyboard->keys);
Jason Ekstrand44a38632013-06-14 10:08:00 -0500492 wl_resource_add_destroy_listener(resource,
493 &keyboard->focus_listener);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400494 keyboard->focus_serial = serial;
495 }
496
497 keyboard->focus_resource = resource;
498 keyboard->focus = surface;
499 wl_signal_emit(&keyboard->focus_signal, keyboard);
500}
501
502WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400503weston_keyboard_start_grab(struct weston_keyboard *keyboard,
504 struct weston_keyboard_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400505{
506 keyboard->grab = grab;
507 grab->keyboard = keyboard;
508
509 /* XXX focus? */
510}
511
512WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400513weston_keyboard_end_grab(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400514{
515 keyboard->grab = &keyboard->default_grab;
516}
517
518WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400519weston_pointer_start_grab(struct weston_pointer *pointer,
520 struct weston_pointer_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400521{
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400522 pointer->grab = grab;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400523 grab->pointer = pointer;
Kristian Høgsbergda751b82013-07-04 00:58:07 -0400524 pointer->grab->interface->focus(pointer->grab);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400525}
526
527WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400528weston_pointer_end_grab(struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400529{
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400530 pointer->grab = &pointer->default_grab;
Kristian Høgsbergda751b82013-07-04 00:58:07 -0400531 pointer->grab->interface->focus(pointer->grab);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400532}
533
534WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -0400535weston_touch_start_grab(struct weston_touch *touch, struct weston_touch_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400536{
537 touch->grab = grab;
538 grab->touch = touch;
539}
540
541WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -0400542weston_touch_end_grab(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400543{
544 touch->grab = &touch->default_grab;
545}
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400546
Rob Bradford806d8c02013-06-25 18:56:41 +0100547WL_EXPORT void
548weston_pointer_clamp(struct weston_pointer *pointer, wl_fixed_t *fx, wl_fixed_t *fy)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400549{
Rob Bradford806d8c02013-06-25 18:56:41 +0100550 struct weston_compositor *ec = pointer->seat->compositor;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400551 struct weston_output *output, *prev = NULL;
552 int x, y, old_x, old_y, valid = 0;
553
554 x = wl_fixed_to_int(*fx);
555 y = wl_fixed_to_int(*fy);
Rob Bradford806d8c02013-06-25 18:56:41 +0100556 old_x = wl_fixed_to_int(pointer->x);
557 old_y = wl_fixed_to_int(pointer->y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400558
559 wl_list_for_each(output, &ec->output_list, link) {
Rob Bradford66bd9f52013-06-25 18:56:42 +0100560 if (pointer->seat->output && pointer->seat->output != output)
561 continue;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400562 if (pixman_region32_contains_point(&output->region,
563 x, y, NULL))
564 valid = 1;
565 if (pixman_region32_contains_point(&output->region,
566 old_x, old_y, NULL))
567 prev = output;
568 }
569
Rob Bradford66bd9f52013-06-25 18:56:42 +0100570 if (!prev)
571 prev = pointer->seat->output;
572
573 if (prev && !valid) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400574 if (x < prev->x)
575 *fx = wl_fixed_from_int(prev->x);
576 else if (x >= prev->x + prev->width)
577 *fx = wl_fixed_from_int(prev->x +
578 prev->width - 1);
579 if (y < prev->y)
580 *fy = wl_fixed_from_int(prev->y);
Alexander Larssonbcd18d92013-05-28 16:23:33 +0200581 else if (y >= prev->y + prev->height)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400582 *fy = wl_fixed_from_int(prev->y +
583 prev->height - 1);
584 }
585}
586
587/* Takes absolute values */
588static void
589move_pointer(struct weston_seat *seat, wl_fixed_t x, wl_fixed_t y)
590{
591 struct weston_compositor *ec = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400592 struct weston_pointer *pointer = seat->pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400593 struct weston_output *output;
594 int32_t ix, iy;
595
Rob Bradford806d8c02013-06-25 18:56:41 +0100596 weston_pointer_clamp (pointer, &x, &y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400597
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400598 pointer->x = x;
599 pointer->y = y;
600
601 ix = wl_fixed_to_int(x);
602 iy = wl_fixed_to_int(y);
603
604 wl_list_for_each(output, &ec->output_list, link)
605 if (output->zoom.active &&
606 pixman_region32_contains_point(&output->region,
607 ix, iy, NULL))
608 weston_output_update_zoom(output, ZOOM_FOCUS_POINTER);
609
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400610 if (pointer->sprite) {
611 weston_surface_set_position(pointer->sprite,
612 ix - pointer->hotspot_x,
613 iy - pointer->hotspot_y);
614 weston_surface_schedule_repaint(pointer->sprite);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400615 }
616}
617
618WL_EXPORT void
619notify_motion(struct weston_seat *seat,
620 uint32_t time, wl_fixed_t dx, wl_fixed_t dy)
621{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400622 struct weston_compositor *ec = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400623 struct weston_pointer *pointer = seat->pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400624
625 weston_compositor_wake(ec);
626
627 move_pointer(seat, pointer->x + dx, pointer->y + dy);
628
Kristian Høgsbergda751b82013-07-04 00:58:07 -0400629 pointer->grab->interface->focus(pointer->grab);
630 pointer->grab->interface->motion(pointer->grab, time);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400631}
632
633WL_EXPORT void
634notify_motion_absolute(struct weston_seat *seat,
635 uint32_t time, wl_fixed_t x, wl_fixed_t y)
636{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400637 struct weston_compositor *ec = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400638 struct weston_pointer *pointer = seat->pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400639
640 weston_compositor_wake(ec);
641
642 move_pointer(seat, x, y);
643
Kristian Høgsbergda751b82013-07-04 00:58:07 -0400644 pointer->grab->interface->focus(pointer->grab);
645 pointer->grab->interface->motion(pointer->grab, time);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400646}
647
648WL_EXPORT void
649weston_surface_activate(struct weston_surface *surface,
650 struct weston_seat *seat)
651{
652 struct weston_compositor *compositor = seat->compositor;
653
Kristian Høgsberge3148752013-05-06 23:19:49 -0400654 if (seat->keyboard) {
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400655 weston_keyboard_set_focus(seat->keyboard, surface);
Kristian Høgsberge3148752013-05-06 23:19:49 -0400656 wl_data_device_set_keyboard_focus(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400657 }
658
659 wl_signal_emit(&compositor->activate_signal, surface);
660}
661
662WL_EXPORT void
663notify_button(struct weston_seat *seat, uint32_t time, int32_t button,
664 enum wl_pointer_button_state state)
665{
666 struct weston_compositor *compositor = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400667 struct weston_pointer *pointer = seat->pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400668 struct weston_surface *focus =
669 (struct weston_surface *) pointer->focus;
670 uint32_t serial = wl_display_next_serial(compositor->wl_display);
671
672 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
673 if (compositor->ping_handler && focus)
674 compositor->ping_handler(focus, serial);
675 weston_compositor_idle_inhibit(compositor);
676 if (pointer->button_count == 0) {
677 pointer->grab_button = button;
678 pointer->grab_time = time;
679 pointer->grab_x = pointer->x;
680 pointer->grab_y = pointer->y;
681 }
682 pointer->button_count++;
683 } else {
684 weston_compositor_idle_release(compositor);
685 pointer->button_count--;
686 }
687
688 weston_compositor_run_button_binding(compositor, seat, time, button,
689 state);
690
691 pointer->grab->interface->button(pointer->grab, time, button, state);
692
693 if (pointer->button_count == 1)
694 pointer->grab_serial =
695 wl_display_get_serial(compositor->wl_display);
696}
697
698WL_EXPORT void
699notify_axis(struct weston_seat *seat, uint32_t time, uint32_t axis,
700 wl_fixed_t value)
701{
702 struct weston_compositor *compositor = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400703 struct weston_pointer *pointer = seat->pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400704 struct weston_surface *focus =
705 (struct weston_surface *) pointer->focus;
706 uint32_t serial = wl_display_next_serial(compositor->wl_display);
707
708 if (compositor->ping_handler && focus)
709 compositor->ping_handler(focus, serial);
710
711 weston_compositor_wake(compositor);
712
713 if (!value)
714 return;
715
716 if (weston_compositor_run_axis_binding(compositor, seat,
717 time, axis, value))
718 return;
719
720 if (pointer->focus_resource)
721 wl_pointer_send_axis(pointer->focus_resource, time, axis,
722 value);
723}
724
Rob Bradford382ff462013-06-24 16:52:45 +0100725#ifdef ENABLE_XKBCOMMON
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400726WL_EXPORT void
727notify_modifiers(struct weston_seat *seat, uint32_t serial)
728{
Kristian Høgsberge3148752013-05-06 23:19:49 -0400729 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400730 struct weston_keyboard_grab *grab = keyboard->grab;
731 uint32_t mods_depressed, mods_latched, mods_locked, group;
732 uint32_t mods_lookup;
733 enum weston_led leds = 0;
734 int changed = 0;
735
736 /* Serialize and update our internal state, checking to see if it's
737 * different to the previous state. */
738 mods_depressed = xkb_state_serialize_mods(seat->xkb_state.state,
739 XKB_STATE_DEPRESSED);
740 mods_latched = xkb_state_serialize_mods(seat->xkb_state.state,
741 XKB_STATE_LATCHED);
742 mods_locked = xkb_state_serialize_mods(seat->xkb_state.state,
743 XKB_STATE_LOCKED);
744 group = xkb_state_serialize_group(seat->xkb_state.state,
745 XKB_STATE_EFFECTIVE);
746
Kristian Høgsberge3148752013-05-06 23:19:49 -0400747 if (mods_depressed != seat->keyboard->modifiers.mods_depressed ||
748 mods_latched != seat->keyboard->modifiers.mods_latched ||
749 mods_locked != seat->keyboard->modifiers.mods_locked ||
750 group != seat->keyboard->modifiers.group)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400751 changed = 1;
752
Kristian Høgsberge3148752013-05-06 23:19:49 -0400753 seat->keyboard->modifiers.mods_depressed = mods_depressed;
754 seat->keyboard->modifiers.mods_latched = mods_latched;
755 seat->keyboard->modifiers.mods_locked = mods_locked;
756 seat->keyboard->modifiers.group = group;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400757
758 /* And update the modifier_state for bindings. */
759 mods_lookup = mods_depressed | mods_latched;
760 seat->modifier_state = 0;
761 if (mods_lookup & (1 << seat->xkb_info.ctrl_mod))
762 seat->modifier_state |= MODIFIER_CTRL;
763 if (mods_lookup & (1 << seat->xkb_info.alt_mod))
764 seat->modifier_state |= MODIFIER_ALT;
765 if (mods_lookup & (1 << seat->xkb_info.super_mod))
766 seat->modifier_state |= MODIFIER_SUPER;
767 if (mods_lookup & (1 << seat->xkb_info.shift_mod))
768 seat->modifier_state |= MODIFIER_SHIFT;
769
770 /* Finally, notify the compositor that LEDs have changed. */
771 if (xkb_state_led_index_is_active(seat->xkb_state.state,
772 seat->xkb_info.num_led))
773 leds |= LED_NUM_LOCK;
774 if (xkb_state_led_index_is_active(seat->xkb_state.state,
775 seat->xkb_info.caps_led))
776 leds |= LED_CAPS_LOCK;
777 if (xkb_state_led_index_is_active(seat->xkb_state.state,
778 seat->xkb_info.scroll_led))
779 leds |= LED_SCROLL_LOCK;
780 if (leds != seat->xkb_state.leds && seat->led_update)
781 seat->led_update(seat, leds);
782 seat->xkb_state.leds = leds;
783
784 if (changed) {
785 grab->interface->modifiers(grab,
786 serial,
787 keyboard->modifiers.mods_depressed,
788 keyboard->modifiers.mods_latched,
789 keyboard->modifiers.mods_locked,
790 keyboard->modifiers.group);
791 }
792}
793
794static void
795update_modifier_state(struct weston_seat *seat, uint32_t serial, uint32_t key,
796 enum wl_keyboard_key_state state)
797{
798 enum xkb_key_direction direction;
799
Matt Roper01a92732013-06-24 16:52:44 +0100800 /* Keyboard modifiers don't exist in raw keyboard mode */
801 if (!seat->compositor->use_xkbcommon)
802 return;
803
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400804 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
805 direction = XKB_KEY_DOWN;
806 else
807 direction = XKB_KEY_UP;
808
809 /* Offset the keycode by 8, as the evdev XKB rules reflect X's
810 * broken keycode system, which starts at 8. */
811 xkb_state_update_key(seat->xkb_state.state, key + 8, direction);
812
813 notify_modifiers(seat, serial);
814}
Rob Bradford382ff462013-06-24 16:52:45 +0100815#else
816WL_EXPORT void
817notify_modifiers(struct weston_seat *seat, uint32_t serial)
818{
819}
820
821static void
822update_modifier_state(struct weston_seat *seat, uint32_t serial, uint32_t key,
823 enum wl_keyboard_key_state state)
824{
825}
826#endif
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400827
828WL_EXPORT void
829notify_key(struct weston_seat *seat, uint32_t time, uint32_t key,
830 enum wl_keyboard_key_state state,
831 enum weston_key_state_update update_state)
832{
833 struct weston_compositor *compositor = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400834 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400835 struct weston_surface *focus =
836 (struct weston_surface *) keyboard->focus;
837 struct weston_keyboard_grab *grab = keyboard->grab;
838 uint32_t serial = wl_display_next_serial(compositor->wl_display);
839 uint32_t *k, *end;
840
841 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
842 if (compositor->ping_handler && focus)
843 compositor->ping_handler(focus, serial);
844
845 weston_compositor_idle_inhibit(compositor);
846 keyboard->grab_key = key;
847 keyboard->grab_time = time;
848 } else {
849 weston_compositor_idle_release(compositor);
850 }
851
852 end = keyboard->keys.data + keyboard->keys.size;
853 for (k = keyboard->keys.data; k < end; k++) {
854 if (*k == key) {
855 /* Ignore server-generated repeats. */
856 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
857 return;
858 *k = *--end;
859 }
860 }
861 keyboard->keys.size = (void *) end - keyboard->keys.data;
862 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
863 k = wl_array_add(&keyboard->keys, sizeof *k);
864 *k = key;
865 }
866
867 if (grab == &keyboard->default_grab ||
868 grab == &keyboard->input_method_grab) {
869 weston_compositor_run_key_binding(compositor, seat, time, key,
870 state);
871 grab = keyboard->grab;
872 }
873
874 grab->interface->key(grab, time, key, state);
875
876 if (update_state == STATE_UPDATE_AUTOMATIC) {
877 update_modifier_state(seat,
878 wl_display_get_serial(compositor->wl_display),
879 key,
880 state);
881 }
882}
883
884WL_EXPORT void
885notify_pointer_focus(struct weston_seat *seat, struct weston_output *output,
886 wl_fixed_t x, wl_fixed_t y)
887{
888 struct weston_compositor *compositor = seat->compositor;
889
890 if (output) {
891 move_pointer(seat, x, y);
892 compositor->focus = 1;
893 } else {
894 compositor->focus = 0;
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400895 /* FIXME: We should call weston_pointer_set_focus(seat,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400896 * NULL) here, but somehow that breaks re-entry... */
897 }
898}
899
900static void
901destroy_device_saved_kbd_focus(struct wl_listener *listener, void *data)
902{
903 struct weston_seat *ws;
904
905 ws = container_of(listener, struct weston_seat,
906 saved_kbd_focus_listener);
907
908 ws->saved_kbd_focus = NULL;
909}
910
911WL_EXPORT void
912notify_keyboard_focus_in(struct weston_seat *seat, struct wl_array *keys,
913 enum weston_key_state_update update_state)
914{
915 struct weston_compositor *compositor = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400916 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400917 struct weston_surface *surface;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400918 uint32_t *k, serial;
919
920 serial = wl_display_next_serial(compositor->wl_display);
921 wl_array_copy(&keyboard->keys, keys);
922 wl_array_for_each(k, &keyboard->keys) {
923 weston_compositor_idle_inhibit(compositor);
924 if (update_state == STATE_UPDATE_AUTOMATIC)
925 update_modifier_state(seat, serial, *k,
926 WL_KEYBOARD_KEY_STATE_PRESSED);
927 }
928
929 /* Run key bindings after we've updated the state. */
930 wl_array_for_each(k, &keyboard->keys) {
931 weston_compositor_run_key_binding(compositor, seat, 0, *k,
932 WL_KEYBOARD_KEY_STATE_PRESSED);
933 }
934
935 surface = seat->saved_kbd_focus;
936
937 if (surface) {
938 wl_list_remove(&seat->saved_kbd_focus_listener.link);
939 weston_keyboard_set_focus(keyboard, surface);
940 seat->saved_kbd_focus = NULL;
941 }
942}
943
944WL_EXPORT void
945notify_keyboard_focus_out(struct weston_seat *seat)
946{
947 struct weston_compositor *compositor = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400948 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400949 uint32_t *k, serial;
950
951 serial = wl_display_next_serial(compositor->wl_display);
952 wl_array_for_each(k, &keyboard->keys) {
953 weston_compositor_idle_release(compositor);
954 update_modifier_state(seat, serial, *k,
955 WL_KEYBOARD_KEY_STATE_RELEASED);
956 }
957
958 seat->modifier_state = 0;
959
960 if (keyboard->focus) {
961 seat->saved_kbd_focus = keyboard->focus;
962 seat->saved_kbd_focus_listener.notify =
963 destroy_device_saved_kbd_focus;
Jason Ekstrand26ed73c2013-06-06 22:34:41 -0500964 wl_signal_add(&keyboard->focus->destroy_signal,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400965 &seat->saved_kbd_focus_listener);
966 }
967
968 weston_keyboard_set_focus(keyboard, NULL);
969 /* FIXME: We really need keyboard grab cancel here to
970 * let the grab shut down properly. As it is we leak
971 * the grab data. */
972 weston_keyboard_end_grab(keyboard);
973}
974
Michael Fua2bb7912013-07-23 15:51:06 +0800975WL_EXPORT void
976weston_touch_set_focus(struct weston_seat *seat, struct weston_surface *surface)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400977{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400978 struct wl_resource *resource;
979
980 if (seat->touch->focus == surface)
981 return;
982
983 if (seat->touch->focus_resource)
984 wl_list_remove(&seat->touch->focus_listener.link);
985 seat->touch->focus = NULL;
986 seat->touch->focus_resource = NULL;
987
988 if (surface) {
989 resource =
Kristian Høgsberg80fb82d2013-05-06 21:49:55 -0400990 find_resource_for_surface(&seat->touch->resource_list,
991 surface);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400992 if (!resource) {
993 weston_log("couldn't find resource\n");
994 return;
995 }
996
997 seat->touch->focus = surface;
998 seat->touch->focus_resource = resource;
Jason Ekstrand44a38632013-06-14 10:08:00 -0500999 wl_resource_add_destroy_listener(resource,
1000 &seat->touch->focus_listener);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001001 }
1002}
1003
1004/**
1005 * notify_touch - emulates button touches and notifies surfaces accordingly.
1006 *
1007 * It assumes always the correct cycle sequence until it gets here: touch_down
1008 * → touch_update → ... → touch_update → touch_end. The driver is responsible
1009 * for sending along such order.
1010 *
1011 */
1012WL_EXPORT void
1013notify_touch(struct weston_seat *seat, uint32_t time, int touch_id,
1014 wl_fixed_t x, wl_fixed_t y, int touch_type)
1015{
1016 struct weston_compositor *ec = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -04001017 struct weston_touch *touch = seat->touch;
Kristian Høgsberge329f362013-05-06 22:19:57 -04001018 struct weston_touch_grab *grab = touch->grab;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001019 struct weston_surface *es;
1020 wl_fixed_t sx, sy;
1021
1022 /* Update grab's global coordinates. */
1023 touch->grab_x = x;
1024 touch->grab_y = y;
1025
1026 switch (touch_type) {
1027 case WL_TOUCH_DOWN:
1028 weston_compositor_idle_inhibit(ec);
1029
1030 seat->num_tp++;
1031
1032 /* the first finger down picks the surface, and all further go
1033 * to that surface for the remainder of the touch session i.e.
1034 * until all touch points are up again. */
1035 if (seat->num_tp == 1) {
1036 es = weston_compositor_pick_surface(ec, x, y, &sx, &sy);
Michael Fua2bb7912013-07-23 15:51:06 +08001037 weston_touch_set_focus(seat, es);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001038 } else if (touch->focus) {
1039 es = (struct weston_surface *) touch->focus;
1040 weston_surface_from_global_fixed(es, x, y, &sx, &sy);
1041 } else {
1042 /* Unexpected condition: We have non-initial touch but
1043 * there is no focused surface.
1044 */
1045 weston_log("touch event received with %d points down"
1046 "but no surface focused\n", seat->num_tp);
1047 return;
1048 }
1049
1050 grab->interface->down(grab, time, touch_id, sx, sy);
Rusty Lynchf1407ff2013-08-08 21:13:57 -07001051 if (seat->num_tp == 1) {
1052 touch->grab_serial =
1053 wl_display_get_serial(ec->wl_display);
1054 touch->grab_time = time;
1055 touch->grab_x = x;
1056 touch->grab_y = y;
1057 }
1058
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001059 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}