7 #include <wayland-client.h>
8 #include <xkbcommon/xkbcommon.h>
10 #include "libds/log.h"
11 #include "libds/pointer.h"
12 #include "libds/touch.h"
21 #define MIN(a, b) ((a) < (b) ? (a) : (b))
23 static const struct wl_seat_listener seat_listener;
24 static const struct wl_callback_listener seat_callback_listener;
26 static void seat_update_capabilities(struct ds_wl_seat *seat,
27 enum wl_seat_capability caps);
28 static struct ds_input_device *
29 create_wl_input_device(struct ds_wl_seat *seat,
30 enum ds_input_device_type type);
31 static struct ds_pointer *create_wl_pointer(struct ds_wl_seat *seat);
32 static struct ds_keyboard *create_wl_keyboard(struct ds_wl_seat *seat);
33 static struct ds_touch *create_wl_touch(struct ds_wl_seat *seat);
36 create_wl_seat(struct ds_wl_backend *backend, uint32_t id,
37 uint32_t available_version)
39 struct ds_wl_seat *seat;
41 seat = calloc(1, sizeof *seat);
45 seat->backend = backend;
46 seat->version = MIN(available_version, 5);
47 seat->wl_seat = wl_registry_bind(backend->server.registry, id,
48 &wl_seat_interface, seat->version);
50 wl_seat_add_listener(seat->wl_seat, &seat_listener, seat);
52 seat->initial_info_cb = wl_display_sync(backend->server.display);
53 wl_callback_add_listener(seat->initial_info_cb, &seat_callback_listener,
56 ds_dbg("wl_backend: Seat(%p) created", seat);
62 destroy_wl_seat(struct ds_wl_seat *seat)
64 ds_dbg("wl_backend: Seat(%p) destroy", seat);
66 if (seat->pointer_dev)
67 ds_input_device_destroy(seat->pointer_dev);
69 if (seat->keyboard_dev)
70 ds_input_device_destroy(seat->keyboard_dev);
73 ds_input_device_destroy(seat->touch_dev);
75 if (seat->version >= WL_SEAT_RELEASE_SINCE_VERSION)
76 wl_seat_release(seat->wl_seat);
78 wl_seat_destroy(seat->wl_seat);
80 wl_list_remove(&seat->link);
87 seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
88 enum wl_seat_capability caps)
90 struct ds_wl_seat *seat = data;
92 if (seat->initialized)
93 seat_update_capabilities(seat, caps);
97 ds_dbg("wl_backend: Seat(%p) capabilities(%d)", seat, caps);
101 seat_handle_name(void *data, struct wl_seat *wl_seat, const char *name)
103 struct ds_wl_seat *seat = data;
108 ds_dbg("wl_backend: Seat(%p) name(%s)", seat, name);
110 seat->name = strdup(name);
113 static const struct wl_seat_listener seat_listener = {
114 .capabilities = seat_handle_capabilities,
115 .name = seat_handle_name,
119 seat_add_callback_handle_done(void *data, struct wl_callback *callback,
120 uint32_t callback_data)
122 struct ds_wl_seat *seat = data;
124 wl_callback_destroy(seat->initial_info_cb);
125 seat->initial_info_cb = NULL;
126 seat->initialized = true;
128 seat_update_capabilities(seat, seat->caps);
131 static const struct wl_callback_listener seat_callback_listener = {
132 .done = seat_add_callback_handle_done,
136 seat_update_capabilities(struct ds_wl_seat *seat, enum wl_seat_capability caps)
138 if ((caps & WL_SEAT_CAPABILITY_POINTER) && seat->pointer_dev == NULL) {
139 ds_dbg("wl_backend: Seat(%p) offered pointer", seat);
141 seat->pointer_dev = create_wl_input_device(seat,
142 DS_INPUT_DEVICE_POINTER);
143 seat->pointer_dev->pointer = create_wl_pointer(seat);
145 wl_signal_emit(&seat->backend->base.events.new_input,
148 else if (!(caps & WL_SEAT_CAPABILITY_POINTER) &&
149 seat->pointer_dev != NULL) {
150 ds_dbg("wl_backend: Seat(%p) dropped pointer", seat);
151 ds_input_device_destroy(seat->pointer_dev);
152 seat->pointer_dev = NULL;
155 if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && seat->keyboard_dev == NULL) {
156 ds_dbg("wl_backend: Seat(%p) offered keyboard", seat);
158 seat->keyboard_dev = create_wl_input_device(seat,
159 DS_INPUT_DEVICE_KEYBOARD);
160 seat->keyboard_dev->keyboard = create_wl_keyboard(seat);
162 wl_signal_emit(&seat->backend->base.events.new_input,
165 else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) &&
166 seat->keyboard_dev != NULL) {
167 ds_dbg("wl_backend: Seat(%p) dropped keyboard", seat);
168 ds_input_device_destroy(seat->keyboard_dev);
169 seat->keyboard_dev = NULL;
172 if ((caps & WL_SEAT_CAPABILITY_TOUCH) && seat->touch_dev == NULL) {
173 ds_dbg("wl_backend: Seat(%p) offered touch", seat);
174 seat->touch_dev = create_wl_input_device(seat,
175 DS_INPUT_DEVICE_TOUCH);
176 seat->touch_dev->touch = create_wl_touch(seat);
177 wl_signal_emit(&seat->backend->base.events.new_input,
180 else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) &&
181 seat->touch_dev != NULL) {
182 ds_dbg("wl_backend: Seat(%p) dropped touch", seat);
183 ds_input_device_destroy(seat->touch_dev);
184 seat->touch_dev = NULL;
188 static const struct ds_input_device_interface input_device_iface;
191 ds_input_device_is_wl(struct ds_input_device *ds_dev)
193 return ds_dev->iface == &input_device_iface;
196 static struct ds_wl_input_device *
197 get_wl_input_device_from_input_device(struct ds_input_device *ds_dev)
199 assert(ds_input_device_is_wl(ds_dev));
200 return (struct ds_wl_input_device *)ds_dev;
204 input_device_iface_destroy(struct ds_input_device *ds_dev)
206 struct ds_wl_input_device *dev;
208 dev = get_wl_input_device_from_input_device(ds_dev);
213 static const struct ds_input_device_interface input_device_iface =
215 .destroy = input_device_iface_destroy,
218 static struct ds_input_device *
219 create_wl_input_device(struct ds_wl_seat *seat,
220 enum ds_input_device_type type)
222 struct ds_wl_input_device *dev;
223 unsigned int vendor = 0, product = 0;
227 dev = calloc(1, sizeof *dev);
231 dev->backend = seat->backend;
234 name_size = 8 + strlen(seat->name) + 1;
235 name = alloca(name_size);
236 (void) snprintf(name, name_size, "wayland-%s", seat->name);
238 ds_input_device_init(&dev->base, type, &input_device_iface, name, vendor,
244 static const struct ds_pointer_interface pointer_iface;
246 static struct ds_wl_pointer *
247 get_wl_pointer_from_pointer(struct ds_pointer *ds_pointer)
249 assert(ds_pointer->iface == &pointer_iface);
250 return (struct ds_wl_pointer *)ds_pointer;
254 pointer_iface_destroy(struct ds_pointer *ds_pointer)
256 struct ds_wl_pointer *pointer;
258 pointer = get_wl_pointer_from_pointer(ds_pointer);
260 wl_pointer_release(pointer->wl_pointer);
265 static const struct ds_pointer_interface pointer_iface = {
266 .destroy = pointer_iface_destroy,
270 pointer_handle_enter(void *data, struct wl_pointer *wl_pointer,
271 uint32_t serial, struct wl_surface *surface,
272 wl_fixed_t sx, wl_fixed_t sy)
274 struct ds_wl_seat *seat = data;
275 struct ds_wl_pointer *pointer;
280 ds_dbg("Enter pointer");
282 seat->output = wl_surface_get_user_data(surface);
283 seat->enter_serial = serial;
285 pointer = get_wl_pointer_from_pointer(seat->pointer_dev->pointer);
286 output_enter_pointer(seat->output, pointer, seat->enter_serial);
290 pointer_handle_leave(void *data, struct wl_pointer *wl_pointer,
291 uint32_t serial, struct wl_surface *surface)
293 struct ds_wl_seat *seat = data;
294 struct ds_wl_output *output;
299 output = wl_surface_get_user_data(surface);
300 if (seat->output != output)
303 ds_dbg("Leave pointer");
305 output_leave_pointer(seat->output);
308 seat->enter_serial = 0;
312 pointer_handle_motion(void *data, struct wl_pointer *wl_pointer,
313 uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
315 struct ds_wl_seat *seat = data;
320 // FIXME take size size of a output into account
321 struct ds_event_pointer_motion_absolute event = {
322 .device = seat->pointer_dev,
324 .x = wl_fixed_to_double(sx) / 700,
325 .y = wl_fixed_to_double(sy) / 400,
328 wl_signal_emit(&seat->pointer_dev->pointer->events.motion_absolute,
333 pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
334 uint32_t serial, uint32_t time, uint32_t button, uint32_t state)
336 struct ds_wl_seat *seat = data;
341 struct ds_event_pointer_button event = {
342 .device = seat->pointer_dev,
348 wl_signal_emit(&seat->pointer_dev->pointer->events.button, &event);
352 pointer_handle_axis(void *data, struct wl_pointer *wl_pointer,
353 uint32_t time, uint32_t axis, wl_fixed_t value)
359 pointer_handle_frame(void *data, struct wl_pointer *wl_pointer)
361 struct ds_wl_seat *seat = data;
366 wl_signal_emit(&seat->pointer_dev->pointer->events.frame,
371 pointer_handle_axis_source(void *data, struct wl_pointer *wl_pointer,
372 uint32_t axis_source)
378 pointer_handle_axis_stop(void *data, struct wl_pointer *wl_pointer,
379 uint32_t time, uint32_t axis)
385 pointer_handle_axis_discrete(void *data, struct wl_pointer *wl_pointer,
386 uint32_t axis, int32_t discrete)
391 static const struct wl_pointer_listener wl_pointer_listener = {
392 .enter = pointer_handle_enter,
393 .leave = pointer_handle_leave,
394 .motion = pointer_handle_motion,
395 .button = pointer_handle_button,
396 .axis = pointer_handle_axis,
397 .frame = pointer_handle_frame,
398 .axis_source = pointer_handle_axis_source,
399 .axis_stop = pointer_handle_axis_stop,
400 .axis_discrete = pointer_handle_axis_discrete,
403 static struct ds_pointer *
404 create_wl_pointer(struct ds_wl_seat *seat)
406 struct ds_wl_pointer *pointer;
408 pointer = calloc(1, sizeof *pointer);
410 ds_err("Could not allocate memory");
414 ds_pointer_init(&pointer->base, &pointer_iface);
416 pointer->wl_pointer = wl_seat_get_pointer(seat->wl_seat);
417 wl_pointer_add_listener(pointer->wl_pointer, &wl_pointer_listener, seat);
419 return &pointer->base;
422 static const struct ds_keyboard_interface keyboard_iface;
424 static struct ds_wl_keyboard *
425 get_wl_keyboard_from_keyboard(struct ds_keyboard *ds_keyboard)
427 assert(ds_keyboard->iface == &keyboard_iface);
428 return (struct ds_wl_keyboard *)ds_keyboard;
432 keyboard_iface_destroy(struct ds_keyboard *ds_keyboard)
434 struct ds_wl_keyboard *keyboard;
436 keyboard = get_wl_keyboard_from_keyboard(ds_keyboard);
438 wl_keyboard_release(keyboard->wl_keyboard);
443 static const struct ds_keyboard_interface keyboard_iface = {
444 .destroy = keyboard_iface_destroy,
448 keyboard_handle_keymap(void *data, struct wl_keyboard *wl_keyboard,
449 uint32_t format, int fd, uint32_t size)
451 struct ds_wl_seat *seat = data;
452 struct xkb_context *context;
453 struct xkb_keymap *keymap;
456 ds_dbg("wl_keyboard: keymap");
458 if (format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
459 map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
460 if (map_str == MAP_FAILED) {
461 ds_log_errno(DS_ERR, "mmap failed");
465 context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
466 keymap = xkb_keymap_new_from_string(context, map_str,
467 XKB_KEYMAP_FORMAT_TEXT_V1, 0);
468 munmap(map_str, size);
471 ds_err("Failed to compile keymap");
475 ds_keyboard_set_keymap(seat->keyboard_dev->keyboard, keymap);
477 xkb_keymap_unref(keymap);
478 xkb_context_unref(context);
488 keyboard_handle_enter(void *data, struct wl_keyboard *wl_keyboard,
489 uint32_t serial, struct wl_surface *surface, struct wl_array *keys)
491 struct ds_wl_seat *seat = data;
492 uint32_t *keycode_ptr;
495 ds_dbg("wl_keyboard: enter");
497 time = get_current_time_msec();
499 wl_array_for_each(keycode_ptr, keys) {
500 struct ds_event_keyboard_key event = {
501 .keycode = *keycode_ptr,
502 .state = WL_KEYBOARD_KEY_STATE_PRESSED,
504 .update_state = false,
507 ds_keyboard_notify_key(seat->keyboard_dev->keyboard, &event);
512 keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard,
513 uint32_t serial, struct wl_surface *surface)
515 struct ds_wl_seat *seat = data;
516 struct ds_keyboard *keyboard = seat->keyboard_dev->keyboard;
518 uint32_t time, keycode;
521 ds_dbg("wl_keyboard: leave");
523 time = get_current_time_msec();
525 num_keycodes = keyboard->num_keycodes;
526 pressed = alloca(num_keycodes + 1);
527 memcpy(pressed, keyboard->keycodes, num_keycodes * sizeof(uint32_t));
529 for (size_t i = 0; i < num_keycodes; i++) {
530 keycode = pressed[i];
532 struct ds_event_keyboard_key event = {
534 .state = WL_KEYBOARD_KEY_STATE_RELEASED,
536 .update_state = false,
539 ds_keyboard_notify_key(keyboard, &event);
544 keyboard_handle_key(void *data, struct wl_keyboard *wl_keyboard,
545 uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
547 struct ds_wl_seat *seat = data;
549 ds_dbg("wl_keyboard: key");
551 struct ds_event_keyboard_key event = {
555 .update_state = false,
558 ds_keyboard_notify_key(seat->keyboard_dev->keyboard, &event);
562 keyboard_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard,
563 uint32_t serial_in, uint32_t mods_depressed, uint32_t mods_latched,
564 uint32_t mods_locked, uint32_t group)
566 struct ds_wl_seat *seat = data;
568 ds_dbg("wl_keyboard: modifiers");
570 ds_keyboard_notify_modifiers(seat->keyboard_dev->keyboard,
571 mods_depressed, mods_latched, mods_locked, group);
575 keyboard_handle_repeat_info(void *data, struct wl_keyboard *wl_keyboard,
576 int32_t rate, int32_t delay)
578 ds_dbg("wl_keyboard: repeat_info");
580 // This space is intentionally left blank
583 static const struct wl_keyboard_listener wl_keyboard_listener = {
584 .keymap = keyboard_handle_keymap,
585 .enter = keyboard_handle_enter,
586 .leave = keyboard_handle_leave,
587 .key = keyboard_handle_key,
588 .modifiers = keyboard_handle_modifiers,
589 .repeat_info = keyboard_handle_repeat_info,
592 static struct ds_keyboard *
593 create_wl_keyboard(struct ds_wl_seat *seat)
595 struct ds_wl_keyboard *keyboard;
597 keyboard = calloc(1, sizeof *keyboard);
601 ds_keyboard_init(&keyboard->base, &keyboard_iface);
603 keyboard->wl_keyboard = wl_seat_get_keyboard(seat->wl_seat);
604 wl_keyboard_add_listener(keyboard->wl_keyboard,
605 &wl_keyboard_listener, seat);
607 return &keyboard->base;
610 static const struct ds_touch_interface touch_iface;
612 static struct ds_wl_touch *
613 get_wl_touch_from_touch(struct ds_touch *ds_touch)
615 assert(ds_touch->iface == &touch_iface);
616 return (struct ds_wl_touch *)ds_touch;
620 touch_iface_destroy(struct ds_touch *ds_touch)
622 struct ds_wl_touch *touch;
624 touch = get_wl_touch_from_touch(ds_touch);
626 wl_touch_release(touch->wl_touch);
631 static const struct ds_touch_interface touch_iface = {
632 .destroy = touch_iface_destroy,
636 touch_handle_down(void *data, struct wl_touch *wl_touch,
637 uint32_t serial, uint32_t time,
638 struct wl_surface *surface, int32_t id,
639 wl_fixed_t fixed_x, wl_fixed_t fixed_y)
641 struct ds_wl_seat *seat = data;
643 ds_dbg("wl_touch: down");
645 struct ds_event_touch_down event = {
646 .device = seat->touch_dev,
652 wl_signal_emit(&seat->touch_dev->touch->events.down, &event);
656 touch_handle_up(void *data, struct wl_touch *wl_touch,
657 uint32_t serial, uint32_t time, int32_t id)
659 struct ds_wl_seat *seat = data;
661 ds_dbg("wl_touch: up");
663 struct ds_event_touch_up event = {
664 .device = seat->touch_dev,
668 wl_signal_emit(&seat->touch_dev->touch->events.up, &event);
672 touch_handle_motion(void *data, struct wl_touch *wl_touch,
673 uint32_t time, int32_t id,
674 wl_fixed_t fixed_x, wl_fixed_t fixed_y)
676 ds_dbg("wl_touch: motion");
680 touch_handle_frame(void *data, struct wl_touch *wl_touch)
682 ds_dbg("wl_touch: frame");
686 touch_handle_cancel(void *data, struct wl_touch *wl_touch)
688 ds_dbg("wl_touch: cancel");
691 static const struct wl_touch_listener wl_touch_listener = {
692 .down = touch_handle_down,
693 .up = touch_handle_up,
694 .motion = touch_handle_motion,
695 .frame = touch_handle_frame,
696 .cancel = touch_handle_cancel,
699 static struct ds_touch *
700 create_wl_touch(struct ds_wl_seat *seat)
702 struct ds_wl_touch *touch;
704 touch = calloc(1, sizeof *touch);
706 ds_err("Could not allocate memory");
710 ds_touch_init(&touch->base, &touch_iface);
712 touch->wl_touch = wl_seat_get_touch(seat->wl_seat);
713 wl_touch_add_listener(touch->wl_touch, &wl_touch_listener, seat);