blob: d23d78b161461bb6570c33c68dae873a7c4140e0 [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øgsbergbe6403e2013-05-08 21:03:21 -040050 struct weston_surface *surface;
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
66static void
67weston_compositor_idle_inhibit(struct weston_compositor *compositor)
68{
69 weston_compositor_wake(compositor);
70 compositor->idle_inhibit++;
71}
72
73static void
74weston_compositor_idle_release(struct weston_compositor *compositor)
75{
76 compositor->idle_inhibit--;
77 weston_compositor_wake(compositor);
78}
79
Kristian Høgsberg2158a882013-04-18 15:07:39 -040080static void
81lose_pointer_focus(struct wl_listener *listener, void *data)
82{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -040083 struct weston_pointer *pointer =
84 container_of(listener, struct weston_pointer, focus_listener);
Kristian Høgsberg2158a882013-04-18 15:07:39 -040085
86 pointer->focus_resource = NULL;
87}
88
89static void
90lose_keyboard_focus(struct wl_listener *listener, void *data)
91{
Kristian Høgsberg29139d42013-04-18 15:25:39 -040092 struct weston_keyboard *keyboard =
93 container_of(listener, struct weston_keyboard, focus_listener);
Kristian Høgsberg2158a882013-04-18 15:07:39 -040094
95 keyboard->focus_resource = NULL;
96}
97
98static void
99lose_touch_focus(struct wl_listener *listener, void *data)
100{
Kristian Høgsberge329f362013-05-06 22:19:57 -0400101 struct weston_touch *touch =
102 container_of(listener, struct weston_touch, focus_listener);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400103
104 touch->focus_resource = NULL;
105}
106
107static void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400108default_grab_focus(struct weston_pointer_grab *grab,
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400109 struct weston_surface *surface, wl_fixed_t x, wl_fixed_t y)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400110{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400111 struct weston_pointer *pointer = grab->pointer;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400112
113 if (pointer->button_count > 0)
114 return;
115
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400116 if (pointer->focus != surface)
117 weston_pointer_set_focus(pointer, surface, x, y);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400118}
119
120static void
Kristian Høgsbergbe6403e2013-05-08 21:03:21 -0400121default_grab_motion(struct weston_pointer_grab *grab, uint32_t time)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400122{
Kristian Høgsbergbe6403e2013-05-08 21:03:21 -0400123 struct weston_pointer *pointer = grab->pointer;
124 wl_fixed_t sx, sy;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400125
Kristian Høgsbergbe6403e2013-05-08 21:03:21 -0400126 if (pointer->focus_resource) {
127 weston_surface_from_global_fixed(pointer->focus,
128 pointer->x, pointer->y,
129 &sx, &sy);
130 wl_pointer_send_motion(pointer->focus_resource, time, sx, sy);
131 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400132}
133
134static void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400135default_grab_button(struct weston_pointer_grab *grab,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400136 uint32_t time, uint32_t button, uint32_t state_w)
137{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400138 struct weston_pointer *pointer = grab->pointer;
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400139 struct weston_compositor *compositor = pointer->seat->compositor;
140 struct weston_surface *surface;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400141 struct wl_resource *resource;
142 uint32_t serial;
143 enum wl_pointer_button_state state = state_w;
144 struct wl_display *display;
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400145 wl_fixed_t sx, sy;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400146
147 resource = pointer->focus_resource;
148 if (resource) {
149 display = wl_client_get_display(resource->client);
150 serial = wl_display_next_serial(display);
151 wl_pointer_send_button(resource, serial, time, button, state_w);
152 }
153
154 if (pointer->button_count == 0 &&
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400155 state == WL_POINTER_BUTTON_STATE_RELEASED) {
156 surface = weston_compositor_pick_surface(compositor,
157 pointer->x,
158 pointer->y,
159 &sx, &sy);
160
161 weston_pointer_set_focus(pointer, surface, sx, sy);
162 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400163}
164
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400165static const struct weston_pointer_grab_interface
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400166 default_pointer_grab_interface = {
167 default_grab_focus,
168 default_grab_motion,
169 default_grab_button
170};
171
Kristian Høgsberge329f362013-05-06 22:19:57 -0400172static void
173default_grab_touch_down(struct weston_touch_grab *grab, uint32_t time,
174 int touch_id, wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400175{
Kristian Høgsberge329f362013-05-06 22:19:57 -0400176 struct weston_touch *touch = grab->touch;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400177 struct wl_display *display;
178 uint32_t serial;
179
180 if (touch->focus_resource && touch->focus) {
181 display = wl_client_get_display(touch->focus_resource->client);
182 serial = wl_display_next_serial(display);
183 wl_touch_send_down(touch->focus_resource, serial, time,
Kristian Høgsberge329f362013-05-06 22:19:57 -0400184 &touch->focus->resource,
185 touch_id, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400186 }
187}
188
Kristian Høgsberge329f362013-05-06 22:19:57 -0400189static void
190default_grab_touch_up(struct weston_touch_grab *grab,
191 uint32_t time, int touch_id)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400192{
Kristian Høgsberge329f362013-05-06 22:19:57 -0400193 struct weston_touch *touch = grab->touch;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400194 struct wl_display *display;
195 uint32_t serial;
196
197 if (touch->focus_resource) {
198 display = wl_client_get_display(touch->focus_resource->client);
199 serial = wl_display_next_serial(display);
200 wl_touch_send_up(touch->focus_resource, serial, time, touch_id);
201 }
202}
203
Kristian Høgsberge329f362013-05-06 22:19:57 -0400204static void
205default_grab_touch_motion(struct weston_touch_grab *grab, uint32_t time,
206 int touch_id, wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400207{
Kristian Høgsberge329f362013-05-06 22:19:57 -0400208 struct weston_touch *touch = grab->touch;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400209
210 if (touch->focus_resource) {
211 wl_touch_send_motion(touch->focus_resource, time,
Kristian Høgsberge329f362013-05-06 22:19:57 -0400212 touch_id, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400213 }
214}
215
Kristian Høgsberge329f362013-05-06 22:19:57 -0400216static const struct weston_touch_grab_interface default_touch_grab_interface = {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400217 default_grab_touch_down,
218 default_grab_touch_up,
219 default_grab_touch_motion
220};
221
222static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400223default_grab_key(struct weston_keyboard_grab *grab,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400224 uint32_t time, uint32_t key, uint32_t state)
225{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400226 struct weston_keyboard *keyboard = grab->keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400227 struct wl_resource *resource;
228 struct wl_display *display;
229 uint32_t serial;
230
231 resource = keyboard->focus_resource;
232 if (resource) {
233 display = wl_client_get_display(resource->client);
234 serial = wl_display_next_serial(display);
235 wl_keyboard_send_key(resource, serial, time, key, state);
236 }
237}
238
239static struct wl_resource *
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400240find_resource_for_surface(struct wl_list *list, struct weston_surface *surface)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400241{
242 struct wl_resource *r;
243
244 if (!surface)
245 return NULL;
246
247 wl_list_for_each(r, list, link) {
248 if (r->client == surface->resource.client)
249 return r;
250 }
251
252 return NULL;
253}
254
255static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400256default_grab_modifiers(struct weston_keyboard_grab *grab, uint32_t serial,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400257 uint32_t mods_depressed, uint32_t mods_latched,
258 uint32_t mods_locked, uint32_t group)
259{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400260 struct weston_keyboard *keyboard = grab->keyboard;
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400261 struct weston_pointer *pointer = keyboard->seat->pointer;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400262 struct wl_resource *resource, *pr;
263
264 resource = keyboard->focus_resource;
265 if (!resource)
266 return;
267
268 wl_keyboard_send_modifiers(resource, serial, mods_depressed,
269 mods_latched, mods_locked, group);
270
271 if (pointer && pointer->focus && pointer->focus != keyboard->focus) {
272 pr = find_resource_for_surface(&keyboard->resource_list,
273 pointer->focus);
274 if (pr) {
275 wl_keyboard_send_modifiers(pr,
276 serial,
277 keyboard->modifiers.mods_depressed,
278 keyboard->modifiers.mods_latched,
279 keyboard->modifiers.mods_locked,
280 keyboard->modifiers.group);
281 }
282 }
283}
284
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400285static const struct weston_keyboard_grab_interface
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400286 default_keyboard_grab_interface = {
287 default_grab_key,
288 default_grab_modifiers,
289};
290
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400291static void
292pointer_unmap_sprite(struct weston_pointer *pointer)
293{
294 if (weston_surface_is_mapped(pointer->sprite))
295 weston_surface_unmap(pointer->sprite);
296
297 wl_list_remove(&pointer->sprite_destroy_listener.link);
298 pointer->sprite->configure = NULL;
299 pointer->sprite->configure_private = NULL;
300 pointer->sprite = NULL;
301}
302
303static void
304pointer_handle_sprite_destroy(struct wl_listener *listener, void *data)
305{
306 struct weston_pointer *pointer =
307 container_of(listener, struct weston_pointer,
308 sprite_destroy_listener);
309
310 pointer->sprite = NULL;
311}
312
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400313WL_EXPORT struct weston_pointer *
314weston_pointer_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400315{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400316 struct weston_pointer *pointer;
317
318 pointer = malloc(sizeof *pointer);
319 if (pointer == NULL)
320 return NULL;
321
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400322 memset(pointer, 0, sizeof *pointer);
323 wl_list_init(&pointer->resource_list);
324 pointer->focus_listener.notify = lose_pointer_focus;
325 pointer->default_grab.interface = &default_pointer_grab_interface;
326 pointer->default_grab.pointer = pointer;
327 pointer->grab = &pointer->default_grab;
328 wl_signal_init(&pointer->focus_signal);
329
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400330 pointer->sprite_destroy_listener.notify = pointer_handle_sprite_destroy;
331
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400332 /* FIXME: Pick better co-ords. */
333 pointer->x = wl_fixed_from_int(100);
334 pointer->y = wl_fixed_from_int(100);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400335
336 return pointer;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400337}
338
339WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400340weston_pointer_destroy(struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400341{
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400342 if (pointer->sprite)
343 pointer_unmap_sprite(pointer);
344
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400345 /* XXX: What about pointer->resource_list? */
346 if (pointer->focus_resource)
347 wl_list_remove(&pointer->focus_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400348 free(pointer);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400349}
350
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400351WL_EXPORT struct weston_keyboard *
352weston_keyboard_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400353{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400354 struct weston_keyboard *keyboard;
355
356 keyboard = malloc(sizeof *keyboard);
357 if (keyboard == NULL)
358 return NULL;
359
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400360 memset(keyboard, 0, sizeof *keyboard);
361 wl_list_init(&keyboard->resource_list);
362 wl_array_init(&keyboard->keys);
363 keyboard->focus_listener.notify = lose_keyboard_focus;
364 keyboard->default_grab.interface = &default_keyboard_grab_interface;
365 keyboard->default_grab.keyboard = keyboard;
366 keyboard->grab = &keyboard->default_grab;
367 wl_signal_init(&keyboard->focus_signal);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400368
369 return keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400370}
371
372WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400373weston_keyboard_destroy(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400374{
375 /* XXX: What about keyboard->resource_list? */
376 if (keyboard->focus_resource)
377 wl_list_remove(&keyboard->focus_listener.link);
378 wl_array_release(&keyboard->keys);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400379 free(keyboard);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400380}
381
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400382WL_EXPORT struct weston_touch *
383weston_touch_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400384{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400385 struct weston_touch *touch;
386
387 touch = malloc(sizeof *touch);
388 if (touch == NULL)
389 return NULL;
390
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400391 memset(touch, 0, sizeof *touch);
392 wl_list_init(&touch->resource_list);
393 touch->focus_listener.notify = lose_touch_focus;
394 touch->default_grab.interface = &default_touch_grab_interface;
395 touch->default_grab.touch = touch;
396 touch->grab = &touch->default_grab;
397 wl_signal_init(&touch->focus_signal);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400398
399 return touch;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400400}
401
402WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400403weston_touch_destroy(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400404{
405 /* XXX: What about touch->resource_list? */
406 if (touch->focus_resource)
407 wl_list_remove(&touch->focus_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400408 free(touch);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400409}
410
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400411static void
Kristian Høgsberge3148752013-05-06 23:19:49 -0400412seat_send_updated_caps(struct weston_seat *seat)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400413{
414 struct wl_resource *r;
415 enum wl_seat_capability caps = 0;
416
417 if (seat->pointer)
418 caps |= WL_SEAT_CAPABILITY_POINTER;
419 if (seat->keyboard)
420 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
421 if (seat->touch)
422 caps |= WL_SEAT_CAPABILITY_TOUCH;
423
424 wl_list_for_each(r, &seat->base_resource_list, link)
425 wl_seat_send_capabilities(r, caps);
426}
427
428WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400429weston_pointer_set_focus(struct weston_pointer *pointer,
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400430 struct weston_surface *surface,
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400431 wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400432{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400433 struct weston_keyboard *kbd = pointer->seat->keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400434 struct wl_resource *resource, *kr;
435 struct wl_display *display;
436 uint32_t serial;
437
438 resource = pointer->focus_resource;
439 if (resource && pointer->focus != surface) {
440 display = wl_client_get_display(resource->client);
441 serial = wl_display_next_serial(display);
442 wl_pointer_send_leave(resource, serial,
443 &pointer->focus->resource);
444 wl_list_remove(&pointer->focus_listener.link);
445 }
446
447 resource = find_resource_for_surface(&pointer->resource_list,
448 surface);
449 if (resource &&
450 (pointer->focus != surface ||
451 pointer->focus_resource != resource)) {
452 display = wl_client_get_display(resource->client);
453 serial = wl_display_next_serial(display);
454 if (kbd) {
455 kr = find_resource_for_surface(&kbd->resource_list,
456 surface);
457 if (kr) {
458 wl_keyboard_send_modifiers(kr,
459 serial,
460 kbd->modifiers.mods_depressed,
461 kbd->modifiers.mods_latched,
462 kbd->modifiers.mods_locked,
463 kbd->modifiers.group);
464 }
465 }
466 wl_pointer_send_enter(resource, serial, &surface->resource,
467 sx, sy);
468 wl_signal_add(&resource->destroy_signal,
469 &pointer->focus_listener);
470 pointer->focus_serial = serial;
471 }
472
473 pointer->focus_resource = resource;
474 pointer->focus = surface;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400475 wl_signal_emit(&pointer->focus_signal, pointer);
476}
477
478WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400479weston_keyboard_set_focus(struct weston_keyboard *keyboard,
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400480 struct weston_surface *surface)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400481{
482 struct wl_resource *resource;
483 struct wl_display *display;
484 uint32_t serial;
485
486 if (keyboard->focus_resource && keyboard->focus != surface) {
487 resource = keyboard->focus_resource;
488 display = wl_client_get_display(resource->client);
489 serial = wl_display_next_serial(display);
490 wl_keyboard_send_leave(resource, serial,
491 &keyboard->focus->resource);
492 wl_list_remove(&keyboard->focus_listener.link);
493 }
494
495 resource = find_resource_for_surface(&keyboard->resource_list,
496 surface);
497 if (resource &&
498 (keyboard->focus != surface ||
499 keyboard->focus_resource != resource)) {
500 display = wl_client_get_display(resource->client);
501 serial = wl_display_next_serial(display);
502 wl_keyboard_send_modifiers(resource, serial,
503 keyboard->modifiers.mods_depressed,
504 keyboard->modifiers.mods_latched,
505 keyboard->modifiers.mods_locked,
506 keyboard->modifiers.group);
507 wl_keyboard_send_enter(resource, serial, &surface->resource,
508 &keyboard->keys);
509 wl_signal_add(&resource->destroy_signal,
510 &keyboard->focus_listener);
511 keyboard->focus_serial = serial;
512 }
513
514 keyboard->focus_resource = resource;
515 keyboard->focus = surface;
516 wl_signal_emit(&keyboard->focus_signal, keyboard);
517}
518
519WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400520weston_keyboard_start_grab(struct weston_keyboard *keyboard,
521 struct weston_keyboard_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400522{
523 keyboard->grab = grab;
524 grab->keyboard = keyboard;
525
526 /* XXX focus? */
527}
528
529WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400530weston_keyboard_end_grab(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400531{
532 keyboard->grab = &keyboard->default_grab;
533}
534
535WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400536weston_pointer_start_grab(struct weston_pointer *pointer,
537 struct weston_pointer_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400538{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400539 const struct weston_pointer_grab_interface *interface;
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400540 struct weston_compositor *compositor = pointer->seat->compositor;
541 struct weston_surface *surface;
542 wl_fixed_t sx, sy;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400543
544 pointer->grab = grab;
545 interface = pointer->grab->interface;
546 grab->pointer = pointer;
547
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400548 surface = weston_compositor_pick_surface(compositor,
549 pointer->x, pointer->y,
550 &sx, &sy);
551
552 if (surface)
553 interface->focus(pointer->grab, surface, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400554}
555
556WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400557weston_pointer_end_grab(struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400558{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400559 const struct weston_pointer_grab_interface *interface;
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400560 struct weston_compositor *compositor = pointer->seat->compositor;
561 struct weston_surface *surface;
562 wl_fixed_t sx, sy;
563
564 surface = weston_compositor_pick_surface(compositor,
565 pointer->x, pointer->y,
566 &sx, &sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400567
568 pointer->grab = &pointer->default_grab;
569 interface = pointer->grab->interface;
Kristian Høgsberge122b7b2013-05-08 16:47:00 -0400570 interface->focus(pointer->grab, surface, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400571}
572
573WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -0400574weston_touch_start_grab(struct weston_touch *touch, struct weston_touch_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400575{
576 touch->grab = grab;
577 grab->touch = touch;
578}
579
580WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -0400581weston_touch_end_grab(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400582{
583 touch->grab = &touch->default_grab;
584}
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400585
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400586static void
587clip_pointer_motion(struct weston_seat *seat, wl_fixed_t *fx, wl_fixed_t *fy)
588{
589 struct weston_compositor *ec = seat->compositor;
590 struct weston_output *output, *prev = NULL;
591 int x, y, old_x, old_y, valid = 0;
592
593 x = wl_fixed_to_int(*fx);
594 y = wl_fixed_to_int(*fy);
Kristian Høgsberge3148752013-05-06 23:19:49 -0400595 old_x = wl_fixed_to_int(seat->pointer->x);
596 old_y = wl_fixed_to_int(seat->pointer->y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400597
598 wl_list_for_each(output, &ec->output_list, link) {
599 if (pixman_region32_contains_point(&output->region,
600 x, y, NULL))
601 valid = 1;
602 if (pixman_region32_contains_point(&output->region,
603 old_x, old_y, NULL))
604 prev = output;
605 }
606
607 if (!valid) {
608 if (x < prev->x)
609 *fx = wl_fixed_from_int(prev->x);
610 else if (x >= prev->x + prev->width)
611 *fx = wl_fixed_from_int(prev->x +
612 prev->width - 1);
613 if (y < prev->y)
614 *fy = wl_fixed_from_int(prev->y);
615 else if (y >= prev->y + prev->current->height)
616 *fy = wl_fixed_from_int(prev->y +
617 prev->height - 1);
618 }
619}
620
621/* Takes absolute values */
622static void
623move_pointer(struct weston_seat *seat, wl_fixed_t x, wl_fixed_t y)
624{
625 struct weston_compositor *ec = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400626 struct weston_pointer *pointer = seat->pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400627 struct weston_output *output;
628 int32_t ix, iy;
629
630 clip_pointer_motion(seat, &x, &y);
631
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400632 pointer->x = x;
633 pointer->y = y;
634
635 ix = wl_fixed_to_int(x);
636 iy = wl_fixed_to_int(y);
637
638 wl_list_for_each(output, &ec->output_list, link)
639 if (output->zoom.active &&
640 pixman_region32_contains_point(&output->region,
641 ix, iy, NULL))
642 weston_output_update_zoom(output, ZOOM_FOCUS_POINTER);
643
Kristian Høgsberga71e8b22013-05-06 21:51:21 -0400644 weston_seat_repick(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400645
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400646 if (pointer->sprite) {
647 weston_surface_set_position(pointer->sprite,
648 ix - pointer->hotspot_x,
649 iy - pointer->hotspot_y);
650 weston_surface_schedule_repaint(pointer->sprite);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400651 }
652}
653
654WL_EXPORT void
655notify_motion(struct weston_seat *seat,
656 uint32_t time, wl_fixed_t dx, wl_fixed_t dy)
657{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400658 const struct weston_pointer_grab_interface *interface;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400659 struct weston_compositor *ec = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400660 struct weston_pointer *pointer = seat->pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400661
662 weston_compositor_wake(ec);
663
664 move_pointer(seat, pointer->x + dx, pointer->y + dy);
665
666 interface = pointer->grab->interface;
Kristian Høgsbergbe6403e2013-05-08 21:03:21 -0400667 interface->motion(pointer->grab, time);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400668}
669
670WL_EXPORT void
671notify_motion_absolute(struct weston_seat *seat,
672 uint32_t time, wl_fixed_t x, wl_fixed_t y)
673{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400674 const struct weston_pointer_grab_interface *interface;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400675 struct weston_compositor *ec = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400676 struct weston_pointer *pointer = seat->pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400677
678 weston_compositor_wake(ec);
679
680 move_pointer(seat, x, y);
681
682 interface = pointer->grab->interface;
Kristian Høgsbergbe6403e2013-05-08 21:03:21 -0400683 interface->motion(pointer->grab, time);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400684}
685
686WL_EXPORT void
687weston_surface_activate(struct weston_surface *surface,
688 struct weston_seat *seat)
689{
690 struct weston_compositor *compositor = seat->compositor;
691
Kristian Høgsberge3148752013-05-06 23:19:49 -0400692 if (seat->keyboard) {
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400693 weston_keyboard_set_focus(seat->keyboard, surface);
Kristian Høgsberge3148752013-05-06 23:19:49 -0400694 wl_data_device_set_keyboard_focus(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400695 }
696
697 wl_signal_emit(&compositor->activate_signal, surface);
698}
699
700WL_EXPORT void
701notify_button(struct weston_seat *seat, uint32_t time, int32_t button,
702 enum wl_pointer_button_state state)
703{
704 struct weston_compositor *compositor = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400705 struct weston_pointer *pointer = seat->pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400706 struct weston_surface *focus =
707 (struct weston_surface *) pointer->focus;
708 uint32_t serial = wl_display_next_serial(compositor->wl_display);
709
710 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
711 if (compositor->ping_handler && focus)
712 compositor->ping_handler(focus, serial);
713 weston_compositor_idle_inhibit(compositor);
714 if (pointer->button_count == 0) {
715 pointer->grab_button = button;
716 pointer->grab_time = time;
717 pointer->grab_x = pointer->x;
718 pointer->grab_y = pointer->y;
719 }
720 pointer->button_count++;
721 } else {
722 weston_compositor_idle_release(compositor);
723 pointer->button_count--;
724 }
725
726 weston_compositor_run_button_binding(compositor, seat, time, button,
727 state);
728
729 pointer->grab->interface->button(pointer->grab, time, button, state);
730
731 if (pointer->button_count == 1)
732 pointer->grab_serial =
733 wl_display_get_serial(compositor->wl_display);
734}
735
736WL_EXPORT void
737notify_axis(struct weston_seat *seat, uint32_t time, uint32_t axis,
738 wl_fixed_t value)
739{
740 struct weston_compositor *compositor = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400741 struct weston_pointer *pointer = seat->pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400742 struct weston_surface *focus =
743 (struct weston_surface *) pointer->focus;
744 uint32_t serial = wl_display_next_serial(compositor->wl_display);
745
746 if (compositor->ping_handler && focus)
747 compositor->ping_handler(focus, serial);
748
749 weston_compositor_wake(compositor);
750
751 if (!value)
752 return;
753
754 if (weston_compositor_run_axis_binding(compositor, seat,
755 time, axis, value))
756 return;
757
758 if (pointer->focus_resource)
759 wl_pointer_send_axis(pointer->focus_resource, time, axis,
760 value);
761}
762
763WL_EXPORT void
764notify_modifiers(struct weston_seat *seat, uint32_t serial)
765{
Kristian Høgsberge3148752013-05-06 23:19:49 -0400766 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400767 struct weston_keyboard_grab *grab = keyboard->grab;
768 uint32_t mods_depressed, mods_latched, mods_locked, group;
769 uint32_t mods_lookup;
770 enum weston_led leds = 0;
771 int changed = 0;
772
773 /* Serialize and update our internal state, checking to see if it's
774 * different to the previous state. */
775 mods_depressed = xkb_state_serialize_mods(seat->xkb_state.state,
776 XKB_STATE_DEPRESSED);
777 mods_latched = xkb_state_serialize_mods(seat->xkb_state.state,
778 XKB_STATE_LATCHED);
779 mods_locked = xkb_state_serialize_mods(seat->xkb_state.state,
780 XKB_STATE_LOCKED);
781 group = xkb_state_serialize_group(seat->xkb_state.state,
782 XKB_STATE_EFFECTIVE);
783
Kristian Høgsberge3148752013-05-06 23:19:49 -0400784 if (mods_depressed != seat->keyboard->modifiers.mods_depressed ||
785 mods_latched != seat->keyboard->modifiers.mods_latched ||
786 mods_locked != seat->keyboard->modifiers.mods_locked ||
787 group != seat->keyboard->modifiers.group)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400788 changed = 1;
789
Kristian Høgsberge3148752013-05-06 23:19:49 -0400790 seat->keyboard->modifiers.mods_depressed = mods_depressed;
791 seat->keyboard->modifiers.mods_latched = mods_latched;
792 seat->keyboard->modifiers.mods_locked = mods_locked;
793 seat->keyboard->modifiers.group = group;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400794
795 /* And update the modifier_state for bindings. */
796 mods_lookup = mods_depressed | mods_latched;
797 seat->modifier_state = 0;
798 if (mods_lookup & (1 << seat->xkb_info.ctrl_mod))
799 seat->modifier_state |= MODIFIER_CTRL;
800 if (mods_lookup & (1 << seat->xkb_info.alt_mod))
801 seat->modifier_state |= MODIFIER_ALT;
802 if (mods_lookup & (1 << seat->xkb_info.super_mod))
803 seat->modifier_state |= MODIFIER_SUPER;
804 if (mods_lookup & (1 << seat->xkb_info.shift_mod))
805 seat->modifier_state |= MODIFIER_SHIFT;
806
807 /* Finally, notify the compositor that LEDs have changed. */
808 if (xkb_state_led_index_is_active(seat->xkb_state.state,
809 seat->xkb_info.num_led))
810 leds |= LED_NUM_LOCK;
811 if (xkb_state_led_index_is_active(seat->xkb_state.state,
812 seat->xkb_info.caps_led))
813 leds |= LED_CAPS_LOCK;
814 if (xkb_state_led_index_is_active(seat->xkb_state.state,
815 seat->xkb_info.scroll_led))
816 leds |= LED_SCROLL_LOCK;
817 if (leds != seat->xkb_state.leds && seat->led_update)
818 seat->led_update(seat, leds);
819 seat->xkb_state.leds = leds;
820
821 if (changed) {
822 grab->interface->modifiers(grab,
823 serial,
824 keyboard->modifiers.mods_depressed,
825 keyboard->modifiers.mods_latched,
826 keyboard->modifiers.mods_locked,
827 keyboard->modifiers.group);
828 }
829}
830
831static void
832update_modifier_state(struct weston_seat *seat, uint32_t serial, uint32_t key,
833 enum wl_keyboard_key_state state)
834{
835 enum xkb_key_direction direction;
836
837 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
838 direction = XKB_KEY_DOWN;
839 else
840 direction = XKB_KEY_UP;
841
842 /* Offset the keycode by 8, as the evdev XKB rules reflect X's
843 * broken keycode system, which starts at 8. */
844 xkb_state_update_key(seat->xkb_state.state, key + 8, direction);
845
846 notify_modifiers(seat, serial);
847}
848
849WL_EXPORT void
850notify_key(struct weston_seat *seat, uint32_t time, uint32_t key,
851 enum wl_keyboard_key_state state,
852 enum weston_key_state_update update_state)
853{
854 struct weston_compositor *compositor = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400855 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400856 struct weston_surface *focus =
857 (struct weston_surface *) keyboard->focus;
858 struct weston_keyboard_grab *grab = keyboard->grab;
859 uint32_t serial = wl_display_next_serial(compositor->wl_display);
860 uint32_t *k, *end;
861
862 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
863 if (compositor->ping_handler && focus)
864 compositor->ping_handler(focus, serial);
865
866 weston_compositor_idle_inhibit(compositor);
867 keyboard->grab_key = key;
868 keyboard->grab_time = time;
869 } else {
870 weston_compositor_idle_release(compositor);
871 }
872
873 end = keyboard->keys.data + keyboard->keys.size;
874 for (k = keyboard->keys.data; k < end; k++) {
875 if (*k == key) {
876 /* Ignore server-generated repeats. */
877 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
878 return;
879 *k = *--end;
880 }
881 }
882 keyboard->keys.size = (void *) end - keyboard->keys.data;
883 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
884 k = wl_array_add(&keyboard->keys, sizeof *k);
885 *k = key;
886 }
887
888 if (grab == &keyboard->default_grab ||
889 grab == &keyboard->input_method_grab) {
890 weston_compositor_run_key_binding(compositor, seat, time, key,
891 state);
892 grab = keyboard->grab;
893 }
894
895 grab->interface->key(grab, time, key, state);
896
897 if (update_state == STATE_UPDATE_AUTOMATIC) {
898 update_modifier_state(seat,
899 wl_display_get_serial(compositor->wl_display),
900 key,
901 state);
902 }
903}
904
905WL_EXPORT void
906notify_pointer_focus(struct weston_seat *seat, struct weston_output *output,
907 wl_fixed_t x, wl_fixed_t y)
908{
909 struct weston_compositor *compositor = seat->compositor;
910
911 if (output) {
912 move_pointer(seat, x, y);
913 compositor->focus = 1;
914 } else {
915 compositor->focus = 0;
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400916 /* FIXME: We should call weston_pointer_set_focus(seat,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400917 * NULL) here, but somehow that breaks re-entry... */
918 }
919}
920
921static void
922destroy_device_saved_kbd_focus(struct wl_listener *listener, void *data)
923{
924 struct weston_seat *ws;
925
926 ws = container_of(listener, struct weston_seat,
927 saved_kbd_focus_listener);
928
929 ws->saved_kbd_focus = NULL;
930}
931
932WL_EXPORT void
933notify_keyboard_focus_in(struct weston_seat *seat, struct wl_array *keys,
934 enum weston_key_state_update update_state)
935{
936 struct weston_compositor *compositor = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400937 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400938 struct weston_surface *surface;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400939 uint32_t *k, serial;
940
941 serial = wl_display_next_serial(compositor->wl_display);
942 wl_array_copy(&keyboard->keys, keys);
943 wl_array_for_each(k, &keyboard->keys) {
944 weston_compositor_idle_inhibit(compositor);
945 if (update_state == STATE_UPDATE_AUTOMATIC)
946 update_modifier_state(seat, serial, *k,
947 WL_KEYBOARD_KEY_STATE_PRESSED);
948 }
949
950 /* Run key bindings after we've updated the state. */
951 wl_array_for_each(k, &keyboard->keys) {
952 weston_compositor_run_key_binding(compositor, seat, 0, *k,
953 WL_KEYBOARD_KEY_STATE_PRESSED);
954 }
955
956 surface = seat->saved_kbd_focus;
957
958 if (surface) {
959 wl_list_remove(&seat->saved_kbd_focus_listener.link);
960 weston_keyboard_set_focus(keyboard, surface);
961 seat->saved_kbd_focus = NULL;
962 }
963}
964
965WL_EXPORT void
966notify_keyboard_focus_out(struct weston_seat *seat)
967{
968 struct weston_compositor *compositor = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400969 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400970 uint32_t *k, serial;
971
972 serial = wl_display_next_serial(compositor->wl_display);
973 wl_array_for_each(k, &keyboard->keys) {
974 weston_compositor_idle_release(compositor);
975 update_modifier_state(seat, serial, *k,
976 WL_KEYBOARD_KEY_STATE_RELEASED);
977 }
978
979 seat->modifier_state = 0;
980
981 if (keyboard->focus) {
982 seat->saved_kbd_focus = keyboard->focus;
983 seat->saved_kbd_focus_listener.notify =
984 destroy_device_saved_kbd_focus;
985 wl_signal_add(&keyboard->focus->resource.destroy_signal,
986 &seat->saved_kbd_focus_listener);
987 }
988
989 weston_keyboard_set_focus(keyboard, NULL);
990 /* FIXME: We really need keyboard grab cancel here to
991 * let the grab shut down properly. As it is we leak
992 * the grab data. */
993 weston_keyboard_end_grab(keyboard);
994}
995
996static void
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400997touch_set_focus(struct weston_seat *seat, struct weston_surface *surface)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400998{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400999 struct wl_resource *resource;
1000
1001 if (seat->touch->focus == surface)
1002 return;
1003
1004 if (seat->touch->focus_resource)
1005 wl_list_remove(&seat->touch->focus_listener.link);
1006 seat->touch->focus = NULL;
1007 seat->touch->focus_resource = NULL;
1008
1009 if (surface) {
1010 resource =
Kristian Høgsberg80fb82d2013-05-06 21:49:55 -04001011 find_resource_for_surface(&seat->touch->resource_list,
1012 surface);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001013 if (!resource) {
1014 weston_log("couldn't find resource\n");
1015 return;
1016 }
1017
1018 seat->touch->focus = surface;
1019 seat->touch->focus_resource = resource;
1020 wl_signal_add(&resource->destroy_signal,
1021 &seat->touch->focus_listener);
1022 }
1023}
1024
1025/**
1026 * notify_touch - emulates button touches and notifies surfaces accordingly.
1027 *
1028 * It assumes always the correct cycle sequence until it gets here: touch_down
1029 * → touch_update → ... → touch_update → touch_end. The driver is responsible
1030 * for sending along such order.
1031 *
1032 */
1033WL_EXPORT void
1034notify_touch(struct weston_seat *seat, uint32_t time, int touch_id,
1035 wl_fixed_t x, wl_fixed_t y, int touch_type)
1036{
1037 struct weston_compositor *ec = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -04001038 struct weston_touch *touch = seat->touch;
Kristian Høgsberge329f362013-05-06 22:19:57 -04001039 struct weston_touch_grab *grab = touch->grab;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001040 struct weston_surface *es;
1041 wl_fixed_t sx, sy;
1042
1043 /* Update grab's global coordinates. */
1044 touch->grab_x = x;
1045 touch->grab_y = y;
1046
1047 switch (touch_type) {
1048 case WL_TOUCH_DOWN:
1049 weston_compositor_idle_inhibit(ec);
1050
1051 seat->num_tp++;
1052
1053 /* the first finger down picks the surface, and all further go
1054 * to that surface for the remainder of the touch session i.e.
1055 * until all touch points are up again. */
1056 if (seat->num_tp == 1) {
1057 es = weston_compositor_pick_surface(ec, x, y, &sx, &sy);
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -04001058 touch_set_focus(seat, es);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001059 } else if (touch->focus) {
1060 es = (struct weston_surface *) touch->focus;
1061 weston_surface_from_global_fixed(es, x, y, &sx, &sy);
1062 } else {
1063 /* Unexpected condition: We have non-initial touch but
1064 * there is no focused surface.
1065 */
1066 weston_log("touch event received with %d points down"
1067 "but no surface focused\n", seat->num_tp);
1068 return;
1069 }
1070
1071 grab->interface->down(grab, time, touch_id, sx, sy);
1072 break;
1073 case WL_TOUCH_MOTION:
1074 es = (struct weston_surface *) touch->focus;
1075 if (!es)
1076 break;
1077
1078 weston_surface_from_global_fixed(es, x, y, &sx, &sy);
1079 grab->interface->motion(grab, time, touch_id, sx, sy);
1080 break;
1081 case WL_TOUCH_UP:
1082 weston_compositor_idle_release(ec);
1083 seat->num_tp--;
1084
1085 grab->interface->up(grab, time, touch_id);
1086 if (seat->num_tp == 0)
1087 touch_set_focus(seat, NULL);
1088 break;
1089 }
1090}
1091
1092static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001093pointer_cursor_surface_configure(struct weston_surface *es,
1094 int32_t dx, int32_t dy, int32_t width, int32_t height)
1095{
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001096 struct weston_pointer *pointer = es->configure_private;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001097 int x, y;
1098
1099 if (width == 0)
1100 return;
1101
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001102 assert(es == pointer->sprite);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001103
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001104 pointer->hotspot_x -= dx;
1105 pointer->hotspot_y -= dy;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001106
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001107 x = wl_fixed_to_int(pointer->x) - pointer->hotspot_x;
1108 y = wl_fixed_to_int(pointer->y) - pointer->hotspot_y;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001109
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001110 weston_surface_configure(pointer->sprite, x, y, width, height);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001111
1112 empty_region(&es->pending.input);
1113
1114 if (!weston_surface_is_mapped(es)) {
1115 wl_list_insert(&es->compositor->cursor_layer.surface_list,
1116 &es->layer_link);
1117 weston_surface_update_transform(es);
1118 }
1119}
1120
1121static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001122pointer_set_cursor(struct wl_client *client, struct wl_resource *resource,
1123 uint32_t serial, struct wl_resource *surface_resource,
1124 int32_t x, int32_t y)
1125{
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001126 struct weston_pointer *pointer = resource->data;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001127 struct weston_surface *surface = NULL;
1128
1129 if (surface_resource)
1130 surface = surface_resource->data;
1131
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001132 if (pointer->focus == NULL)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001133 return;
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001134 if (pointer->focus->resource.client != client)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001135 return;
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001136 if (pointer->focus_serial - serial > UINT32_MAX / 2)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001137 return;
1138
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001139 if (surface && surface != pointer->sprite) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001140 if (surface->configure) {
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -04001141 wl_resource_post_error(&surface->resource,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001142 WL_DISPLAY_ERROR_INVALID_OBJECT,
1143 "surface->configure already "
1144 "set");
1145 return;
1146 }
1147 }
1148
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001149 if (pointer->sprite)
1150 pointer_unmap_sprite(pointer);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001151
1152 if (!surface)
1153 return;
1154
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -04001155 wl_signal_add(&surface->resource.destroy_signal,
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001156 &pointer->sprite_destroy_listener);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001157
1158 surface->configure = pointer_cursor_surface_configure;
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001159 surface->configure_private = pointer;
1160 pointer->sprite = surface;
1161 pointer->hotspot_x = x;
1162 pointer->hotspot_y = y;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001163
1164 if (surface->buffer_ref.buffer)
1165 pointer_cursor_surface_configure(surface, 0, 0, weston_surface_buffer_width(surface),
1166 weston_surface_buffer_height(surface));
1167}
1168
1169static const struct wl_pointer_interface pointer_interface = {
1170 pointer_set_cursor
1171};
1172
1173static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001174seat_get_pointer(struct wl_client *client, struct wl_resource *resource,
1175 uint32_t id)
1176{
1177 struct weston_seat *seat = resource->data;
1178 struct wl_resource *cr;
1179
Kristian Høgsberge3148752013-05-06 23:19:49 -04001180 if (!seat->pointer)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001181 return;
1182
1183 cr = wl_client_add_object(client, &wl_pointer_interface,
Kristian Høgsberg195b8692013-05-08 15:02:05 -04001184 &pointer_interface, id, seat->pointer);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001185 wl_list_insert(&seat->pointer->resource_list, &cr->link);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001186 cr->destroy = unbind_resource;
1187
Kristian Høgsberge3148752013-05-06 23:19:49 -04001188 if (seat->pointer->focus &&
1189 seat->pointer->focus->resource.client == client) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001190 struct weston_surface *surface;
1191 wl_fixed_t sx, sy;
1192
Kristian Høgsberge3148752013-05-06 23:19:49 -04001193 surface = (struct weston_surface *) seat->pointer->focus;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001194 weston_surface_from_global_fixed(surface,
Kristian Høgsberge3148752013-05-06 23:19:49 -04001195 seat->pointer->x,
1196 seat->pointer->y,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001197 &sx,
1198 &sy);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001199 weston_pointer_set_focus(seat->pointer,
1200 seat->pointer->focus,
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001201 sx,
1202 sy);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001203 }
1204}
1205
1206static void
1207seat_get_keyboard(struct wl_client *client, struct wl_resource *resource,
1208 uint32_t id)
1209{
1210 struct weston_seat *seat = resource->data;
1211 struct wl_resource *cr;
1212
Kristian Høgsberge3148752013-05-06 23:19:49 -04001213 if (!seat->keyboard)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001214 return;
1215
1216 cr = wl_client_add_object(client, &wl_keyboard_interface, NULL, id,
1217 seat);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001218 wl_list_insert(&seat->keyboard->resource_list, &cr->link);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001219 cr->destroy = unbind_resource;
1220
1221 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
1222 seat->xkb_info.keymap_fd,
1223 seat->xkb_info.keymap_size);
1224
Kristian Høgsberge3148752013-05-06 23:19:49 -04001225 if (seat->keyboard->focus &&
1226 seat->keyboard->focus->resource.client == client) {
1227 weston_keyboard_set_focus(seat->keyboard,
1228 seat->keyboard->focus);
1229 wl_data_device_set_keyboard_focus(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001230 }
1231}
1232
1233static void
1234seat_get_touch(struct wl_client *client, struct wl_resource *resource,
1235 uint32_t id)
1236{
1237 struct weston_seat *seat = resource->data;
1238 struct wl_resource *cr;
1239
Kristian Høgsberge3148752013-05-06 23:19:49 -04001240 if (!seat->touch)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001241 return;
1242
1243 cr = wl_client_add_object(client, &wl_touch_interface, NULL, id, seat);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001244 wl_list_insert(&seat->touch->resource_list, &cr->link);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001245 cr->destroy = unbind_resource;
1246}
1247
1248static const struct wl_seat_interface seat_interface = {
1249 seat_get_pointer,
1250 seat_get_keyboard,
1251 seat_get_touch,
1252};
1253
1254static void
1255bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
1256{
Kristian Høgsberge3148752013-05-06 23:19:49 -04001257 struct weston_seat *seat = data;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001258 struct wl_resource *resource;
1259 enum wl_seat_capability caps = 0;
1260
1261 resource = wl_client_add_object(client, &wl_seat_interface,
1262 &seat_interface, id, data);
1263 wl_list_insert(&seat->base_resource_list, &resource->link);
1264 resource->destroy = unbind_resource;
1265
1266 if (seat->pointer)
1267 caps |= WL_SEAT_CAPABILITY_POINTER;
1268 if (seat->keyboard)
1269 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
1270 if (seat->touch)
1271 caps |= WL_SEAT_CAPABILITY_TOUCH;
1272
1273 wl_seat_send_capabilities(resource, caps);
1274}
1275
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001276int
1277weston_compositor_xkb_init(struct weston_compositor *ec,
1278 struct xkb_rule_names *names)
1279{
1280 if (ec->xkb_context == NULL) {
1281 ec->xkb_context = xkb_context_new(0);
1282 if (ec->xkb_context == NULL) {
1283 weston_log("failed to create XKB context\n");
1284 return -1;
1285 }
1286 }
1287
1288 if (names)
1289 ec->xkb_names = *names;
1290 if (!ec->xkb_names.rules)
1291 ec->xkb_names.rules = strdup("evdev");
1292 if (!ec->xkb_names.model)
1293 ec->xkb_names.model = strdup("pc105");
1294 if (!ec->xkb_names.layout)
1295 ec->xkb_names.layout = strdup("us");
1296
1297 return 0;
1298}
1299
1300static void xkb_info_destroy(struct weston_xkb_info *xkb_info)
1301{
1302 if (xkb_info->keymap)
1303 xkb_map_unref(xkb_info->keymap);
1304
1305 if (xkb_info->keymap_area)
1306 munmap(xkb_info->keymap_area, xkb_info->keymap_size);
1307 if (xkb_info->keymap_fd >= 0)
1308 close(xkb_info->keymap_fd);
1309}
1310
1311void
1312weston_compositor_xkb_destroy(struct weston_compositor *ec)
1313{
1314 free((char *) ec->xkb_names.rules);
1315 free((char *) ec->xkb_names.model);
1316 free((char *) ec->xkb_names.layout);
1317 free((char *) ec->xkb_names.variant);
1318 free((char *) ec->xkb_names.options);
1319
1320 xkb_info_destroy(&ec->xkb_info);
1321 xkb_context_unref(ec->xkb_context);
1322}
1323
1324static int
1325weston_xkb_info_new_keymap(struct weston_xkb_info *xkb_info)
1326{
1327 char *keymap_str;
1328
1329 xkb_info->shift_mod = xkb_map_mod_get_index(xkb_info->keymap,
1330 XKB_MOD_NAME_SHIFT);
1331 xkb_info->caps_mod = xkb_map_mod_get_index(xkb_info->keymap,
1332 XKB_MOD_NAME_CAPS);
1333 xkb_info->ctrl_mod = xkb_map_mod_get_index(xkb_info->keymap,
1334 XKB_MOD_NAME_CTRL);
1335 xkb_info->alt_mod = xkb_map_mod_get_index(xkb_info->keymap,
1336 XKB_MOD_NAME_ALT);
1337 xkb_info->mod2_mod = xkb_map_mod_get_index(xkb_info->keymap, "Mod2");
1338 xkb_info->mod3_mod = xkb_map_mod_get_index(xkb_info->keymap, "Mod3");
1339 xkb_info->super_mod = xkb_map_mod_get_index(xkb_info->keymap,
1340 XKB_MOD_NAME_LOGO);
1341 xkb_info->mod5_mod = xkb_map_mod_get_index(xkb_info->keymap, "Mod5");
1342
1343 xkb_info->num_led = xkb_map_led_get_index(xkb_info->keymap,
1344 XKB_LED_NAME_NUM);
1345 xkb_info->caps_led = xkb_map_led_get_index(xkb_info->keymap,
1346 XKB_LED_NAME_CAPS);
1347 xkb_info->scroll_led = xkb_map_led_get_index(xkb_info->keymap,
1348 XKB_LED_NAME_SCROLL);
1349
1350 keymap_str = xkb_map_get_as_string(xkb_info->keymap);
1351 if (keymap_str == NULL) {
1352 weston_log("failed to get string version of keymap\n");
1353 return -1;
1354 }
1355 xkb_info->keymap_size = strlen(keymap_str) + 1;
1356
1357 xkb_info->keymap_fd = os_create_anonymous_file(xkb_info->keymap_size);
1358 if (xkb_info->keymap_fd < 0) {
1359 weston_log("creating a keymap file for %lu bytes failed: %m\n",
1360 (unsigned long) xkb_info->keymap_size);
1361 goto err_keymap_str;
1362 }
1363
1364 xkb_info->keymap_area = mmap(NULL, xkb_info->keymap_size,
1365 PROT_READ | PROT_WRITE,
1366 MAP_SHARED, xkb_info->keymap_fd, 0);
1367 if (xkb_info->keymap_area == MAP_FAILED) {
1368 weston_log("failed to mmap() %lu bytes\n",
1369 (unsigned long) xkb_info->keymap_size);
1370 goto err_dev_zero;
1371 }
1372 strcpy(xkb_info->keymap_area, keymap_str);
1373 free(keymap_str);
1374
1375 return 0;
1376
1377err_dev_zero:
1378 close(xkb_info->keymap_fd);
1379 xkb_info->keymap_fd = -1;
1380err_keymap_str:
1381 free(keymap_str);
1382 return -1;
1383}
1384
1385static int
1386weston_compositor_build_global_keymap(struct weston_compositor *ec)
1387{
1388 if (ec->xkb_info.keymap != NULL)
1389 return 0;
1390
1391 ec->xkb_info.keymap = xkb_map_new_from_names(ec->xkb_context,
1392 &ec->xkb_names,
1393 0);
1394 if (ec->xkb_info.keymap == NULL) {
1395 weston_log("failed to compile global XKB keymap\n");
1396 weston_log(" tried rules %s, model %s, layout %s, variant %s, "
1397 "options %s\n",
1398 ec->xkb_names.rules, ec->xkb_names.model,
1399 ec->xkb_names.layout, ec->xkb_names.variant,
1400 ec->xkb_names.options);
1401 return -1;
1402 }
1403
1404 if (weston_xkb_info_new_keymap(&ec->xkb_info) < 0)
1405 return -1;
1406
1407 return 0;
1408}
1409
1410WL_EXPORT int
1411weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap)
1412{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001413 struct weston_keyboard *keyboard;
1414
Kristian Høgsberg2bf87622013-05-07 23:17:41 -04001415 if (seat->keyboard)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001416 return 0;
1417
1418 if (keymap != NULL) {
1419 seat->xkb_info.keymap = xkb_map_ref(keymap);
1420 if (weston_xkb_info_new_keymap(&seat->xkb_info) < 0)
1421 return -1;
1422 } else {
1423 if (weston_compositor_build_global_keymap(seat->compositor) < 0)
1424 return -1;
1425 seat->xkb_info = seat->compositor->xkb_info;
1426 seat->xkb_info.keymap = xkb_map_ref(seat->xkb_info.keymap);
1427 }
1428
1429 seat->xkb_state.state = xkb_state_new(seat->xkb_info.keymap);
1430 if (seat->xkb_state.state == NULL) {
1431 weston_log("failed to initialise XKB state\n");
1432 return -1;
1433 }
1434
1435 seat->xkb_state.leds = 0;
1436
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001437 keyboard = weston_keyboard_create();
1438 if (keyboard == NULL) {
1439 weston_log("failed to allocate weston keyboard struct\n");
1440 return -1;
1441 }
1442
1443 seat->keyboard = keyboard;
1444 keyboard->seat = seat;
1445
1446 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001447
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001448 return 0;
1449}
1450
1451WL_EXPORT void
1452weston_seat_init_pointer(struct weston_seat *seat)
1453{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001454 struct weston_pointer *pointer;
1455
Kristian Høgsberg2bf87622013-05-07 23:17:41 -04001456 if (seat->pointer)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001457 return;
1458
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001459 pointer = weston_pointer_create();
1460 if (pointer == NULL)
1461 return;
1462
1463 seat->pointer = pointer;
1464 pointer->seat = seat;
1465
1466 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001467}
1468
1469WL_EXPORT void
1470weston_seat_init_touch(struct weston_seat *seat)
1471{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001472 struct weston_touch *touch;
1473
Kristian Høgsberg2bf87622013-05-07 23:17:41 -04001474 if (seat->touch)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001475 return;
1476
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001477 touch = weston_touch_create();
1478 if (touch == NULL)
1479 return;
1480
1481 seat->touch = touch;
1482 touch->seat = seat;
1483
1484 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001485}
1486
1487WL_EXPORT void
1488weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec)
1489{
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04001490 memset(seat, 0, sizeof *seat);
1491
Kristian Høgsberge3148752013-05-06 23:19:49 -04001492 seat->selection_data_source = NULL;
1493 wl_list_init(&seat->base_resource_list);
1494 wl_signal_init(&seat->selection_signal);
1495 wl_list_init(&seat->drag_resource_list);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001496 wl_signal_init(&seat->destroy_signal);
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04001497
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001498 wl_display_add_global(ec->wl_display, &wl_seat_interface, seat,
1499 bind_seat);
1500
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001501 seat->compositor = ec;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001502 seat->modifier_state = 0;
1503 seat->num_tp = 0;
1504
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001505 wl_list_insert(ec->seat_list.prev, &seat->link);
1506
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001507 clipboard_create(seat);
1508
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001509 wl_signal_emit(&ec->seat_created_signal, seat);
1510}
1511
1512WL_EXPORT void
1513weston_seat_release(struct weston_seat *seat)
1514{
1515 wl_list_remove(&seat->link);
1516 /* The global object is destroyed at wl_display_destroy() time. */
1517
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001518 if (seat->xkb_state.state != NULL)
1519 xkb_state_unref(seat->xkb_state.state);
1520 xkb_info_destroy(&seat->xkb_info);
1521
Kristian Høgsberge3148752013-05-06 23:19:49 -04001522 if (seat->pointer)
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001523 weston_pointer_destroy(seat->pointer);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001524 if (seat->keyboard)
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001525 weston_keyboard_destroy(seat->keyboard);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001526 if (seat->touch)
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001527 weston_touch_destroy(seat->touch);
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04001528
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001529 wl_signal_emit(&seat->destroy_signal, seat);
1530}