blob: 93cdf60ca776b75e21ed5e370c38dce3caa90053 [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>
Kristian Høgsberg2158a882013-04-18 15:07:39 -040029
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040030#include "../shared/os-compatibility.h"
Kristian Høgsberg2158a882013-04-18 15:07:39 -040031#include "compositor.h"
32
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040033static void
34empty_region(pixman_region32_t *region)
35{
36 pixman_region32_fini(region);
37 pixman_region32_init(region);
38}
39
40static void unbind_resource(struct wl_resource *resource)
41{
42 wl_list_remove(&resource->link);
43 free(resource);
44}
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øgsberg02bbabb2013-05-06 22:15:05 -040049 const struct weston_pointer_grab_interface *interface;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040050 struct weston_surface *surface, *focus;
Kristian Høgsberge3148752013-05-06 23:19:49 -040051 struct weston_pointer *pointer = seat->pointer;
Kristian Høgsberge122b7b2013-05-08 16:47:00 -040052 wl_fixed_t sx, sy;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040053
54 if (!pointer)
55 return;
56
57 surface = weston_compositor_pick_surface(seat->compositor,
58 pointer->x,
59 pointer->y,
Kristian Høgsberge122b7b2013-05-08 16:47:00 -040060 &sx, &sy);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040061
Kristian Høgsberge122b7b2013-05-08 16:47:00 -040062 interface = pointer->grab->interface;
63 interface->focus(pointer->grab, surface, sx, sy);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040064
65 focus = (struct weston_surface *) pointer->grab->focus;
66 if (focus)
67 weston_surface_from_global_fixed(focus,
68 pointer->x,
69 pointer->y,
70 &pointer->grab->x,
71 &pointer->grab->y);
72}
73
74static void
75weston_compositor_idle_inhibit(struct weston_compositor *compositor)
76{
77 weston_compositor_wake(compositor);
78 compositor->idle_inhibit++;
79}
80
81static void
82weston_compositor_idle_release(struct weston_compositor *compositor)
83{
84 compositor->idle_inhibit--;
85 weston_compositor_wake(compositor);
86}
87
Kristian Høgsberg2158a882013-04-18 15:07:39 -040088static void
89lose_pointer_focus(struct wl_listener *listener, void *data)
90{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -040091 struct weston_pointer *pointer =
92 container_of(listener, struct weston_pointer, focus_listener);
Kristian Høgsberg2158a882013-04-18 15:07:39 -040093
94 pointer->focus_resource = NULL;
95}
96
97static void
98lose_keyboard_focus(struct wl_listener *listener, void *data)
99{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400100 struct weston_keyboard *keyboard =
101 container_of(listener, struct weston_keyboard, focus_listener);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400102
103 keyboard->focus_resource = NULL;
104}
105
106static void
107lose_touch_focus(struct wl_listener *listener, void *data)
108{
Kristian Høgsberge329f362013-05-06 22:19:57 -0400109 struct weston_touch *touch =
110 container_of(listener, struct weston_touch, focus_listener);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400111
112 touch->focus_resource = NULL;
113}
114
115static void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400116default_grab_focus(struct weston_pointer_grab *grab,
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400117 struct weston_surface *surface, wl_fixed_t x, wl_fixed_t y)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400118{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400119 struct weston_pointer *pointer = grab->pointer;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400120
121 if (pointer->button_count > 0)
122 return;
123
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400124 if (pointer->focus != surface)
125 weston_pointer_set_focus(pointer, surface, x, y);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400126}
127
128static void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400129default_grab_motion(struct weston_pointer_grab *grab,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400130 uint32_t time, wl_fixed_t x, wl_fixed_t y)
131{
132 struct wl_resource *resource;
133
134 resource = grab->pointer->focus_resource;
135 if (resource)
136 wl_pointer_send_motion(resource, time, x, y);
137}
138
139static void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400140default_grab_button(struct weston_pointer_grab *grab,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400141 uint32_t time, uint32_t button, uint32_t state_w)
142{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400143 struct weston_pointer *pointer = grab->pointer;
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400144 struct weston_compositor *compositor = pointer->seat->compositor;
145 struct weston_surface *surface;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400146 struct wl_resource *resource;
147 uint32_t serial;
148 enum wl_pointer_button_state state = state_w;
149 struct wl_display *display;
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400150 wl_fixed_t sx, sy;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400151
152 resource = pointer->focus_resource;
153 if (resource) {
154 display = wl_client_get_display(resource->client);
155 serial = wl_display_next_serial(display);
156 wl_pointer_send_button(resource, serial, time, button, state_w);
157 }
158
159 if (pointer->button_count == 0 &&
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400160 state == WL_POINTER_BUTTON_STATE_RELEASED) {
161 surface = weston_compositor_pick_surface(compositor,
162 pointer->x,
163 pointer->y,
164 &sx, &sy);
165
166 weston_pointer_set_focus(pointer, surface, sx, sy);
167 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400168}
169
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400170static const struct weston_pointer_grab_interface
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400171 default_pointer_grab_interface = {
172 default_grab_focus,
173 default_grab_motion,
174 default_grab_button
175};
176
Kristian Høgsberge329f362013-05-06 22:19:57 -0400177static void
178default_grab_touch_down(struct weston_touch_grab *grab, uint32_t time,
179 int touch_id, wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400180{
Kristian Høgsberge329f362013-05-06 22:19:57 -0400181 struct weston_touch *touch = grab->touch;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400182 struct wl_display *display;
183 uint32_t serial;
184
185 if (touch->focus_resource && touch->focus) {
186 display = wl_client_get_display(touch->focus_resource->client);
187 serial = wl_display_next_serial(display);
188 wl_touch_send_down(touch->focus_resource, serial, time,
Kristian Høgsberge329f362013-05-06 22:19:57 -0400189 &touch->focus->resource,
190 touch_id, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400191 }
192}
193
Kristian Høgsberge329f362013-05-06 22:19:57 -0400194static void
195default_grab_touch_up(struct weston_touch_grab *grab,
196 uint32_t time, int touch_id)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400197{
Kristian Høgsberge329f362013-05-06 22:19:57 -0400198 struct weston_touch *touch = grab->touch;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400199 struct wl_display *display;
200 uint32_t serial;
201
202 if (touch->focus_resource) {
203 display = wl_client_get_display(touch->focus_resource->client);
204 serial = wl_display_next_serial(display);
205 wl_touch_send_up(touch->focus_resource, serial, time, touch_id);
206 }
207}
208
Kristian Høgsberge329f362013-05-06 22:19:57 -0400209static void
210default_grab_touch_motion(struct weston_touch_grab *grab, uint32_t time,
211 int touch_id, wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400212{
Kristian Høgsberge329f362013-05-06 22:19:57 -0400213 struct weston_touch *touch = grab->touch;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400214
215 if (touch->focus_resource) {
216 wl_touch_send_motion(touch->focus_resource, time,
Kristian Høgsberge329f362013-05-06 22:19:57 -0400217 touch_id, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400218 }
219}
220
Kristian Høgsberge329f362013-05-06 22:19:57 -0400221static const struct weston_touch_grab_interface default_touch_grab_interface = {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400222 default_grab_touch_down,
223 default_grab_touch_up,
224 default_grab_touch_motion
225};
226
227static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400228default_grab_key(struct weston_keyboard_grab *grab,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400229 uint32_t time, uint32_t key, uint32_t state)
230{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400231 struct weston_keyboard *keyboard = grab->keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400232 struct wl_resource *resource;
233 struct wl_display *display;
234 uint32_t serial;
235
236 resource = keyboard->focus_resource;
237 if (resource) {
238 display = wl_client_get_display(resource->client);
239 serial = wl_display_next_serial(display);
240 wl_keyboard_send_key(resource, serial, time, key, state);
241 }
242}
243
244static struct wl_resource *
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400245find_resource_for_surface(struct wl_list *list, struct weston_surface *surface)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400246{
247 struct wl_resource *r;
248
249 if (!surface)
250 return NULL;
251
252 wl_list_for_each(r, list, link) {
253 if (r->client == surface->resource.client)
254 return r;
255 }
256
257 return NULL;
258}
259
260static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400261default_grab_modifiers(struct weston_keyboard_grab *grab, uint32_t serial,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400262 uint32_t mods_depressed, uint32_t mods_latched,
263 uint32_t mods_locked, uint32_t group)
264{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400265 struct weston_keyboard *keyboard = grab->keyboard;
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400266 struct weston_pointer *pointer = keyboard->seat->pointer;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400267 struct wl_resource *resource, *pr;
268
269 resource = keyboard->focus_resource;
270 if (!resource)
271 return;
272
273 wl_keyboard_send_modifiers(resource, serial, mods_depressed,
274 mods_latched, mods_locked, group);
275
276 if (pointer && pointer->focus && pointer->focus != keyboard->focus) {
277 pr = find_resource_for_surface(&keyboard->resource_list,
278 pointer->focus);
279 if (pr) {
280 wl_keyboard_send_modifiers(pr,
281 serial,
282 keyboard->modifiers.mods_depressed,
283 keyboard->modifiers.mods_latched,
284 keyboard->modifiers.mods_locked,
285 keyboard->modifiers.group);
286 }
287 }
288}
289
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400290static const struct weston_keyboard_grab_interface
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400291 default_keyboard_grab_interface = {
292 default_grab_key,
293 default_grab_modifiers,
294};
295
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400296static void
297pointer_unmap_sprite(struct weston_pointer *pointer)
298{
299 if (weston_surface_is_mapped(pointer->sprite))
300 weston_surface_unmap(pointer->sprite);
301
302 wl_list_remove(&pointer->sprite_destroy_listener.link);
303 pointer->sprite->configure = NULL;
304 pointer->sprite->configure_private = NULL;
305 pointer->sprite = NULL;
306}
307
308static void
309pointer_handle_sprite_destroy(struct wl_listener *listener, void *data)
310{
311 struct weston_pointer *pointer =
312 container_of(listener, struct weston_pointer,
313 sprite_destroy_listener);
314
315 pointer->sprite = NULL;
316}
317
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400318WL_EXPORT struct weston_pointer *
319weston_pointer_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400320{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400321 struct weston_pointer *pointer;
322
323 pointer = malloc(sizeof *pointer);
324 if (pointer == NULL)
325 return NULL;
326
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400327 memset(pointer, 0, sizeof *pointer);
328 wl_list_init(&pointer->resource_list);
329 pointer->focus_listener.notify = lose_pointer_focus;
330 pointer->default_grab.interface = &default_pointer_grab_interface;
331 pointer->default_grab.pointer = pointer;
332 pointer->grab = &pointer->default_grab;
333 wl_signal_init(&pointer->focus_signal);
334
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400335 pointer->sprite_destroy_listener.notify = pointer_handle_sprite_destroy;
336
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400337 /* FIXME: Pick better co-ords. */
338 pointer->x = wl_fixed_from_int(100);
339 pointer->y = wl_fixed_from_int(100);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400340
341 return pointer;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400342}
343
344WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400345weston_pointer_destroy(struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400346{
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400347 if (pointer->sprite)
348 pointer_unmap_sprite(pointer);
349
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400350 /* XXX: What about pointer->resource_list? */
351 if (pointer->focus_resource)
352 wl_list_remove(&pointer->focus_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400353 free(pointer);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400354}
355
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400356WL_EXPORT struct weston_keyboard *
357weston_keyboard_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400358{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400359 struct weston_keyboard *keyboard;
360
361 keyboard = malloc(sizeof *keyboard);
362 if (keyboard == NULL)
363 return NULL;
364
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400365 memset(keyboard, 0, sizeof *keyboard);
366 wl_list_init(&keyboard->resource_list);
367 wl_array_init(&keyboard->keys);
368 keyboard->focus_listener.notify = lose_keyboard_focus;
369 keyboard->default_grab.interface = &default_keyboard_grab_interface;
370 keyboard->default_grab.keyboard = keyboard;
371 keyboard->grab = &keyboard->default_grab;
372 wl_signal_init(&keyboard->focus_signal);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400373
374 return keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400375}
376
377WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400378weston_keyboard_destroy(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400379{
380 /* XXX: What about keyboard->resource_list? */
381 if (keyboard->focus_resource)
382 wl_list_remove(&keyboard->focus_listener.link);
383 wl_array_release(&keyboard->keys);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400384 free(keyboard);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400385}
386
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400387WL_EXPORT struct weston_touch *
388weston_touch_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400389{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400390 struct weston_touch *touch;
391
392 touch = malloc(sizeof *touch);
393 if (touch == NULL)
394 return NULL;
395
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400396 memset(touch, 0, sizeof *touch);
397 wl_list_init(&touch->resource_list);
398 touch->focus_listener.notify = lose_touch_focus;
399 touch->default_grab.interface = &default_touch_grab_interface;
400 touch->default_grab.touch = touch;
401 touch->grab = &touch->default_grab;
402 wl_signal_init(&touch->focus_signal);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400403
404 return touch;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400405}
406
407WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400408weston_touch_destroy(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400409{
410 /* XXX: What about touch->resource_list? */
411 if (touch->focus_resource)
412 wl_list_remove(&touch->focus_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400413 free(touch);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400414}
415
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400416static void
Kristian Høgsberge3148752013-05-06 23:19:49 -0400417seat_send_updated_caps(struct weston_seat *seat)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400418{
419 struct wl_resource *r;
420 enum wl_seat_capability caps = 0;
421
422 if (seat->pointer)
423 caps |= WL_SEAT_CAPABILITY_POINTER;
424 if (seat->keyboard)
425 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
426 if (seat->touch)
427 caps |= WL_SEAT_CAPABILITY_TOUCH;
428
429 wl_list_for_each(r, &seat->base_resource_list, link)
430 wl_seat_send_capabilities(r, caps);
431}
432
433WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400434weston_pointer_set_focus(struct weston_pointer *pointer,
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400435 struct weston_surface *surface,
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400436 wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400437{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400438 struct weston_keyboard *kbd = pointer->seat->keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400439 struct wl_resource *resource, *kr;
440 struct wl_display *display;
441 uint32_t serial;
442
443 resource = pointer->focus_resource;
444 if (resource && pointer->focus != surface) {
445 display = wl_client_get_display(resource->client);
446 serial = wl_display_next_serial(display);
447 wl_pointer_send_leave(resource, serial,
448 &pointer->focus->resource);
449 wl_list_remove(&pointer->focus_listener.link);
450 }
451
452 resource = find_resource_for_surface(&pointer->resource_list,
453 surface);
454 if (resource &&
455 (pointer->focus != surface ||
456 pointer->focus_resource != resource)) {
457 display = wl_client_get_display(resource->client);
458 serial = wl_display_next_serial(display);
459 if (kbd) {
460 kr = find_resource_for_surface(&kbd->resource_list,
461 surface);
462 if (kr) {
463 wl_keyboard_send_modifiers(kr,
464 serial,
465 kbd->modifiers.mods_depressed,
466 kbd->modifiers.mods_latched,
467 kbd->modifiers.mods_locked,
468 kbd->modifiers.group);
469 }
470 }
471 wl_pointer_send_enter(resource, serial, &surface->resource,
472 sx, sy);
473 wl_signal_add(&resource->destroy_signal,
474 &pointer->focus_listener);
475 pointer->focus_serial = serial;
476 }
477
478 pointer->focus_resource = resource;
479 pointer->focus = surface;
480 pointer->default_grab.focus = surface;
481 wl_signal_emit(&pointer->focus_signal, pointer);
482}
483
484WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400485weston_keyboard_set_focus(struct weston_keyboard *keyboard,
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400486 struct weston_surface *surface)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400487{
488 struct wl_resource *resource;
489 struct wl_display *display;
490 uint32_t serial;
491
492 if (keyboard->focus_resource && keyboard->focus != surface) {
493 resource = keyboard->focus_resource;
494 display = wl_client_get_display(resource->client);
495 serial = wl_display_next_serial(display);
496 wl_keyboard_send_leave(resource, serial,
497 &keyboard->focus->resource);
498 wl_list_remove(&keyboard->focus_listener.link);
499 }
500
501 resource = find_resource_for_surface(&keyboard->resource_list,
502 surface);
503 if (resource &&
504 (keyboard->focus != surface ||
505 keyboard->focus_resource != resource)) {
506 display = wl_client_get_display(resource->client);
507 serial = wl_display_next_serial(display);
508 wl_keyboard_send_modifiers(resource, serial,
509 keyboard->modifiers.mods_depressed,
510 keyboard->modifiers.mods_latched,
511 keyboard->modifiers.mods_locked,
512 keyboard->modifiers.group);
513 wl_keyboard_send_enter(resource, serial, &surface->resource,
514 &keyboard->keys);
515 wl_signal_add(&resource->destroy_signal,
516 &keyboard->focus_listener);
517 keyboard->focus_serial = serial;
518 }
519
520 keyboard->focus_resource = resource;
521 keyboard->focus = surface;
522 wl_signal_emit(&keyboard->focus_signal, keyboard);
523}
524
525WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400526weston_keyboard_start_grab(struct weston_keyboard *keyboard,
527 struct weston_keyboard_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400528{
529 keyboard->grab = grab;
530 grab->keyboard = keyboard;
531
532 /* XXX focus? */
533}
534
535WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400536weston_keyboard_end_grab(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400537{
538 keyboard->grab = &keyboard->default_grab;
539}
540
541WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400542weston_pointer_start_grab(struct weston_pointer *pointer,
543 struct weston_pointer_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400544{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400545 const struct weston_pointer_grab_interface *interface;
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400546 struct weston_compositor *compositor = pointer->seat->compositor;
547 struct weston_surface *surface;
548 wl_fixed_t sx, sy;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400549
550 pointer->grab = grab;
551 interface = pointer->grab->interface;
552 grab->pointer = pointer;
553
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400554 surface = weston_compositor_pick_surface(compositor,
555 pointer->x, pointer->y,
556 &sx, &sy);
557
558 if (surface)
559 interface->focus(pointer->grab, surface, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400560}
561
562WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400563weston_pointer_end_grab(struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400564{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400565 const struct weston_pointer_grab_interface *interface;
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400566 struct weston_compositor *compositor = pointer->seat->compositor;
567 struct weston_surface *surface;
568 wl_fixed_t sx, sy;
569
570 surface = weston_compositor_pick_surface(compositor,
571 pointer->x, pointer->y,
572 &sx, &sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400573
574 pointer->grab = &pointer->default_grab;
575 interface = pointer->grab->interface;
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400576 interface->focus(pointer->grab, surface, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400577}
578
579WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -0400580weston_touch_start_grab(struct weston_touch *touch, struct weston_touch_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400581{
582 touch->grab = grab;
583 grab->touch = touch;
584}
585
586WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -0400587weston_touch_end_grab(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400588{
589 touch->grab = &touch->default_grab;
590}
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400591
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400592static void
593clip_pointer_motion(struct weston_seat *seat, wl_fixed_t *fx, wl_fixed_t *fy)
594{
595 struct weston_compositor *ec = seat->compositor;
596 struct weston_output *output, *prev = NULL;
597 int x, y, old_x, old_y, valid = 0;
598
599 x = wl_fixed_to_int(*fx);
600 y = wl_fixed_to_int(*fy);
Kristian Høgsberge3148752013-05-06 23:19:49 -0400601 old_x = wl_fixed_to_int(seat->pointer->x);
602 old_y = wl_fixed_to_int(seat->pointer->y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400603
604 wl_list_for_each(output, &ec->output_list, link) {
605 if (pixman_region32_contains_point(&output->region,
606 x, y, NULL))
607 valid = 1;
608 if (pixman_region32_contains_point(&output->region,
609 old_x, old_y, NULL))
610 prev = output;
611 }
612
613 if (!valid) {
614 if (x < prev->x)
615 *fx = wl_fixed_from_int(prev->x);
616 else if (x >= prev->x + prev->width)
617 *fx = wl_fixed_from_int(prev->x +
618 prev->width - 1);
619 if (y < prev->y)
620 *fy = wl_fixed_from_int(prev->y);
621 else if (y >= prev->y + prev->current->height)
622 *fy = wl_fixed_from_int(prev->y +
623 prev->height - 1);
624 }
625}
626
627/* Takes absolute values */
628static void
629move_pointer(struct weston_seat *seat, wl_fixed_t x, wl_fixed_t y)
630{
631 struct weston_compositor *ec = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400632 struct weston_pointer *pointer = seat->pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400633 struct weston_output *output;
634 int32_t ix, iy;
635
636 clip_pointer_motion(seat, &x, &y);
637
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400638 pointer->x = x;
639 pointer->y = y;
640
641 ix = wl_fixed_to_int(x);
642 iy = wl_fixed_to_int(y);
643
644 wl_list_for_each(output, &ec->output_list, link)
645 if (output->zoom.active &&
646 pixman_region32_contains_point(&output->region,
647 ix, iy, NULL))
648 weston_output_update_zoom(output, ZOOM_FOCUS_POINTER);
649
Kristian Høgsberga71e8b22013-05-06 21:51:21 -0400650 weston_seat_repick(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400651
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400652 if (pointer->sprite) {
653 weston_surface_set_position(pointer->sprite,
654 ix - pointer->hotspot_x,
655 iy - pointer->hotspot_y);
656 weston_surface_schedule_repaint(pointer->sprite);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400657 }
658}
659
660WL_EXPORT void
661notify_motion(struct weston_seat *seat,
662 uint32_t time, wl_fixed_t dx, wl_fixed_t dy)
663{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400664 const struct weston_pointer_grab_interface *interface;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400665 struct weston_compositor *ec = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400666 struct weston_pointer *pointer = seat->pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400667
668 weston_compositor_wake(ec);
669
670 move_pointer(seat, pointer->x + dx, pointer->y + dy);
671
672 interface = pointer->grab->interface;
673 interface->motion(pointer->grab, time,
674 pointer->grab->x, pointer->grab->y);
675}
676
677WL_EXPORT void
678notify_motion_absolute(struct weston_seat *seat,
679 uint32_t time, wl_fixed_t x, wl_fixed_t y)
680{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400681 const struct weston_pointer_grab_interface *interface;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400682 struct weston_compositor *ec = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400683 struct weston_pointer *pointer = seat->pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400684
685 weston_compositor_wake(ec);
686
687 move_pointer(seat, x, y);
688
689 interface = pointer->grab->interface;
690 interface->motion(pointer->grab, time,
691 pointer->grab->x, pointer->grab->y);
692}
693
694WL_EXPORT void
695weston_surface_activate(struct weston_surface *surface,
696 struct weston_seat *seat)
697{
698 struct weston_compositor *compositor = seat->compositor;
699
Kristian Høgsberge3148752013-05-06 23:19:49 -0400700 if (seat->keyboard) {
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400701 weston_keyboard_set_focus(seat->keyboard, surface);
Kristian Høgsberge3148752013-05-06 23:19:49 -0400702 wl_data_device_set_keyboard_focus(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400703 }
704
705 wl_signal_emit(&compositor->activate_signal, surface);
706}
707
708WL_EXPORT void
709notify_button(struct weston_seat *seat, uint32_t time, int32_t button,
710 enum wl_pointer_button_state state)
711{
712 struct weston_compositor *compositor = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400713 struct weston_pointer *pointer = seat->pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400714 struct weston_surface *focus =
715 (struct weston_surface *) pointer->focus;
716 uint32_t serial = wl_display_next_serial(compositor->wl_display);
717
718 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
719 if (compositor->ping_handler && focus)
720 compositor->ping_handler(focus, serial);
721 weston_compositor_idle_inhibit(compositor);
722 if (pointer->button_count == 0) {
723 pointer->grab_button = button;
724 pointer->grab_time = time;
725 pointer->grab_x = pointer->x;
726 pointer->grab_y = pointer->y;
727 }
728 pointer->button_count++;
729 } else {
730 weston_compositor_idle_release(compositor);
731 pointer->button_count--;
732 }
733
734 weston_compositor_run_button_binding(compositor, seat, time, button,
735 state);
736
737 pointer->grab->interface->button(pointer->grab, time, button, state);
738
739 if (pointer->button_count == 1)
740 pointer->grab_serial =
741 wl_display_get_serial(compositor->wl_display);
742}
743
744WL_EXPORT void
745notify_axis(struct weston_seat *seat, uint32_t time, uint32_t axis,
746 wl_fixed_t value)
747{
748 struct weston_compositor *compositor = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400749 struct weston_pointer *pointer = seat->pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400750 struct weston_surface *focus =
751 (struct weston_surface *) pointer->focus;
752 uint32_t serial = wl_display_next_serial(compositor->wl_display);
753
754 if (compositor->ping_handler && focus)
755 compositor->ping_handler(focus, serial);
756
757 weston_compositor_wake(compositor);
758
759 if (!value)
760 return;
761
762 if (weston_compositor_run_axis_binding(compositor, seat,
763 time, axis, value))
764 return;
765
766 if (pointer->focus_resource)
767 wl_pointer_send_axis(pointer->focus_resource, time, axis,
768 value);
769}
770
771WL_EXPORT void
772notify_modifiers(struct weston_seat *seat, uint32_t serial)
773{
Kristian Høgsberge3148752013-05-06 23:19:49 -0400774 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400775 struct weston_keyboard_grab *grab = keyboard->grab;
776 uint32_t mods_depressed, mods_latched, mods_locked, group;
777 uint32_t mods_lookup;
778 enum weston_led leds = 0;
779 int changed = 0;
780
781 /* Serialize and update our internal state, checking to see if it's
782 * different to the previous state. */
783 mods_depressed = xkb_state_serialize_mods(seat->xkb_state.state,
784 XKB_STATE_DEPRESSED);
785 mods_latched = xkb_state_serialize_mods(seat->xkb_state.state,
786 XKB_STATE_LATCHED);
787 mods_locked = xkb_state_serialize_mods(seat->xkb_state.state,
788 XKB_STATE_LOCKED);
789 group = xkb_state_serialize_group(seat->xkb_state.state,
790 XKB_STATE_EFFECTIVE);
791
Kristian Høgsberge3148752013-05-06 23:19:49 -0400792 if (mods_depressed != seat->keyboard->modifiers.mods_depressed ||
793 mods_latched != seat->keyboard->modifiers.mods_latched ||
794 mods_locked != seat->keyboard->modifiers.mods_locked ||
795 group != seat->keyboard->modifiers.group)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400796 changed = 1;
797
Kristian Høgsberge3148752013-05-06 23:19:49 -0400798 seat->keyboard->modifiers.mods_depressed = mods_depressed;
799 seat->keyboard->modifiers.mods_latched = mods_latched;
800 seat->keyboard->modifiers.mods_locked = mods_locked;
801 seat->keyboard->modifiers.group = group;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400802
803 /* And update the modifier_state for bindings. */
804 mods_lookup = mods_depressed | mods_latched;
805 seat->modifier_state = 0;
806 if (mods_lookup & (1 << seat->xkb_info.ctrl_mod))
807 seat->modifier_state |= MODIFIER_CTRL;
808 if (mods_lookup & (1 << seat->xkb_info.alt_mod))
809 seat->modifier_state |= MODIFIER_ALT;
810 if (mods_lookup & (1 << seat->xkb_info.super_mod))
811 seat->modifier_state |= MODIFIER_SUPER;
812 if (mods_lookup & (1 << seat->xkb_info.shift_mod))
813 seat->modifier_state |= MODIFIER_SHIFT;
814
815 /* Finally, notify the compositor that LEDs have changed. */
816 if (xkb_state_led_index_is_active(seat->xkb_state.state,
817 seat->xkb_info.num_led))
818 leds |= LED_NUM_LOCK;
819 if (xkb_state_led_index_is_active(seat->xkb_state.state,
820 seat->xkb_info.caps_led))
821 leds |= LED_CAPS_LOCK;
822 if (xkb_state_led_index_is_active(seat->xkb_state.state,
823 seat->xkb_info.scroll_led))
824 leds |= LED_SCROLL_LOCK;
825 if (leds != seat->xkb_state.leds && seat->led_update)
826 seat->led_update(seat, leds);
827 seat->xkb_state.leds = leds;
828
829 if (changed) {
830 grab->interface->modifiers(grab,
831 serial,
832 keyboard->modifiers.mods_depressed,
833 keyboard->modifiers.mods_latched,
834 keyboard->modifiers.mods_locked,
835 keyboard->modifiers.group);
836 }
837}
838
839static void
840update_modifier_state(struct weston_seat *seat, uint32_t serial, uint32_t key,
841 enum wl_keyboard_key_state state)
842{
843 enum xkb_key_direction direction;
844
845 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
846 direction = XKB_KEY_DOWN;
847 else
848 direction = XKB_KEY_UP;
849
850 /* Offset the keycode by 8, as the evdev XKB rules reflect X's
851 * broken keycode system, which starts at 8. */
852 xkb_state_update_key(seat->xkb_state.state, key + 8, direction);
853
854 notify_modifiers(seat, serial);
855}
856
857WL_EXPORT void
858notify_key(struct weston_seat *seat, uint32_t time, uint32_t key,
859 enum wl_keyboard_key_state state,
860 enum weston_key_state_update update_state)
861{
862 struct weston_compositor *compositor = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400863 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400864 struct weston_surface *focus =
865 (struct weston_surface *) keyboard->focus;
866 struct weston_keyboard_grab *grab = keyboard->grab;
867 uint32_t serial = wl_display_next_serial(compositor->wl_display);
868 uint32_t *k, *end;
869
870 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
871 if (compositor->ping_handler && focus)
872 compositor->ping_handler(focus, serial);
873
874 weston_compositor_idle_inhibit(compositor);
875 keyboard->grab_key = key;
876 keyboard->grab_time = time;
877 } else {
878 weston_compositor_idle_release(compositor);
879 }
880
881 end = keyboard->keys.data + keyboard->keys.size;
882 for (k = keyboard->keys.data; k < end; k++) {
883 if (*k == key) {
884 /* Ignore server-generated repeats. */
885 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
886 return;
887 *k = *--end;
888 }
889 }
890 keyboard->keys.size = (void *) end - keyboard->keys.data;
891 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
892 k = wl_array_add(&keyboard->keys, sizeof *k);
893 *k = key;
894 }
895
896 if (grab == &keyboard->default_grab ||
897 grab == &keyboard->input_method_grab) {
898 weston_compositor_run_key_binding(compositor, seat, time, key,
899 state);
900 grab = keyboard->grab;
901 }
902
903 grab->interface->key(grab, time, key, state);
904
905 if (update_state == STATE_UPDATE_AUTOMATIC) {
906 update_modifier_state(seat,
907 wl_display_get_serial(compositor->wl_display),
908 key,
909 state);
910 }
911}
912
913WL_EXPORT void
914notify_pointer_focus(struct weston_seat *seat, struct weston_output *output,
915 wl_fixed_t x, wl_fixed_t y)
916{
917 struct weston_compositor *compositor = seat->compositor;
918
919 if (output) {
920 move_pointer(seat, x, y);
921 compositor->focus = 1;
922 } else {
923 compositor->focus = 0;
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400924 /* FIXME: We should call weston_pointer_set_focus(seat,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400925 * NULL) here, but somehow that breaks re-entry... */
926 }
927}
928
929static void
930destroy_device_saved_kbd_focus(struct wl_listener *listener, void *data)
931{
932 struct weston_seat *ws;
933
934 ws = container_of(listener, struct weston_seat,
935 saved_kbd_focus_listener);
936
937 ws->saved_kbd_focus = NULL;
938}
939
940WL_EXPORT void
941notify_keyboard_focus_in(struct weston_seat *seat, struct wl_array *keys,
942 enum weston_key_state_update update_state)
943{
944 struct weston_compositor *compositor = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400945 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400946 struct weston_surface *surface;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400947 uint32_t *k, serial;
948
949 serial = wl_display_next_serial(compositor->wl_display);
950 wl_array_copy(&keyboard->keys, keys);
951 wl_array_for_each(k, &keyboard->keys) {
952 weston_compositor_idle_inhibit(compositor);
953 if (update_state == STATE_UPDATE_AUTOMATIC)
954 update_modifier_state(seat, serial, *k,
955 WL_KEYBOARD_KEY_STATE_PRESSED);
956 }
957
958 /* Run key bindings after we've updated the state. */
959 wl_array_for_each(k, &keyboard->keys) {
960 weston_compositor_run_key_binding(compositor, seat, 0, *k,
961 WL_KEYBOARD_KEY_STATE_PRESSED);
962 }
963
964 surface = seat->saved_kbd_focus;
965
966 if (surface) {
967 wl_list_remove(&seat->saved_kbd_focus_listener.link);
968 weston_keyboard_set_focus(keyboard, surface);
969 seat->saved_kbd_focus = NULL;
970 }
971}
972
973WL_EXPORT void
974notify_keyboard_focus_out(struct weston_seat *seat)
975{
976 struct weston_compositor *compositor = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400977 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400978 uint32_t *k, serial;
979
980 serial = wl_display_next_serial(compositor->wl_display);
981 wl_array_for_each(k, &keyboard->keys) {
982 weston_compositor_idle_release(compositor);
983 update_modifier_state(seat, serial, *k,
984 WL_KEYBOARD_KEY_STATE_RELEASED);
985 }
986
987 seat->modifier_state = 0;
988
989 if (keyboard->focus) {
990 seat->saved_kbd_focus = keyboard->focus;
991 seat->saved_kbd_focus_listener.notify =
992 destroy_device_saved_kbd_focus;
993 wl_signal_add(&keyboard->focus->resource.destroy_signal,
994 &seat->saved_kbd_focus_listener);
995 }
996
997 weston_keyboard_set_focus(keyboard, NULL);
998 /* FIXME: We really need keyboard grab cancel here to
999 * let the grab shut down properly. As it is we leak
1000 * the grab data. */
1001 weston_keyboard_end_grab(keyboard);
1002}
1003
1004static void
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -04001005touch_set_focus(struct weston_seat *seat, struct weston_surface *surface)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001006{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001007 struct wl_resource *resource;
1008
1009 if (seat->touch->focus == surface)
1010 return;
1011
1012 if (seat->touch->focus_resource)
1013 wl_list_remove(&seat->touch->focus_listener.link);
1014 seat->touch->focus = NULL;
1015 seat->touch->focus_resource = NULL;
1016
1017 if (surface) {
1018 resource =
Kristian Høgsberg80fb82d2013-05-06 21:49:55 -04001019 find_resource_for_surface(&seat->touch->resource_list,
1020 surface);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001021 if (!resource) {
1022 weston_log("couldn't find resource\n");
1023 return;
1024 }
1025
1026 seat->touch->focus = surface;
1027 seat->touch->focus_resource = resource;
1028 wl_signal_add(&resource->destroy_signal,
1029 &seat->touch->focus_listener);
1030 }
1031}
1032
1033/**
1034 * notify_touch - emulates button touches and notifies surfaces accordingly.
1035 *
1036 * It assumes always the correct cycle sequence until it gets here: touch_down
1037 * → touch_update → ... → touch_update → touch_end. The driver is responsible
1038 * for sending along such order.
1039 *
1040 */
1041WL_EXPORT void
1042notify_touch(struct weston_seat *seat, uint32_t time, int touch_id,
1043 wl_fixed_t x, wl_fixed_t y, int touch_type)
1044{
1045 struct weston_compositor *ec = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -04001046 struct weston_touch *touch = seat->touch;
Kristian Høgsberge329f362013-05-06 22:19:57 -04001047 struct weston_touch_grab *grab = touch->grab;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001048 struct weston_surface *es;
1049 wl_fixed_t sx, sy;
1050
1051 /* Update grab's global coordinates. */
1052 touch->grab_x = x;
1053 touch->grab_y = y;
1054
1055 switch (touch_type) {
1056 case WL_TOUCH_DOWN:
1057 weston_compositor_idle_inhibit(ec);
1058
1059 seat->num_tp++;
1060
1061 /* the first finger down picks the surface, and all further go
1062 * to that surface for the remainder of the touch session i.e.
1063 * until all touch points are up again. */
1064 if (seat->num_tp == 1) {
1065 es = weston_compositor_pick_surface(ec, x, y, &sx, &sy);
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -04001066 touch_set_focus(seat, es);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001067 } else if (touch->focus) {
1068 es = (struct weston_surface *) touch->focus;
1069 weston_surface_from_global_fixed(es, x, y, &sx, &sy);
1070 } else {
1071 /* Unexpected condition: We have non-initial touch but
1072 * there is no focused surface.
1073 */
1074 weston_log("touch event received with %d points down"
1075 "but no surface focused\n", seat->num_tp);
1076 return;
1077 }
1078
1079 grab->interface->down(grab, time, touch_id, sx, sy);
1080 break;
1081 case WL_TOUCH_MOTION:
1082 es = (struct weston_surface *) touch->focus;
1083 if (!es)
1084 break;
1085
1086 weston_surface_from_global_fixed(es, x, y, &sx, &sy);
1087 grab->interface->motion(grab, time, touch_id, sx, sy);
1088 break;
1089 case WL_TOUCH_UP:
1090 weston_compositor_idle_release(ec);
1091 seat->num_tp--;
1092
1093 grab->interface->up(grab, time, touch_id);
1094 if (seat->num_tp == 0)
1095 touch_set_focus(seat, NULL);
1096 break;
1097 }
1098}
1099
1100static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001101pointer_cursor_surface_configure(struct weston_surface *es,
1102 int32_t dx, int32_t dy, int32_t width, int32_t height)
1103{
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001104 struct weston_pointer *pointer = es->configure_private;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001105 int x, y;
1106
1107 if (width == 0)
1108 return;
1109
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001110 assert(es == pointer->sprite);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001111
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001112 pointer->hotspot_x -= dx;
1113 pointer->hotspot_y -= dy;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001114
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001115 x = wl_fixed_to_int(pointer->x) - pointer->hotspot_x;
1116 y = wl_fixed_to_int(pointer->y) - pointer->hotspot_y;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001117
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001118 weston_surface_configure(pointer->sprite, x, y, width, height);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001119
1120 empty_region(&es->pending.input);
1121
1122 if (!weston_surface_is_mapped(es)) {
1123 wl_list_insert(&es->compositor->cursor_layer.surface_list,
1124 &es->layer_link);
1125 weston_surface_update_transform(es);
1126 }
1127}
1128
1129static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001130pointer_set_cursor(struct wl_client *client, struct wl_resource *resource,
1131 uint32_t serial, struct wl_resource *surface_resource,
1132 int32_t x, int32_t y)
1133{
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001134 struct weston_pointer *pointer = resource->data;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001135 struct weston_surface *surface = NULL;
1136
1137 if (surface_resource)
1138 surface = surface_resource->data;
1139
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001140 if (pointer->focus == NULL)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001141 return;
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001142 if (pointer->focus->resource.client != client)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001143 return;
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001144 if (pointer->focus_serial - serial > UINT32_MAX / 2)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001145 return;
1146
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001147 if (surface && surface != pointer->sprite) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001148 if (surface->configure) {
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -04001149 wl_resource_post_error(&surface->resource,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001150 WL_DISPLAY_ERROR_INVALID_OBJECT,
1151 "surface->configure already "
1152 "set");
1153 return;
1154 }
1155 }
1156
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001157 if (pointer->sprite)
1158 pointer_unmap_sprite(pointer);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001159
1160 if (!surface)
1161 return;
1162
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -04001163 wl_signal_add(&surface->resource.destroy_signal,
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001164 &pointer->sprite_destroy_listener);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001165
1166 surface->configure = pointer_cursor_surface_configure;
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001167 surface->configure_private = pointer;
1168 pointer->sprite = surface;
1169 pointer->hotspot_x = x;
1170 pointer->hotspot_y = y;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001171
1172 if (surface->buffer_ref.buffer)
1173 pointer_cursor_surface_configure(surface, 0, 0, weston_surface_buffer_width(surface),
1174 weston_surface_buffer_height(surface));
1175}
1176
1177static const struct wl_pointer_interface pointer_interface = {
1178 pointer_set_cursor
1179};
1180
1181static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001182seat_get_pointer(struct wl_client *client, struct wl_resource *resource,
1183 uint32_t id)
1184{
1185 struct weston_seat *seat = resource->data;
1186 struct wl_resource *cr;
1187
Kristian Høgsberge3148752013-05-06 23:19:49 -04001188 if (!seat->pointer)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001189 return;
1190
1191 cr = wl_client_add_object(client, &wl_pointer_interface,
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001192 &pointer_interface, id, seat->pointer);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001193 wl_list_insert(&seat->pointer->resource_list, &cr->link);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001194 cr->destroy = unbind_resource;
1195
Kristian Høgsberge3148752013-05-06 23:19:49 -04001196 if (seat->pointer->focus &&
1197 seat->pointer->focus->resource.client == client) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001198 struct weston_surface *surface;
1199 wl_fixed_t sx, sy;
1200
Kristian Høgsberge3148752013-05-06 23:19:49 -04001201 surface = (struct weston_surface *) seat->pointer->focus;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001202 weston_surface_from_global_fixed(surface,
Kristian Høgsberge3148752013-05-06 23:19:49 -04001203 seat->pointer->x,
1204 seat->pointer->y,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001205 &sx,
1206 &sy);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001207 weston_pointer_set_focus(seat->pointer,
1208 seat->pointer->focus,
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001209 sx,
1210 sy);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001211 }
1212}
1213
1214static void
1215seat_get_keyboard(struct wl_client *client, struct wl_resource *resource,
1216 uint32_t id)
1217{
1218 struct weston_seat *seat = resource->data;
1219 struct wl_resource *cr;
1220
Kristian Høgsberge3148752013-05-06 23:19:49 -04001221 if (!seat->keyboard)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001222 return;
1223
1224 cr = wl_client_add_object(client, &wl_keyboard_interface, NULL, id,
1225 seat);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001226 wl_list_insert(&seat->keyboard->resource_list, &cr->link);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001227 cr->destroy = unbind_resource;
1228
1229 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
1230 seat->xkb_info.keymap_fd,
1231 seat->xkb_info.keymap_size);
1232
Kristian Høgsberge3148752013-05-06 23:19:49 -04001233 if (seat->keyboard->focus &&
1234 seat->keyboard->focus->resource.client == client) {
1235 weston_keyboard_set_focus(seat->keyboard,
1236 seat->keyboard->focus);
1237 wl_data_device_set_keyboard_focus(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001238 }
1239}
1240
1241static void
1242seat_get_touch(struct wl_client *client, struct wl_resource *resource,
1243 uint32_t id)
1244{
1245 struct weston_seat *seat = resource->data;
1246 struct wl_resource *cr;
1247
Kristian Høgsberge3148752013-05-06 23:19:49 -04001248 if (!seat->touch)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001249 return;
1250
1251 cr = wl_client_add_object(client, &wl_touch_interface, NULL, id, seat);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001252 wl_list_insert(&seat->touch->resource_list, &cr->link);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001253 cr->destroy = unbind_resource;
1254}
1255
1256static const struct wl_seat_interface seat_interface = {
1257 seat_get_pointer,
1258 seat_get_keyboard,
1259 seat_get_touch,
1260};
1261
1262static void
1263bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
1264{
Kristian Høgsberge3148752013-05-06 23:19:49 -04001265 struct weston_seat *seat = data;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001266 struct wl_resource *resource;
1267 enum wl_seat_capability caps = 0;
1268
1269 resource = wl_client_add_object(client, &wl_seat_interface,
1270 &seat_interface, id, data);
1271 wl_list_insert(&seat->base_resource_list, &resource->link);
1272 resource->destroy = unbind_resource;
1273
1274 if (seat->pointer)
1275 caps |= WL_SEAT_CAPABILITY_POINTER;
1276 if (seat->keyboard)
1277 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
1278 if (seat->touch)
1279 caps |= WL_SEAT_CAPABILITY_TOUCH;
1280
1281 wl_seat_send_capabilities(resource, caps);
1282}
1283
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001284int
1285weston_compositor_xkb_init(struct weston_compositor *ec,
1286 struct xkb_rule_names *names)
1287{
1288 if (ec->xkb_context == NULL) {
1289 ec->xkb_context = xkb_context_new(0);
1290 if (ec->xkb_context == NULL) {
1291 weston_log("failed to create XKB context\n");
1292 return -1;
1293 }
1294 }
1295
1296 if (names)
1297 ec->xkb_names = *names;
1298 if (!ec->xkb_names.rules)
1299 ec->xkb_names.rules = strdup("evdev");
1300 if (!ec->xkb_names.model)
1301 ec->xkb_names.model = strdup("pc105");
1302 if (!ec->xkb_names.layout)
1303 ec->xkb_names.layout = strdup("us");
1304
1305 return 0;
1306}
1307
1308static void xkb_info_destroy(struct weston_xkb_info *xkb_info)
1309{
1310 if (xkb_info->keymap)
1311 xkb_map_unref(xkb_info->keymap);
1312
1313 if (xkb_info->keymap_area)
1314 munmap(xkb_info->keymap_area, xkb_info->keymap_size);
1315 if (xkb_info->keymap_fd >= 0)
1316 close(xkb_info->keymap_fd);
1317}
1318
1319void
1320weston_compositor_xkb_destroy(struct weston_compositor *ec)
1321{
1322 free((char *) ec->xkb_names.rules);
1323 free((char *) ec->xkb_names.model);
1324 free((char *) ec->xkb_names.layout);
1325 free((char *) ec->xkb_names.variant);
1326 free((char *) ec->xkb_names.options);
1327
1328 xkb_info_destroy(&ec->xkb_info);
1329 xkb_context_unref(ec->xkb_context);
1330}
1331
1332static int
1333weston_xkb_info_new_keymap(struct weston_xkb_info *xkb_info)
1334{
1335 char *keymap_str;
1336
1337 xkb_info->shift_mod = xkb_map_mod_get_index(xkb_info->keymap,
1338 XKB_MOD_NAME_SHIFT);
1339 xkb_info->caps_mod = xkb_map_mod_get_index(xkb_info->keymap,
1340 XKB_MOD_NAME_CAPS);
1341 xkb_info->ctrl_mod = xkb_map_mod_get_index(xkb_info->keymap,
1342 XKB_MOD_NAME_CTRL);
1343 xkb_info->alt_mod = xkb_map_mod_get_index(xkb_info->keymap,
1344 XKB_MOD_NAME_ALT);
1345 xkb_info->mod2_mod = xkb_map_mod_get_index(xkb_info->keymap, "Mod2");
1346 xkb_info->mod3_mod = xkb_map_mod_get_index(xkb_info->keymap, "Mod3");
1347 xkb_info->super_mod = xkb_map_mod_get_index(xkb_info->keymap,
1348 XKB_MOD_NAME_LOGO);
1349 xkb_info->mod5_mod = xkb_map_mod_get_index(xkb_info->keymap, "Mod5");
1350
1351 xkb_info->num_led = xkb_map_led_get_index(xkb_info->keymap,
1352 XKB_LED_NAME_NUM);
1353 xkb_info->caps_led = xkb_map_led_get_index(xkb_info->keymap,
1354 XKB_LED_NAME_CAPS);
1355 xkb_info->scroll_led = xkb_map_led_get_index(xkb_info->keymap,
1356 XKB_LED_NAME_SCROLL);
1357
1358 keymap_str = xkb_map_get_as_string(xkb_info->keymap);
1359 if (keymap_str == NULL) {
1360 weston_log("failed to get string version of keymap\n");
1361 return -1;
1362 }
1363 xkb_info->keymap_size = strlen(keymap_str) + 1;
1364
1365 xkb_info->keymap_fd = os_create_anonymous_file(xkb_info->keymap_size);
1366 if (xkb_info->keymap_fd < 0) {
1367 weston_log("creating a keymap file for %lu bytes failed: %m\n",
1368 (unsigned long) xkb_info->keymap_size);
1369 goto err_keymap_str;
1370 }
1371
1372 xkb_info->keymap_area = mmap(NULL, xkb_info->keymap_size,
1373 PROT_READ | PROT_WRITE,
1374 MAP_SHARED, xkb_info->keymap_fd, 0);
1375 if (xkb_info->keymap_area == MAP_FAILED) {
1376 weston_log("failed to mmap() %lu bytes\n",
1377 (unsigned long) xkb_info->keymap_size);
1378 goto err_dev_zero;
1379 }
1380 strcpy(xkb_info->keymap_area, keymap_str);
1381 free(keymap_str);
1382
1383 return 0;
1384
1385err_dev_zero:
1386 close(xkb_info->keymap_fd);
1387 xkb_info->keymap_fd = -1;
1388err_keymap_str:
1389 free(keymap_str);
1390 return -1;
1391}
1392
1393static int
1394weston_compositor_build_global_keymap(struct weston_compositor *ec)
1395{
1396 if (ec->xkb_info.keymap != NULL)
1397 return 0;
1398
1399 ec->xkb_info.keymap = xkb_map_new_from_names(ec->xkb_context,
1400 &ec->xkb_names,
1401 0);
1402 if (ec->xkb_info.keymap == NULL) {
1403 weston_log("failed to compile global XKB keymap\n");
1404 weston_log(" tried rules %s, model %s, layout %s, variant %s, "
1405 "options %s\n",
1406 ec->xkb_names.rules, ec->xkb_names.model,
1407 ec->xkb_names.layout, ec->xkb_names.variant,
1408 ec->xkb_names.options);
1409 return -1;
1410 }
1411
1412 if (weston_xkb_info_new_keymap(&ec->xkb_info) < 0)
1413 return -1;
1414
1415 return 0;
1416}
1417
1418WL_EXPORT int
1419weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap)
1420{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001421 struct weston_keyboard *keyboard;
1422
Kristian Høgsberg2bf87622013-05-07 23:17:41 -04001423 if (seat->keyboard)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001424 return 0;
1425
1426 if (keymap != NULL) {
1427 seat->xkb_info.keymap = xkb_map_ref(keymap);
1428 if (weston_xkb_info_new_keymap(&seat->xkb_info) < 0)
1429 return -1;
1430 } else {
1431 if (weston_compositor_build_global_keymap(seat->compositor) < 0)
1432 return -1;
1433 seat->xkb_info = seat->compositor->xkb_info;
1434 seat->xkb_info.keymap = xkb_map_ref(seat->xkb_info.keymap);
1435 }
1436
1437 seat->xkb_state.state = xkb_state_new(seat->xkb_info.keymap);
1438 if (seat->xkb_state.state == NULL) {
1439 weston_log("failed to initialise XKB state\n");
1440 return -1;
1441 }
1442
1443 seat->xkb_state.leds = 0;
1444
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001445 keyboard = weston_keyboard_create();
1446 if (keyboard == NULL) {
1447 weston_log("failed to allocate weston keyboard struct\n");
1448 return -1;
1449 }
1450
1451 seat->keyboard = keyboard;
1452 keyboard->seat = seat;
1453
1454 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001455
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001456 return 0;
1457}
1458
1459WL_EXPORT void
1460weston_seat_init_pointer(struct weston_seat *seat)
1461{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001462 struct weston_pointer *pointer;
1463
Kristian Høgsberg2bf87622013-05-07 23:17:41 -04001464 if (seat->pointer)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001465 return;
1466
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001467 pointer = weston_pointer_create();
1468 if (pointer == NULL)
1469 return;
1470
1471 seat->pointer = pointer;
1472 pointer->seat = seat;
1473
1474 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001475}
1476
1477WL_EXPORT void
1478weston_seat_init_touch(struct weston_seat *seat)
1479{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001480 struct weston_touch *touch;
1481
Kristian Høgsberg2bf87622013-05-07 23:17:41 -04001482 if (seat->touch)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001483 return;
1484
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001485 touch = weston_touch_create();
1486 if (touch == NULL)
1487 return;
1488
1489 seat->touch = touch;
1490 touch->seat = seat;
1491
1492 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001493}
1494
1495WL_EXPORT void
1496weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec)
1497{
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04001498 memset(seat, 0, sizeof *seat);
1499
Kristian Høgsberge3148752013-05-06 23:19:49 -04001500 seat->selection_data_source = NULL;
1501 wl_list_init(&seat->base_resource_list);
1502 wl_signal_init(&seat->selection_signal);
1503 wl_list_init(&seat->drag_resource_list);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001504 wl_signal_init(&seat->destroy_signal);
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04001505
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001506 wl_display_add_global(ec->wl_display, &wl_seat_interface, seat,
1507 bind_seat);
1508
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001509 seat->compositor = ec;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001510 seat->modifier_state = 0;
1511 seat->num_tp = 0;
1512
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001513 wl_list_insert(ec->seat_list.prev, &seat->link);
1514
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001515 clipboard_create(seat);
1516
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001517 wl_signal_emit(&ec->seat_created_signal, seat);
1518}
1519
1520WL_EXPORT void
1521weston_seat_release(struct weston_seat *seat)
1522{
1523 wl_list_remove(&seat->link);
1524 /* The global object is destroyed at wl_display_destroy() time. */
1525
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001526 if (seat->xkb_state.state != NULL)
1527 xkb_state_unref(seat->xkb_state.state);
1528 xkb_info_destroy(&seat->xkb_info);
1529
Kristian Høgsberge3148752013-05-06 23:19:49 -04001530 if (seat->pointer)
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001531 weston_pointer_destroy(seat->pointer);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001532 if (seat->keyboard)
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001533 weston_keyboard_destroy(seat->keyboard);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001534 if (seat->touch)
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001535 weston_touch_destroy(seat->touch);
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04001536
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001537 wl_signal_emit(&seat->destroy_signal, seat);
1538}