blob: b0286768fe231ce27b055a5aefb333b4b3421d33 [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 struct wl_resource *
34find_resource_for_client(struct wl_list *list, struct wl_client *client)
35{
36 struct wl_resource *r;
37
38 wl_list_for_each(r, list, link) {
39 if (r->client == client)
40 return r;
41 }
42
43 return NULL;
44}
45
46static void
47empty_region(pixman_region32_t *region)
48{
49 pixman_region32_fini(region);
50 pixman_region32_init(region);
51}
52
53static void unbind_resource(struct wl_resource *resource)
54{
55 wl_list_remove(&resource->link);
56 free(resource);
57}
58
59void
60weston_device_repick(struct weston_seat *seat)
61{
62 const struct wl_pointer_grab_interface *interface;
63 struct weston_surface *surface, *focus;
64 struct wl_pointer *pointer = seat->seat.pointer;
65
66 if (!pointer)
67 return;
68
69 surface = weston_compositor_pick_surface(seat->compositor,
70 pointer->x,
71 pointer->y,
72 &pointer->current_x,
73 &pointer->current_y);
74
75 if (&surface->surface != pointer->current) {
76 interface = pointer->grab->interface;
77 wl_pointer_set_current(pointer, &surface->surface);
78 interface->focus(pointer->grab, &surface->surface,
79 pointer->current_x,
80 pointer->current_y);
81 }
82
83 focus = (struct weston_surface *) pointer->grab->focus;
84 if (focus)
85 weston_surface_from_global_fixed(focus,
86 pointer->x,
87 pointer->y,
88 &pointer->grab->x,
89 &pointer->grab->y);
90}
91
92static void
93weston_compositor_idle_inhibit(struct weston_compositor *compositor)
94{
95 weston_compositor_wake(compositor);
96 compositor->idle_inhibit++;
97}
98
99static void
100weston_compositor_idle_release(struct weston_compositor *compositor)
101{
102 compositor->idle_inhibit--;
103 weston_compositor_wake(compositor);
104}
105
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400106static void
107lose_pointer_focus(struct wl_listener *listener, void *data)
108{
109 struct wl_pointer *pointer =
110 container_of(listener, struct wl_pointer, focus_listener);
111
112 pointer->focus_resource = NULL;
113}
114
115static void
116lose_keyboard_focus(struct wl_listener *listener, void *data)
117{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400118 struct weston_keyboard *keyboard =
119 container_of(listener, struct weston_keyboard, focus_listener);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400120
121 keyboard->focus_resource = NULL;
122}
123
124static void
125lose_touch_focus(struct wl_listener *listener, void *data)
126{
127 struct wl_touch *touch =
128 container_of(listener, struct wl_touch, focus_listener);
129
130 touch->focus_resource = NULL;
131}
132
133static void
134default_grab_focus(struct wl_pointer_grab *grab,
135 struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y)
136{
137 struct wl_pointer *pointer = grab->pointer;
138
139 if (pointer->button_count > 0)
140 return;
141
142 wl_pointer_set_focus(pointer, surface, x, y);
143}
144
145static void
146default_grab_motion(struct wl_pointer_grab *grab,
147 uint32_t time, wl_fixed_t x, wl_fixed_t y)
148{
149 struct wl_resource *resource;
150
151 resource = grab->pointer->focus_resource;
152 if (resource)
153 wl_pointer_send_motion(resource, time, x, y);
154}
155
156static void
157default_grab_button(struct wl_pointer_grab *grab,
158 uint32_t time, uint32_t button, uint32_t state_w)
159{
160 struct wl_pointer *pointer = grab->pointer;
161 struct wl_resource *resource;
162 uint32_t serial;
163 enum wl_pointer_button_state state = state_w;
164 struct wl_display *display;
165
166 resource = pointer->focus_resource;
167 if (resource) {
168 display = wl_client_get_display(resource->client);
169 serial = wl_display_next_serial(display);
170 wl_pointer_send_button(resource, serial, time, button, state_w);
171 }
172
173 if (pointer->button_count == 0 &&
174 state == WL_POINTER_BUTTON_STATE_RELEASED)
175 wl_pointer_set_focus(pointer, pointer->current,
176 pointer->current_x, pointer->current_y);
177}
178
179static const struct wl_pointer_grab_interface
180 default_pointer_grab_interface = {
181 default_grab_focus,
182 default_grab_motion,
183 default_grab_button
184};
185
186static void default_grab_touch_down(struct wl_touch_grab *grab,
187 uint32_t time,
188 int touch_id,
189 wl_fixed_t sx,
190 wl_fixed_t sy)
191{
192 struct wl_touch *touch = grab->touch;
193 struct wl_display *display;
194 uint32_t serial;
195
196 if (touch->focus_resource && touch->focus) {
197 display = wl_client_get_display(touch->focus_resource->client);
198 serial = wl_display_next_serial(display);
199 wl_touch_send_down(touch->focus_resource, serial, time,
200 &touch->focus->resource, touch_id, sx, sy);
201 }
202}
203
204static void default_grab_touch_up(struct wl_touch_grab *grab,
205 uint32_t time,
206 int touch_id)
207{
208 struct wl_touch *touch = grab->touch;
209 struct wl_display *display;
210 uint32_t serial;
211
212 if (touch->focus_resource) {
213 display = wl_client_get_display(touch->focus_resource->client);
214 serial = wl_display_next_serial(display);
215 wl_touch_send_up(touch->focus_resource, serial, time, touch_id);
216 }
217}
218
219static void default_grab_touch_motion(struct wl_touch_grab *grab,
220 uint32_t time,
221 int touch_id,
222 wl_fixed_t sx,
223 wl_fixed_t sy)
224{
225 struct wl_touch *touch = grab->touch;
226
227 if (touch->focus_resource) {
228 wl_touch_send_motion(touch->focus_resource, time,
229 touch_id, sx, sy);
230 }
231}
232
233static const struct wl_touch_grab_interface default_touch_grab_interface = {
234 default_grab_touch_down,
235 default_grab_touch_up,
236 default_grab_touch_motion
237};
238
239static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400240default_grab_key(struct weston_keyboard_grab *grab,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400241 uint32_t time, uint32_t key, uint32_t state)
242{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400243 struct weston_keyboard *keyboard = grab->keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400244 struct wl_resource *resource;
245 struct wl_display *display;
246 uint32_t serial;
247
248 resource = keyboard->focus_resource;
249 if (resource) {
250 display = wl_client_get_display(resource->client);
251 serial = wl_display_next_serial(display);
252 wl_keyboard_send_key(resource, serial, time, key, state);
253 }
254}
255
256static struct wl_resource *
257find_resource_for_surface(struct wl_list *list, struct wl_surface *surface)
258{
259 struct wl_resource *r;
260
261 if (!surface)
262 return NULL;
263
264 wl_list_for_each(r, list, link) {
265 if (r->client == surface->resource.client)
266 return r;
267 }
268
269 return NULL;
270}
271
272static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400273default_grab_modifiers(struct weston_keyboard_grab *grab, uint32_t serial,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400274 uint32_t mods_depressed, uint32_t mods_latched,
275 uint32_t mods_locked, uint32_t group)
276{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400277 struct weston_keyboard *keyboard = grab->keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400278 struct wl_pointer *pointer = keyboard->seat->pointer;
279 struct wl_resource *resource, *pr;
280
281 resource = keyboard->focus_resource;
282 if (!resource)
283 return;
284
285 wl_keyboard_send_modifiers(resource, serial, mods_depressed,
286 mods_latched, mods_locked, group);
287
288 if (pointer && pointer->focus && pointer->focus != keyboard->focus) {
289 pr = find_resource_for_surface(&keyboard->resource_list,
290 pointer->focus);
291 if (pr) {
292 wl_keyboard_send_modifiers(pr,
293 serial,
294 keyboard->modifiers.mods_depressed,
295 keyboard->modifiers.mods_latched,
296 keyboard->modifiers.mods_locked,
297 keyboard->modifiers.group);
298 }
299 }
300}
301
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400302static const struct weston_keyboard_grab_interface
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400303 default_keyboard_grab_interface = {
304 default_grab_key,
305 default_grab_modifiers,
306};
307
308WL_EXPORT void
309wl_pointer_init(struct wl_pointer *pointer)
310{
311 memset(pointer, 0, sizeof *pointer);
312 wl_list_init(&pointer->resource_list);
313 pointer->focus_listener.notify = lose_pointer_focus;
314 pointer->default_grab.interface = &default_pointer_grab_interface;
315 pointer->default_grab.pointer = pointer;
316 pointer->grab = &pointer->default_grab;
317 wl_signal_init(&pointer->focus_signal);
318
319 /* FIXME: Pick better co-ords. */
320 pointer->x = wl_fixed_from_int(100);
321 pointer->y = wl_fixed_from_int(100);
322}
323
324WL_EXPORT void
325wl_pointer_release(struct wl_pointer *pointer)
326{
327 /* XXX: What about pointer->resource_list? */
328 if (pointer->focus_resource)
329 wl_list_remove(&pointer->focus_listener.link);
330}
331
332WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400333weston_keyboard_init(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400334{
335 memset(keyboard, 0, sizeof *keyboard);
336 wl_list_init(&keyboard->resource_list);
337 wl_array_init(&keyboard->keys);
338 keyboard->focus_listener.notify = lose_keyboard_focus;
339 keyboard->default_grab.interface = &default_keyboard_grab_interface;
340 keyboard->default_grab.keyboard = keyboard;
341 keyboard->grab = &keyboard->default_grab;
342 wl_signal_init(&keyboard->focus_signal);
343}
344
345WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400346weston_keyboard_release(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400347{
348 /* XXX: What about keyboard->resource_list? */
349 if (keyboard->focus_resource)
350 wl_list_remove(&keyboard->focus_listener.link);
351 wl_array_release(&keyboard->keys);
352}
353
354WL_EXPORT void
355wl_touch_init(struct wl_touch *touch)
356{
357 memset(touch, 0, sizeof *touch);
358 wl_list_init(&touch->resource_list);
359 touch->focus_listener.notify = lose_touch_focus;
360 touch->default_grab.interface = &default_touch_grab_interface;
361 touch->default_grab.touch = touch;
362 touch->grab = &touch->default_grab;
363 wl_signal_init(&touch->focus_signal);
364}
365
366WL_EXPORT void
367wl_touch_release(struct wl_touch *touch)
368{
369 /* XXX: What about touch->resource_list? */
370 if (touch->focus_resource)
371 wl_list_remove(&touch->focus_listener.link);
372}
373
374WL_EXPORT void
375wl_seat_init(struct wl_seat *seat)
376{
377 memset(seat, 0, sizeof *seat);
378
379 wl_signal_init(&seat->destroy_signal);
380
381 seat->selection_data_source = NULL;
382 wl_list_init(&seat->base_resource_list);
383 wl_signal_init(&seat->selection_signal);
384 wl_list_init(&seat->drag_resource_list);
385 wl_signal_init(&seat->drag_icon_signal);
386}
387
388WL_EXPORT void
389wl_seat_release(struct wl_seat *seat)
390{
391 wl_signal_emit(&seat->destroy_signal, seat);
392
393 if (seat->pointer)
394 wl_pointer_release(seat->pointer);
395 if (seat->keyboard)
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400396 weston_keyboard_release(seat->keyboard);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400397 if (seat->touch)
398 wl_touch_release(seat->touch);
399}
400
401static void
402seat_send_updated_caps(struct wl_seat *seat)
403{
404 struct wl_resource *r;
405 enum wl_seat_capability caps = 0;
406
407 if (seat->pointer)
408 caps |= WL_SEAT_CAPABILITY_POINTER;
409 if (seat->keyboard)
410 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
411 if (seat->touch)
412 caps |= WL_SEAT_CAPABILITY_TOUCH;
413
414 wl_list_for_each(r, &seat->base_resource_list, link)
415 wl_seat_send_capabilities(r, caps);
416}
417
418WL_EXPORT void
419wl_seat_set_pointer(struct wl_seat *seat, struct wl_pointer *pointer)
420{
421 if (pointer && (seat->pointer || pointer->seat))
422 return; /* XXX: error? */
423 if (!pointer && !seat->pointer)
424 return;
425
426 seat->pointer = pointer;
427 if (pointer)
428 pointer->seat = seat;
429
430 seat_send_updated_caps(seat);
431}
432
433WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400434wl_seat_set_keyboard(struct wl_seat *seat, struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400435{
436 if (keyboard && (seat->keyboard || keyboard->seat))
437 return; /* XXX: error? */
438 if (!keyboard && !seat->keyboard)
439 return;
440
441 seat->keyboard = keyboard;
442 if (keyboard)
443 keyboard->seat = seat;
444
445 seat_send_updated_caps(seat);
446}
447
448WL_EXPORT void
449wl_seat_set_touch(struct wl_seat *seat, struct wl_touch *touch)
450{
451 if (touch && (seat->touch || touch->seat))
452 return; /* XXX: error? */
453 if (!touch && !seat->touch)
454 return;
455
456 seat->touch = touch;
457 if (touch)
458 touch->seat = seat;
459
460 seat_send_updated_caps(seat);
461}
462
463WL_EXPORT void
464wl_pointer_set_focus(struct wl_pointer *pointer, struct wl_surface *surface,
465 wl_fixed_t sx, wl_fixed_t sy)
466{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400467 struct weston_keyboard *kbd = pointer->seat->keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400468 struct wl_resource *resource, *kr;
469 struct wl_display *display;
470 uint32_t serial;
471
472 resource = pointer->focus_resource;
473 if (resource && pointer->focus != surface) {
474 display = wl_client_get_display(resource->client);
475 serial = wl_display_next_serial(display);
476 wl_pointer_send_leave(resource, serial,
477 &pointer->focus->resource);
478 wl_list_remove(&pointer->focus_listener.link);
479 }
480
481 resource = find_resource_for_surface(&pointer->resource_list,
482 surface);
483 if (resource &&
484 (pointer->focus != surface ||
485 pointer->focus_resource != resource)) {
486 display = wl_client_get_display(resource->client);
487 serial = wl_display_next_serial(display);
488 if (kbd) {
489 kr = find_resource_for_surface(&kbd->resource_list,
490 surface);
491 if (kr) {
492 wl_keyboard_send_modifiers(kr,
493 serial,
494 kbd->modifiers.mods_depressed,
495 kbd->modifiers.mods_latched,
496 kbd->modifiers.mods_locked,
497 kbd->modifiers.group);
498 }
499 }
500 wl_pointer_send_enter(resource, serial, &surface->resource,
501 sx, sy);
502 wl_signal_add(&resource->destroy_signal,
503 &pointer->focus_listener);
504 pointer->focus_serial = serial;
505 }
506
507 pointer->focus_resource = resource;
508 pointer->focus = surface;
509 pointer->default_grab.focus = surface;
510 wl_signal_emit(&pointer->focus_signal, pointer);
511}
512
513WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400514weston_keyboard_set_focus(struct weston_keyboard *keyboard,
515 struct wl_surface *surface)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400516{
517 struct wl_resource *resource;
518 struct wl_display *display;
519 uint32_t serial;
520
521 if (keyboard->focus_resource && keyboard->focus != surface) {
522 resource = keyboard->focus_resource;
523 display = wl_client_get_display(resource->client);
524 serial = wl_display_next_serial(display);
525 wl_keyboard_send_leave(resource, serial,
526 &keyboard->focus->resource);
527 wl_list_remove(&keyboard->focus_listener.link);
528 }
529
530 resource = find_resource_for_surface(&keyboard->resource_list,
531 surface);
532 if (resource &&
533 (keyboard->focus != surface ||
534 keyboard->focus_resource != resource)) {
535 display = wl_client_get_display(resource->client);
536 serial = wl_display_next_serial(display);
537 wl_keyboard_send_modifiers(resource, serial,
538 keyboard->modifiers.mods_depressed,
539 keyboard->modifiers.mods_latched,
540 keyboard->modifiers.mods_locked,
541 keyboard->modifiers.group);
542 wl_keyboard_send_enter(resource, serial, &surface->resource,
543 &keyboard->keys);
544 wl_signal_add(&resource->destroy_signal,
545 &keyboard->focus_listener);
546 keyboard->focus_serial = serial;
547 }
548
549 keyboard->focus_resource = resource;
550 keyboard->focus = surface;
551 wl_signal_emit(&keyboard->focus_signal, keyboard);
552}
553
554WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400555weston_keyboard_start_grab(struct weston_keyboard *keyboard,
556 struct weston_keyboard_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400557{
558 keyboard->grab = grab;
559 grab->keyboard = keyboard;
560
561 /* XXX focus? */
562}
563
564WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400565weston_keyboard_end_grab(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400566{
567 keyboard->grab = &keyboard->default_grab;
568}
569
570WL_EXPORT void
571wl_pointer_start_grab(struct wl_pointer *pointer, struct wl_pointer_grab *grab)
572{
573 const struct wl_pointer_grab_interface *interface;
574
575 pointer->grab = grab;
576 interface = pointer->grab->interface;
577 grab->pointer = pointer;
578
579 if (pointer->current)
580 interface->focus(pointer->grab, pointer->current,
581 pointer->current_x, pointer->current_y);
582}
583
584WL_EXPORT void
585wl_pointer_end_grab(struct wl_pointer *pointer)
586{
587 const struct wl_pointer_grab_interface *interface;
588
589 pointer->grab = &pointer->default_grab;
590 interface = pointer->grab->interface;
591 interface->focus(pointer->grab, pointer->current,
592 pointer->current_x, pointer->current_y);
593}
594
595static void
596current_surface_destroy(struct wl_listener *listener, void *data)
597{
598 struct wl_pointer *pointer =
599 container_of(listener, struct wl_pointer, current_listener);
600
601 pointer->current = NULL;
602}
603
604WL_EXPORT void
605wl_pointer_set_current(struct wl_pointer *pointer, struct wl_surface *surface)
606{
607 if (pointer->current)
608 wl_list_remove(&pointer->current_listener.link);
609
610 pointer->current = surface;
611
612 if (!surface)
613 return;
614
615 wl_signal_add(&surface->resource.destroy_signal,
616 &pointer->current_listener);
617 pointer->current_listener.notify = current_surface_destroy;
618}
619
620WL_EXPORT void
621wl_touch_start_grab(struct wl_touch *touch, struct wl_touch_grab *grab)
622{
623 touch->grab = grab;
624 grab->touch = touch;
625}
626
627WL_EXPORT void
628wl_touch_end_grab(struct wl_touch *touch)
629{
630 touch->grab = &touch->default_grab;
631}
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400632
633static void
634weston_seat_update_drag_surface(struct weston_seat *seat, int dx, int dy);
635
636static void
637clip_pointer_motion(struct weston_seat *seat, wl_fixed_t *fx, wl_fixed_t *fy)
638{
639 struct weston_compositor *ec = seat->compositor;
640 struct weston_output *output, *prev = NULL;
641 int x, y, old_x, old_y, valid = 0;
642
643 x = wl_fixed_to_int(*fx);
644 y = wl_fixed_to_int(*fy);
645 old_x = wl_fixed_to_int(seat->seat.pointer->x);
646 old_y = wl_fixed_to_int(seat->seat.pointer->y);
647
648 wl_list_for_each(output, &ec->output_list, link) {
649 if (pixman_region32_contains_point(&output->region,
650 x, y, NULL))
651 valid = 1;
652 if (pixman_region32_contains_point(&output->region,
653 old_x, old_y, NULL))
654 prev = output;
655 }
656
657 if (!valid) {
658 if (x < prev->x)
659 *fx = wl_fixed_from_int(prev->x);
660 else if (x >= prev->x + prev->width)
661 *fx = wl_fixed_from_int(prev->x +
662 prev->width - 1);
663 if (y < prev->y)
664 *fy = wl_fixed_from_int(prev->y);
665 else if (y >= prev->y + prev->current->height)
666 *fy = wl_fixed_from_int(prev->y +
667 prev->height - 1);
668 }
669}
670
671/* Takes absolute values */
672static void
673move_pointer(struct weston_seat *seat, wl_fixed_t x, wl_fixed_t y)
674{
675 struct weston_compositor *ec = seat->compositor;
676 struct wl_pointer *pointer = seat->seat.pointer;
677 struct weston_output *output;
678 int32_t ix, iy;
679
680 clip_pointer_motion(seat, &x, &y);
681
682 weston_seat_update_drag_surface(seat, x - pointer->x, y - pointer->y);
683
684 pointer->x = x;
685 pointer->y = y;
686
687 ix = wl_fixed_to_int(x);
688 iy = wl_fixed_to_int(y);
689
690 wl_list_for_each(output, &ec->output_list, link)
691 if (output->zoom.active &&
692 pixman_region32_contains_point(&output->region,
693 ix, iy, NULL))
694 weston_output_update_zoom(output, ZOOM_FOCUS_POINTER);
695
696 weston_device_repick(seat);
697
698 if (seat->sprite) {
699 weston_surface_set_position(seat->sprite,
700 ix - seat->hotspot_x,
701 iy - seat->hotspot_y);
702 weston_surface_schedule_repaint(seat->sprite);
703 }
704}
705
706WL_EXPORT void
707notify_motion(struct weston_seat *seat,
708 uint32_t time, wl_fixed_t dx, wl_fixed_t dy)
709{
710 const struct wl_pointer_grab_interface *interface;
711 struct weston_compositor *ec = seat->compositor;
712 struct wl_pointer *pointer = seat->seat.pointer;
713
714 weston_compositor_wake(ec);
715
716 move_pointer(seat, pointer->x + dx, pointer->y + dy);
717
718 interface = pointer->grab->interface;
719 interface->motion(pointer->grab, time,
720 pointer->grab->x, pointer->grab->y);
721}
722
723WL_EXPORT void
724notify_motion_absolute(struct weston_seat *seat,
725 uint32_t time, wl_fixed_t x, wl_fixed_t y)
726{
727 const struct wl_pointer_grab_interface *interface;
728 struct weston_compositor *ec = seat->compositor;
729 struct wl_pointer *pointer = seat->seat.pointer;
730
731 weston_compositor_wake(ec);
732
733 move_pointer(seat, x, y);
734
735 interface = pointer->grab->interface;
736 interface->motion(pointer->grab, time,
737 pointer->grab->x, pointer->grab->y);
738}
739
740WL_EXPORT void
741weston_surface_activate(struct weston_surface *surface,
742 struct weston_seat *seat)
743{
744 struct weston_compositor *compositor = seat->compositor;
745
746 if (seat->seat.keyboard) {
747 weston_keyboard_set_focus(seat->seat.keyboard, &surface->surface);
748 wl_data_device_set_keyboard_focus(&seat->seat);
749 }
750
751 wl_signal_emit(&compositor->activate_signal, surface);
752}
753
754WL_EXPORT void
755notify_button(struct weston_seat *seat, uint32_t time, int32_t button,
756 enum wl_pointer_button_state state)
757{
758 struct weston_compositor *compositor = seat->compositor;
759 struct wl_pointer *pointer = seat->seat.pointer;
760 struct weston_surface *focus =
761 (struct weston_surface *) pointer->focus;
762 uint32_t serial = wl_display_next_serial(compositor->wl_display);
763
764 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
765 if (compositor->ping_handler && focus)
766 compositor->ping_handler(focus, serial);
767 weston_compositor_idle_inhibit(compositor);
768 if (pointer->button_count == 0) {
769 pointer->grab_button = button;
770 pointer->grab_time = time;
771 pointer->grab_x = pointer->x;
772 pointer->grab_y = pointer->y;
773 }
774 pointer->button_count++;
775 } else {
776 weston_compositor_idle_release(compositor);
777 pointer->button_count--;
778 }
779
780 weston_compositor_run_button_binding(compositor, seat, time, button,
781 state);
782
783 pointer->grab->interface->button(pointer->grab, time, button, state);
784
785 if (pointer->button_count == 1)
786 pointer->grab_serial =
787 wl_display_get_serial(compositor->wl_display);
788}
789
790WL_EXPORT void
791notify_axis(struct weston_seat *seat, uint32_t time, uint32_t axis,
792 wl_fixed_t value)
793{
794 struct weston_compositor *compositor = seat->compositor;
795 struct wl_pointer *pointer = seat->seat.pointer;
796 struct weston_surface *focus =
797 (struct weston_surface *) pointer->focus;
798 uint32_t serial = wl_display_next_serial(compositor->wl_display);
799
800 if (compositor->ping_handler && focus)
801 compositor->ping_handler(focus, serial);
802
803 weston_compositor_wake(compositor);
804
805 if (!value)
806 return;
807
808 if (weston_compositor_run_axis_binding(compositor, seat,
809 time, axis, value))
810 return;
811
812 if (pointer->focus_resource)
813 wl_pointer_send_axis(pointer->focus_resource, time, axis,
814 value);
815}
816
817WL_EXPORT void
818notify_modifiers(struct weston_seat *seat, uint32_t serial)
819{
820 struct weston_keyboard *keyboard = &seat->keyboard;
821 struct weston_keyboard_grab *grab = keyboard->grab;
822 uint32_t mods_depressed, mods_latched, mods_locked, group;
823 uint32_t mods_lookup;
824 enum weston_led leds = 0;
825 int changed = 0;
826
827 /* Serialize and update our internal state, checking to see if it's
828 * different to the previous state. */
829 mods_depressed = xkb_state_serialize_mods(seat->xkb_state.state,
830 XKB_STATE_DEPRESSED);
831 mods_latched = xkb_state_serialize_mods(seat->xkb_state.state,
832 XKB_STATE_LATCHED);
833 mods_locked = xkb_state_serialize_mods(seat->xkb_state.state,
834 XKB_STATE_LOCKED);
835 group = xkb_state_serialize_group(seat->xkb_state.state,
836 XKB_STATE_EFFECTIVE);
837
838 if (mods_depressed != seat->seat.keyboard->modifiers.mods_depressed ||
839 mods_latched != seat->seat.keyboard->modifiers.mods_latched ||
840 mods_locked != seat->seat.keyboard->modifiers.mods_locked ||
841 group != seat->seat.keyboard->modifiers.group)
842 changed = 1;
843
844 seat->seat.keyboard->modifiers.mods_depressed = mods_depressed;
845 seat->seat.keyboard->modifiers.mods_latched = mods_latched;
846 seat->seat.keyboard->modifiers.mods_locked = mods_locked;
847 seat->seat.keyboard->modifiers.group = group;
848
849 /* And update the modifier_state for bindings. */
850 mods_lookup = mods_depressed | mods_latched;
851 seat->modifier_state = 0;
852 if (mods_lookup & (1 << seat->xkb_info.ctrl_mod))
853 seat->modifier_state |= MODIFIER_CTRL;
854 if (mods_lookup & (1 << seat->xkb_info.alt_mod))
855 seat->modifier_state |= MODIFIER_ALT;
856 if (mods_lookup & (1 << seat->xkb_info.super_mod))
857 seat->modifier_state |= MODIFIER_SUPER;
858 if (mods_lookup & (1 << seat->xkb_info.shift_mod))
859 seat->modifier_state |= MODIFIER_SHIFT;
860
861 /* Finally, notify the compositor that LEDs have changed. */
862 if (xkb_state_led_index_is_active(seat->xkb_state.state,
863 seat->xkb_info.num_led))
864 leds |= LED_NUM_LOCK;
865 if (xkb_state_led_index_is_active(seat->xkb_state.state,
866 seat->xkb_info.caps_led))
867 leds |= LED_CAPS_LOCK;
868 if (xkb_state_led_index_is_active(seat->xkb_state.state,
869 seat->xkb_info.scroll_led))
870 leds |= LED_SCROLL_LOCK;
871 if (leds != seat->xkb_state.leds && seat->led_update)
872 seat->led_update(seat, leds);
873 seat->xkb_state.leds = leds;
874
875 if (changed) {
876 grab->interface->modifiers(grab,
877 serial,
878 keyboard->modifiers.mods_depressed,
879 keyboard->modifiers.mods_latched,
880 keyboard->modifiers.mods_locked,
881 keyboard->modifiers.group);
882 }
883}
884
885static void
886update_modifier_state(struct weston_seat *seat, uint32_t serial, uint32_t key,
887 enum wl_keyboard_key_state state)
888{
889 enum xkb_key_direction direction;
890
891 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
892 direction = XKB_KEY_DOWN;
893 else
894 direction = XKB_KEY_UP;
895
896 /* Offset the keycode by 8, as the evdev XKB rules reflect X's
897 * broken keycode system, which starts at 8. */
898 xkb_state_update_key(seat->xkb_state.state, key + 8, direction);
899
900 notify_modifiers(seat, serial);
901}
902
903WL_EXPORT void
904notify_key(struct weston_seat *seat, uint32_t time, uint32_t key,
905 enum wl_keyboard_key_state state,
906 enum weston_key_state_update update_state)
907{
908 struct weston_compositor *compositor = seat->compositor;
909 struct weston_keyboard *keyboard = &seat->keyboard;
910 struct weston_surface *focus =
911 (struct weston_surface *) keyboard->focus;
912 struct weston_keyboard_grab *grab = keyboard->grab;
913 uint32_t serial = wl_display_next_serial(compositor->wl_display);
914 uint32_t *k, *end;
915
916 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
917 if (compositor->ping_handler && focus)
918 compositor->ping_handler(focus, serial);
919
920 weston_compositor_idle_inhibit(compositor);
921 keyboard->grab_key = key;
922 keyboard->grab_time = time;
923 } else {
924 weston_compositor_idle_release(compositor);
925 }
926
927 end = keyboard->keys.data + keyboard->keys.size;
928 for (k = keyboard->keys.data; k < end; k++) {
929 if (*k == key) {
930 /* Ignore server-generated repeats. */
931 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
932 return;
933 *k = *--end;
934 }
935 }
936 keyboard->keys.size = (void *) end - keyboard->keys.data;
937 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
938 k = wl_array_add(&keyboard->keys, sizeof *k);
939 *k = key;
940 }
941
942 if (grab == &keyboard->default_grab ||
943 grab == &keyboard->input_method_grab) {
944 weston_compositor_run_key_binding(compositor, seat, time, key,
945 state);
946 grab = keyboard->grab;
947 }
948
949 grab->interface->key(grab, time, key, state);
950
951 if (update_state == STATE_UPDATE_AUTOMATIC) {
952 update_modifier_state(seat,
953 wl_display_get_serial(compositor->wl_display),
954 key,
955 state);
956 }
957}
958
959WL_EXPORT void
960notify_pointer_focus(struct weston_seat *seat, struct weston_output *output,
961 wl_fixed_t x, wl_fixed_t y)
962{
963 struct weston_compositor *compositor = seat->compositor;
964
965 if (output) {
966 move_pointer(seat, x, y);
967 compositor->focus = 1;
968 } else {
969 compositor->focus = 0;
970 /* FIXME: We should call wl_pointer_set_focus(seat,
971 * NULL) here, but somehow that breaks re-entry... */
972 }
973}
974
975static void
976destroy_device_saved_kbd_focus(struct wl_listener *listener, void *data)
977{
978 struct weston_seat *ws;
979
980 ws = container_of(listener, struct weston_seat,
981 saved_kbd_focus_listener);
982
983 ws->saved_kbd_focus = NULL;
984}
985
986WL_EXPORT void
987notify_keyboard_focus_in(struct weston_seat *seat, struct wl_array *keys,
988 enum weston_key_state_update update_state)
989{
990 struct weston_compositor *compositor = seat->compositor;
991 struct weston_keyboard *keyboard = seat->seat.keyboard;
992 struct wl_surface *surface;
993 uint32_t *k, serial;
994
995 serial = wl_display_next_serial(compositor->wl_display);
996 wl_array_copy(&keyboard->keys, keys);
997 wl_array_for_each(k, &keyboard->keys) {
998 weston_compositor_idle_inhibit(compositor);
999 if (update_state == STATE_UPDATE_AUTOMATIC)
1000 update_modifier_state(seat, serial, *k,
1001 WL_KEYBOARD_KEY_STATE_PRESSED);
1002 }
1003
1004 /* Run key bindings after we've updated the state. */
1005 wl_array_for_each(k, &keyboard->keys) {
1006 weston_compositor_run_key_binding(compositor, seat, 0, *k,
1007 WL_KEYBOARD_KEY_STATE_PRESSED);
1008 }
1009
1010 surface = seat->saved_kbd_focus;
1011
1012 if (surface) {
1013 wl_list_remove(&seat->saved_kbd_focus_listener.link);
1014 weston_keyboard_set_focus(keyboard, surface);
1015 seat->saved_kbd_focus = NULL;
1016 }
1017}
1018
1019WL_EXPORT void
1020notify_keyboard_focus_out(struct weston_seat *seat)
1021{
1022 struct weston_compositor *compositor = seat->compositor;
1023 struct weston_keyboard *keyboard = seat->seat.keyboard;
1024 uint32_t *k, serial;
1025
1026 serial = wl_display_next_serial(compositor->wl_display);
1027 wl_array_for_each(k, &keyboard->keys) {
1028 weston_compositor_idle_release(compositor);
1029 update_modifier_state(seat, serial, *k,
1030 WL_KEYBOARD_KEY_STATE_RELEASED);
1031 }
1032
1033 seat->modifier_state = 0;
1034
1035 if (keyboard->focus) {
1036 seat->saved_kbd_focus = keyboard->focus;
1037 seat->saved_kbd_focus_listener.notify =
1038 destroy_device_saved_kbd_focus;
1039 wl_signal_add(&keyboard->focus->resource.destroy_signal,
1040 &seat->saved_kbd_focus_listener);
1041 }
1042
1043 weston_keyboard_set_focus(keyboard, NULL);
1044 /* FIXME: We really need keyboard grab cancel here to
1045 * let the grab shut down properly. As it is we leak
1046 * the grab data. */
1047 weston_keyboard_end_grab(keyboard);
1048}
1049
1050static void
1051touch_set_focus(struct weston_seat *ws, struct wl_surface *surface)
1052{
1053 struct wl_seat *seat = &ws->seat;
1054 struct wl_resource *resource;
1055
1056 if (seat->touch->focus == surface)
1057 return;
1058
1059 if (seat->touch->focus_resource)
1060 wl_list_remove(&seat->touch->focus_listener.link);
1061 seat->touch->focus = NULL;
1062 seat->touch->focus_resource = NULL;
1063
1064 if (surface) {
1065 resource =
1066 find_resource_for_client(&seat->touch->resource_list,
1067 surface->resource.client);
1068 if (!resource) {
1069 weston_log("couldn't find resource\n");
1070 return;
1071 }
1072
1073 seat->touch->focus = surface;
1074 seat->touch->focus_resource = resource;
1075 wl_signal_add(&resource->destroy_signal,
1076 &seat->touch->focus_listener);
1077 }
1078}
1079
1080/**
1081 * notify_touch - emulates button touches and notifies surfaces accordingly.
1082 *
1083 * It assumes always the correct cycle sequence until it gets here: touch_down
1084 * → touch_update → ... → touch_update → touch_end. The driver is responsible
1085 * for sending along such order.
1086 *
1087 */
1088WL_EXPORT void
1089notify_touch(struct weston_seat *seat, uint32_t time, int touch_id,
1090 wl_fixed_t x, wl_fixed_t y, int touch_type)
1091{
1092 struct weston_compositor *ec = seat->compositor;
1093 struct wl_touch *touch = seat->seat.touch;
1094 struct wl_touch_grab *grab = touch->grab;
1095 struct weston_surface *es;
1096 wl_fixed_t sx, sy;
1097
1098 /* Update grab's global coordinates. */
1099 touch->grab_x = x;
1100 touch->grab_y = y;
1101
1102 switch (touch_type) {
1103 case WL_TOUCH_DOWN:
1104 weston_compositor_idle_inhibit(ec);
1105
1106 seat->num_tp++;
1107
1108 /* the first finger down picks the surface, and all further go
1109 * to that surface for the remainder of the touch session i.e.
1110 * until all touch points are up again. */
1111 if (seat->num_tp == 1) {
1112 es = weston_compositor_pick_surface(ec, x, y, &sx, &sy);
1113 touch_set_focus(seat, &es->surface);
1114 } else if (touch->focus) {
1115 es = (struct weston_surface *) touch->focus;
1116 weston_surface_from_global_fixed(es, x, y, &sx, &sy);
1117 } else {
1118 /* Unexpected condition: We have non-initial touch but
1119 * there is no focused surface.
1120 */
1121 weston_log("touch event received with %d points down"
1122 "but no surface focused\n", seat->num_tp);
1123 return;
1124 }
1125
1126 grab->interface->down(grab, time, touch_id, sx, sy);
1127 break;
1128 case WL_TOUCH_MOTION:
1129 es = (struct weston_surface *) touch->focus;
1130 if (!es)
1131 break;
1132
1133 weston_surface_from_global_fixed(es, x, y, &sx, &sy);
1134 grab->interface->motion(grab, time, touch_id, sx, sy);
1135 break;
1136 case WL_TOUCH_UP:
1137 weston_compositor_idle_release(ec);
1138 seat->num_tp--;
1139
1140 grab->interface->up(grab, time, touch_id);
1141 if (seat->num_tp == 0)
1142 touch_set_focus(seat, NULL);
1143 break;
1144 }
1145}
1146
1147static void
1148pointer_handle_sprite_destroy(struct wl_listener *listener, void *data)
1149{
1150 struct weston_seat *seat = container_of(listener, struct weston_seat,
1151 sprite_destroy_listener);
1152
1153 seat->sprite = NULL;
1154}
1155
1156static void
1157pointer_cursor_surface_configure(struct weston_surface *es,
1158 int32_t dx, int32_t dy, int32_t width, int32_t height)
1159{
1160 struct weston_seat *seat = es->configure_private;
1161 int x, y;
1162
1163 if (width == 0)
1164 return;
1165
1166 assert(es == seat->sprite);
1167
1168 seat->hotspot_x -= dx;
1169 seat->hotspot_y -= dy;
1170
1171 x = wl_fixed_to_int(seat->seat.pointer->x) - seat->hotspot_x;
1172 y = wl_fixed_to_int(seat->seat.pointer->y) - seat->hotspot_y;
1173
1174 weston_surface_configure(seat->sprite, x, y,
1175 width, height);
1176
1177 empty_region(&es->pending.input);
1178
1179 if (!weston_surface_is_mapped(es)) {
1180 wl_list_insert(&es->compositor->cursor_layer.surface_list,
1181 &es->layer_link);
1182 weston_surface_update_transform(es);
1183 }
1184}
1185
1186static void
1187pointer_unmap_sprite(struct weston_seat *seat)
1188{
1189 if (weston_surface_is_mapped(seat->sprite))
1190 weston_surface_unmap(seat->sprite);
1191
1192 wl_list_remove(&seat->sprite_destroy_listener.link);
1193 seat->sprite->configure = NULL;
1194 seat->sprite->configure_private = NULL;
1195 seat->sprite = NULL;
1196}
1197
1198static void
1199pointer_set_cursor(struct wl_client *client, struct wl_resource *resource,
1200 uint32_t serial, struct wl_resource *surface_resource,
1201 int32_t x, int32_t y)
1202{
1203 struct weston_seat *seat = resource->data;
1204 struct weston_surface *surface = NULL;
1205
1206 if (surface_resource)
1207 surface = surface_resource->data;
1208
1209 if (seat->seat.pointer->focus == NULL)
1210 return;
1211 if (seat->seat.pointer->focus->resource.client != client)
1212 return;
1213 if (seat->seat.pointer->focus_serial - serial > UINT32_MAX / 2)
1214 return;
1215
1216 if (surface && surface != seat->sprite) {
1217 if (surface->configure) {
1218 wl_resource_post_error(&surface->surface.resource,
1219 WL_DISPLAY_ERROR_INVALID_OBJECT,
1220 "surface->configure already "
1221 "set");
1222 return;
1223 }
1224 }
1225
1226 if (seat->sprite)
1227 pointer_unmap_sprite(seat);
1228
1229 if (!surface)
1230 return;
1231
1232 wl_signal_add(&surface->surface.resource.destroy_signal,
1233 &seat->sprite_destroy_listener);
1234
1235 surface->configure = pointer_cursor_surface_configure;
1236 surface->configure_private = seat;
1237 seat->sprite = surface;
1238 seat->hotspot_x = x;
1239 seat->hotspot_y = y;
1240
1241 if (surface->buffer_ref.buffer)
1242 pointer_cursor_surface_configure(surface, 0, 0, weston_surface_buffer_width(surface),
1243 weston_surface_buffer_height(surface));
1244}
1245
1246static const struct wl_pointer_interface pointer_interface = {
1247 pointer_set_cursor
1248};
1249
1250static void
1251handle_drag_surface_destroy(struct wl_listener *listener, void *data)
1252{
1253 struct weston_seat *seat;
1254
1255 seat = container_of(listener, struct weston_seat,
1256 drag_surface_destroy_listener);
1257
1258 seat->drag_surface = NULL;
1259}
1260
1261static void
1262seat_get_pointer(struct wl_client *client, struct wl_resource *resource,
1263 uint32_t id)
1264{
1265 struct weston_seat *seat = resource->data;
1266 struct wl_resource *cr;
1267
1268 if (!seat->seat.pointer)
1269 return;
1270
1271 cr = wl_client_add_object(client, &wl_pointer_interface,
1272 &pointer_interface, id, seat);
1273 wl_list_insert(&seat->seat.pointer->resource_list, &cr->link);
1274 cr->destroy = unbind_resource;
1275
1276 if (seat->seat.pointer->focus &&
1277 seat->seat.pointer->focus->resource.client == client) {
1278 struct weston_surface *surface;
1279 wl_fixed_t sx, sy;
1280
1281 surface = (struct weston_surface *) seat->seat.pointer->focus;
1282 weston_surface_from_global_fixed(surface,
1283 seat->seat.pointer->x,
1284 seat->seat.pointer->y,
1285 &sx,
1286 &sy);
1287 wl_pointer_set_focus(seat->seat.pointer,
1288 seat->seat.pointer->focus,
1289 sx,
1290 sy);
1291 }
1292}
1293
1294static void
1295seat_get_keyboard(struct wl_client *client, struct wl_resource *resource,
1296 uint32_t id)
1297{
1298 struct weston_seat *seat = resource->data;
1299 struct wl_resource *cr;
1300
1301 if (!seat->seat.keyboard)
1302 return;
1303
1304 cr = wl_client_add_object(client, &wl_keyboard_interface, NULL, id,
1305 seat);
1306 wl_list_insert(&seat->seat.keyboard->resource_list, &cr->link);
1307 cr->destroy = unbind_resource;
1308
1309 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
1310 seat->xkb_info.keymap_fd,
1311 seat->xkb_info.keymap_size);
1312
1313 if (seat->seat.keyboard->focus &&
1314 seat->seat.keyboard->focus->resource.client == client) {
1315 weston_keyboard_set_focus(seat->seat.keyboard,
1316 seat->seat.keyboard->focus);
1317 wl_data_device_set_keyboard_focus(&seat->seat);
1318 }
1319}
1320
1321static void
1322seat_get_touch(struct wl_client *client, struct wl_resource *resource,
1323 uint32_t id)
1324{
1325 struct weston_seat *seat = resource->data;
1326 struct wl_resource *cr;
1327
1328 if (!seat->seat.touch)
1329 return;
1330
1331 cr = wl_client_add_object(client, &wl_touch_interface, NULL, id, seat);
1332 wl_list_insert(&seat->seat.touch->resource_list, &cr->link);
1333 cr->destroy = unbind_resource;
1334}
1335
1336static const struct wl_seat_interface seat_interface = {
1337 seat_get_pointer,
1338 seat_get_keyboard,
1339 seat_get_touch,
1340};
1341
1342static void
1343bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
1344{
1345 struct wl_seat *seat = data;
1346 struct wl_resource *resource;
1347 enum wl_seat_capability caps = 0;
1348
1349 resource = wl_client_add_object(client, &wl_seat_interface,
1350 &seat_interface, id, data);
1351 wl_list_insert(&seat->base_resource_list, &resource->link);
1352 resource->destroy = unbind_resource;
1353
1354 if (seat->pointer)
1355 caps |= WL_SEAT_CAPABILITY_POINTER;
1356 if (seat->keyboard)
1357 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
1358 if (seat->touch)
1359 caps |= WL_SEAT_CAPABILITY_TOUCH;
1360
1361 wl_seat_send_capabilities(resource, caps);
1362}
1363
1364static void
1365device_handle_new_drag_icon(struct wl_listener *listener, void *data)
1366{
1367 struct weston_seat *seat;
1368
1369 seat = container_of(listener, struct weston_seat,
1370 new_drag_icon_listener);
1371
1372 weston_seat_update_drag_surface(seat, 0, 0);
1373}
1374
1375int
1376weston_compositor_xkb_init(struct weston_compositor *ec,
1377 struct xkb_rule_names *names)
1378{
1379 if (ec->xkb_context == NULL) {
1380 ec->xkb_context = xkb_context_new(0);
1381 if (ec->xkb_context == NULL) {
1382 weston_log("failed to create XKB context\n");
1383 return -1;
1384 }
1385 }
1386
1387 if (names)
1388 ec->xkb_names = *names;
1389 if (!ec->xkb_names.rules)
1390 ec->xkb_names.rules = strdup("evdev");
1391 if (!ec->xkb_names.model)
1392 ec->xkb_names.model = strdup("pc105");
1393 if (!ec->xkb_names.layout)
1394 ec->xkb_names.layout = strdup("us");
1395
1396 return 0;
1397}
1398
1399static void xkb_info_destroy(struct weston_xkb_info *xkb_info)
1400{
1401 if (xkb_info->keymap)
1402 xkb_map_unref(xkb_info->keymap);
1403
1404 if (xkb_info->keymap_area)
1405 munmap(xkb_info->keymap_area, xkb_info->keymap_size);
1406 if (xkb_info->keymap_fd >= 0)
1407 close(xkb_info->keymap_fd);
1408}
1409
1410void
1411weston_compositor_xkb_destroy(struct weston_compositor *ec)
1412{
1413 free((char *) ec->xkb_names.rules);
1414 free((char *) ec->xkb_names.model);
1415 free((char *) ec->xkb_names.layout);
1416 free((char *) ec->xkb_names.variant);
1417 free((char *) ec->xkb_names.options);
1418
1419 xkb_info_destroy(&ec->xkb_info);
1420 xkb_context_unref(ec->xkb_context);
1421}
1422
1423static int
1424weston_xkb_info_new_keymap(struct weston_xkb_info *xkb_info)
1425{
1426 char *keymap_str;
1427
1428 xkb_info->shift_mod = xkb_map_mod_get_index(xkb_info->keymap,
1429 XKB_MOD_NAME_SHIFT);
1430 xkb_info->caps_mod = xkb_map_mod_get_index(xkb_info->keymap,
1431 XKB_MOD_NAME_CAPS);
1432 xkb_info->ctrl_mod = xkb_map_mod_get_index(xkb_info->keymap,
1433 XKB_MOD_NAME_CTRL);
1434 xkb_info->alt_mod = xkb_map_mod_get_index(xkb_info->keymap,
1435 XKB_MOD_NAME_ALT);
1436 xkb_info->mod2_mod = xkb_map_mod_get_index(xkb_info->keymap, "Mod2");
1437 xkb_info->mod3_mod = xkb_map_mod_get_index(xkb_info->keymap, "Mod3");
1438 xkb_info->super_mod = xkb_map_mod_get_index(xkb_info->keymap,
1439 XKB_MOD_NAME_LOGO);
1440 xkb_info->mod5_mod = xkb_map_mod_get_index(xkb_info->keymap, "Mod5");
1441
1442 xkb_info->num_led = xkb_map_led_get_index(xkb_info->keymap,
1443 XKB_LED_NAME_NUM);
1444 xkb_info->caps_led = xkb_map_led_get_index(xkb_info->keymap,
1445 XKB_LED_NAME_CAPS);
1446 xkb_info->scroll_led = xkb_map_led_get_index(xkb_info->keymap,
1447 XKB_LED_NAME_SCROLL);
1448
1449 keymap_str = xkb_map_get_as_string(xkb_info->keymap);
1450 if (keymap_str == NULL) {
1451 weston_log("failed to get string version of keymap\n");
1452 return -1;
1453 }
1454 xkb_info->keymap_size = strlen(keymap_str) + 1;
1455
1456 xkb_info->keymap_fd = os_create_anonymous_file(xkb_info->keymap_size);
1457 if (xkb_info->keymap_fd < 0) {
1458 weston_log("creating a keymap file for %lu bytes failed: %m\n",
1459 (unsigned long) xkb_info->keymap_size);
1460 goto err_keymap_str;
1461 }
1462
1463 xkb_info->keymap_area = mmap(NULL, xkb_info->keymap_size,
1464 PROT_READ | PROT_WRITE,
1465 MAP_SHARED, xkb_info->keymap_fd, 0);
1466 if (xkb_info->keymap_area == MAP_FAILED) {
1467 weston_log("failed to mmap() %lu bytes\n",
1468 (unsigned long) xkb_info->keymap_size);
1469 goto err_dev_zero;
1470 }
1471 strcpy(xkb_info->keymap_area, keymap_str);
1472 free(keymap_str);
1473
1474 return 0;
1475
1476err_dev_zero:
1477 close(xkb_info->keymap_fd);
1478 xkb_info->keymap_fd = -1;
1479err_keymap_str:
1480 free(keymap_str);
1481 return -1;
1482}
1483
1484static int
1485weston_compositor_build_global_keymap(struct weston_compositor *ec)
1486{
1487 if (ec->xkb_info.keymap != NULL)
1488 return 0;
1489
1490 ec->xkb_info.keymap = xkb_map_new_from_names(ec->xkb_context,
1491 &ec->xkb_names,
1492 0);
1493 if (ec->xkb_info.keymap == NULL) {
1494 weston_log("failed to compile global XKB keymap\n");
1495 weston_log(" tried rules %s, model %s, layout %s, variant %s, "
1496 "options %s\n",
1497 ec->xkb_names.rules, ec->xkb_names.model,
1498 ec->xkb_names.layout, ec->xkb_names.variant,
1499 ec->xkb_names.options);
1500 return -1;
1501 }
1502
1503 if (weston_xkb_info_new_keymap(&ec->xkb_info) < 0)
1504 return -1;
1505
1506 return 0;
1507}
1508
1509WL_EXPORT int
1510weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap)
1511{
1512 if (seat->has_keyboard)
1513 return 0;
1514
1515 if (keymap != NULL) {
1516 seat->xkb_info.keymap = xkb_map_ref(keymap);
1517 if (weston_xkb_info_new_keymap(&seat->xkb_info) < 0)
1518 return -1;
1519 } else {
1520 if (weston_compositor_build_global_keymap(seat->compositor) < 0)
1521 return -1;
1522 seat->xkb_info = seat->compositor->xkb_info;
1523 seat->xkb_info.keymap = xkb_map_ref(seat->xkb_info.keymap);
1524 }
1525
1526 seat->xkb_state.state = xkb_state_new(seat->xkb_info.keymap);
1527 if (seat->xkb_state.state == NULL) {
1528 weston_log("failed to initialise XKB state\n");
1529 return -1;
1530 }
1531
1532 seat->xkb_state.leds = 0;
1533
1534 weston_keyboard_init(&seat->keyboard);
1535 wl_seat_set_keyboard(&seat->seat, &seat->keyboard);
1536
1537 seat->has_keyboard = 1;
1538
1539 return 0;
1540}
1541
1542WL_EXPORT void
1543weston_seat_init_pointer(struct weston_seat *seat)
1544{
1545 if (seat->has_pointer)
1546 return;
1547
1548 wl_pointer_init(&seat->pointer);
1549 wl_seat_set_pointer(&seat->seat, &seat->pointer);
1550
1551 seat->has_pointer = 1;
1552}
1553
1554WL_EXPORT void
1555weston_seat_init_touch(struct weston_seat *seat)
1556{
1557 if (seat->has_touch)
1558 return;
1559
1560 wl_touch_init(&seat->touch);
1561 wl_seat_set_touch(&seat->seat, &seat->touch);
1562
1563 seat->has_touch = 1;
1564}
1565
1566WL_EXPORT void
1567weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec)
1568{
1569 wl_seat_init(&seat->seat);
1570 seat->has_pointer = 0;
1571 seat->has_keyboard = 0;
1572 seat->has_touch = 0;
1573
1574 wl_display_add_global(ec->wl_display, &wl_seat_interface, seat,
1575 bind_seat);
1576
1577 seat->sprite = NULL;
1578 seat->sprite_destroy_listener.notify = pointer_handle_sprite_destroy;
1579
1580 seat->compositor = ec;
1581 seat->hotspot_x = 16;
1582 seat->hotspot_y = 16;
1583 seat->modifier_state = 0;
1584 seat->num_tp = 0;
1585
1586 seat->drag_surface_destroy_listener.notify =
1587 handle_drag_surface_destroy;
1588
1589 wl_list_insert(ec->seat_list.prev, &seat->link);
1590
1591 seat->new_drag_icon_listener.notify = device_handle_new_drag_icon;
1592 wl_signal_add(&seat->seat.drag_icon_signal,
1593 &seat->new_drag_icon_listener);
1594
1595 clipboard_create(seat);
1596
1597 wl_signal_init(&seat->destroy_signal);
1598 wl_signal_emit(&ec->seat_created_signal, seat);
1599}
1600
1601WL_EXPORT void
1602weston_seat_release(struct weston_seat *seat)
1603{
1604 wl_list_remove(&seat->link);
1605 /* The global object is destroyed at wl_display_destroy() time. */
1606
1607 if (seat->sprite)
1608 pointer_unmap_sprite(seat);
1609
1610 if (seat->xkb_state.state != NULL)
1611 xkb_state_unref(seat->xkb_state.state);
1612 xkb_info_destroy(&seat->xkb_info);
1613
1614 wl_seat_release(&seat->seat);
1615 wl_signal_emit(&seat->destroy_signal, seat);
1616}
1617
1618static void
1619drag_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height)
1620{
1621 empty_region(&es->pending.input);
1622
1623 weston_surface_configure(es,
1624 es->geometry.x + sx, es->geometry.y + sy,
1625 width, height);
1626}
1627
1628static int
1629device_setup_new_drag_surface(struct weston_seat *ws,
1630 struct weston_surface *surface)
1631{
1632 struct wl_seat *seat = &ws->seat;
1633
1634 if (surface->configure) {
1635 wl_resource_post_error(&surface->surface.resource,
1636 WL_DISPLAY_ERROR_INVALID_OBJECT,
1637 "surface->configure already set");
1638 return 0;
1639 }
1640
1641 ws->drag_surface = surface;
1642
1643 weston_surface_set_position(ws->drag_surface,
1644 wl_fixed_to_double(seat->pointer->x),
1645 wl_fixed_to_double(seat->pointer->y));
1646
1647 surface->configure = drag_surface_configure;
1648
1649 wl_signal_add(&surface->surface.resource.destroy_signal,
1650 &ws->drag_surface_destroy_listener);
1651
1652 return 1;
1653}
1654
1655static void
1656device_release_drag_surface(struct weston_seat *seat)
1657{
1658 if (weston_surface_is_mapped(seat->drag_surface))
1659 weston_surface_unmap(seat->drag_surface);
1660
1661 seat->drag_surface->configure = NULL;
1662 empty_region(&seat->drag_surface->pending.input);
1663 wl_list_remove(&seat->drag_surface_destroy_listener.link);
1664 seat->drag_surface = NULL;
1665}
1666
1667static void
1668device_map_drag_surface(struct weston_seat *seat)
1669{
1670 struct wl_list *list;
1671
1672 if (weston_surface_is_mapped(seat->drag_surface) ||
1673 !seat->drag_surface->buffer_ref.buffer)
1674 return;
1675
1676 if (seat->sprite && weston_surface_is_mapped(seat->sprite))
1677 list = &seat->sprite->layer_link;
1678 else
1679 list = &seat->compositor->cursor_layer.surface_list;
1680
1681 wl_list_insert(list, &seat->drag_surface->layer_link);
1682 weston_surface_update_transform(seat->drag_surface);
1683 empty_region(&seat->drag_surface->input);
1684}
1685
1686static void
1687weston_seat_update_drag_surface(struct weston_seat *seat,
1688 int dx, int dy)
1689{
1690 int surface_changed = 0;
1691
1692 if (!seat->drag_surface && !seat->seat.drag_surface)
1693 return;
1694
1695 if (seat->drag_surface && seat->seat.drag_surface &&
1696 (&seat->drag_surface->surface.resource !=
1697 &seat->seat.drag_surface->resource))
1698 /* between calls to this funcion we got a new drag_surface */
1699 surface_changed = 1;
1700
1701 if (!seat->seat.drag_surface || surface_changed) {
1702 device_release_drag_surface(seat);
1703 if (!surface_changed)
1704 return;
1705 }
1706
1707 if (!seat->drag_surface || surface_changed) {
1708 struct weston_surface *surface = (struct weston_surface *)
1709 seat->seat.drag_surface;
1710 if (!device_setup_new_drag_surface(seat, surface))
1711 return;
1712 }
1713
1714 /* the client may not have attached a buffer to the drag surface
1715 * when we setup it up, so check if map is needed on every update */
1716 device_map_drag_surface(seat);
1717
1718 if (!dx && !dy)
1719 return;
1720
1721 weston_surface_set_position(seat->drag_surface,
1722 seat->drag_surface->geometry.x + wl_fixed_to_double(dx),
1723 seat->drag_surface->geometry.y + wl_fixed_to_double(dy));
1724}
1725
1726WL_EXPORT void
1727weston_compositor_update_drag_surfaces(struct weston_compositor *compositor)
1728{
1729 struct weston_seat *seat;
1730
1731 wl_list_for_each(seat, &compositor->seat_list, link)
1732 weston_seat_update_drag_surface(seat, 0, 0);
1733}