diff --git a/backend/libinput/backend.c b/backend/libinput/backend.c index 111ebf3e..68e6a0e8 100644 --- a/backend/libinput/backend.c +++ b/backend/libinput/backend.c @@ -255,11 +255,10 @@ struct libinput_device *wlr_libinput_get_device_handle( case WLR_INPUT_DEVICE_TABLET_TOOL: dev = device_from_tablet(wlr_dev->tablet); break; - default: - dev = (struct wlr_libinput_input_device *)wlr_dev; + case WLR_INPUT_DEVICE_TABLET_PAD: + dev = device_from_tablet_pad(wlr_dev->tablet_pad); break; } - return dev->handle; } diff --git a/backend/libinput/events.c b/backend/libinput/events.c index 76e7709c..44800d36 100644 --- a/backend/libinput/events.c +++ b/backend/libinput/events.c @@ -52,6 +52,9 @@ void destroy_libinput_input_device(struct wlr_libinput_input_device *dev) if (dev->tablet.impl) { wlr_tablet_destroy(&dev->tablet); } + if (dev->tablet_pad.impl) { + wlr_tablet_pad_destroy(&dev->tablet_pad); + } } libinput_device_unref(dev->handle); @@ -59,32 +62,6 @@ void destroy_libinput_input_device(struct wlr_libinput_input_device *dev) free(dev); } -static struct wlr_input_device *allocate_device( - struct wlr_libinput_backend *backend, - struct libinput_device *libinput_dev, struct wl_list *wlr_devices, - enum wlr_input_device_type type) { - const char *name = libinput_device_get_name(libinput_dev); - struct wlr_libinput_input_device *dev = - calloc(1, sizeof(struct wlr_libinput_input_device)); - if (dev == NULL) { - return NULL; - } - struct wlr_input_device *wlr_dev = &dev->wlr_input_device; - libinput_device_get_size(libinput_dev, - &wlr_dev->width_mm, &wlr_dev->height_mm); - const char *output_name = libinput_device_get_output_name(libinput_dev); - if (output_name != NULL) { - wlr_dev->output_name = strdup(output_name); - } - wl_list_insert(wlr_devices, &dev->link); - dev->handle = libinput_dev; - libinput_device_ref(libinput_dev); - wlr_input_device_init(wlr_dev, type, name); - wlr_dev->vendor = libinput_device_get_id_vendor(libinput_dev); - wlr_dev->product = libinput_device_get_id_product(libinput_dev); - return wlr_dev; -} - bool wlr_input_device_is_libinput(struct wlr_input_device *wlr_dev) { switch (wlr_dev->type) { case WLR_INPUT_DEVICE_KEYBOARD: @@ -173,6 +150,14 @@ static void handle_device_added(struct wlr_libinput_backend *backend, dev_used = true; } + if (libinput_device_has_capability( + libinput_dev, LIBINPUT_DEVICE_CAP_TABLET_PAD)) { + init_device_tablet_pad(dev); + wlr_signal_emit_safe(&backend->backend.events.new_input, + &dev->tablet_pad.base); + dev_used = true; + } + if (dev_used) { wl_list_insert(&backend->devices, &dev->link); return; @@ -187,21 +172,6 @@ static void handle_device_added(struct wlr_libinput_backend *backend, return; } wl_list_init(wlr_devices); - - if (libinput_device_has_capability( - libinput_dev, LIBINPUT_DEVICE_CAP_TABLET_PAD)) { - struct wlr_input_device *wlr_dev = allocate_device(backend, - libinput_dev, wlr_devices, WLR_INPUT_DEVICE_TABLET_PAD); - if (!wlr_dev) { - goto fail; - } - wlr_dev->tablet_pad = create_libinput_tablet_pad(libinput_dev); - if (!wlr_dev->tablet_pad) { - free(wlr_dev); - goto fail; - } - wlr_signal_emit_safe(&backend->backend.events.new_input, wlr_dev); - } if (libinput_device_has_capability( libinput_dev, LIBINPUT_DEVICE_CAP_GESTURE)) { // TODO @@ -325,13 +295,13 @@ void handle_libinput_event(struct wlr_libinput_backend *backend, handle_tablet_tool_button(event, &dev->tablet); break; case LIBINPUT_EVENT_TABLET_PAD_BUTTON: - handle_tablet_pad_button(event, libinput_dev); + handle_tablet_pad_button(event, &dev->tablet_pad); break; case LIBINPUT_EVENT_TABLET_PAD_RING: - handle_tablet_pad_ring(event, libinput_dev); + handle_tablet_pad_ring(event, &dev->tablet_pad); break; case LIBINPUT_EVENT_TABLET_PAD_STRIP: - handle_tablet_pad_strip(event, libinput_dev); + handle_tablet_pad_strip(event, &dev->tablet_pad); break; case LIBINPUT_EVENT_SWITCH_TOGGLE: handle_switch_toggle(event, &dev->switch_device); diff --git a/backend/libinput/tablet_pad.c b/backend/libinput/tablet_pad.c index 50b8ad6e..ba988557 100644 --- a/backend/libinput/tablet_pad.c +++ b/backend/libinput/tablet_pad.c @@ -1,17 +1,20 @@ -#ifndef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 200809L -#endif #include #include #include #include -#include #include -#include #include #include "backend/libinput.h" #include "util/signal.h" +static void group_destroy(struct wlr_tablet_pad_group *group) { + free(group->buttons); + free(group->strips); + free(group->rings); + free(group); +} + // FIXME: Decide on how to alloc/count here static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad, struct libinput_device *device, unsigned int index) { @@ -20,6 +23,7 @@ static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad, struct wlr_tablet_pad_group *group = calloc(1, sizeof(struct wlr_tablet_pad_group)); if (!group) { + wlr_log_errno(WLR_ERROR, "failed to allocate wlr_tablet_pad_group"); return; } @@ -29,6 +33,10 @@ static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad, } } group->rings = calloc(sizeof(unsigned int), group->ring_count); + if (group->rings == NULL) { + goto group_fail; + } + size_t ring = 0; for (size_t i = 0; i < pad->ring_count; ++i) { if (libinput_tablet_pad_mode_group_has_ring(li_group, i)) { @@ -42,6 +50,9 @@ static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad, } } group->strips = calloc(sizeof(unsigned int), group->strip_count); + if (group->strips == NULL) { + goto group_fail; + } size_t strip = 0; for (size_t i = 0; i < pad->strip_count; ++i) { if (libinput_tablet_pad_mode_group_has_strip(li_group, i)) { @@ -55,6 +66,9 @@ static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad, } } group->buttons = calloc(sizeof(unsigned int), group->button_count); + if (group->buttons == NULL) { + goto group_fail; + } size_t button = 0; for (size_t i = 0; i < pad->button_count; ++i) { if (libinput_tablet_pad_mode_group_has_button(li_group, i)) { @@ -63,53 +77,74 @@ static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad, } group->mode_count = libinput_tablet_pad_mode_group_get_num_modes(li_group); + + libinput_tablet_pad_mode_group_ref(li_group); + wl_list_insert(&pad->groups, &group->link); + return; + +group_fail: + wlr_log(WLR_ERROR, "failed to configure wlr_tablet_pad_group"); + group_destroy(group); } -const struct wlr_tablet_pad_impl libinput_tablet_pad_impl; +static void tablet_pad_destroy(struct wlr_tablet_pad *wlr_tablet_pad) { + struct wlr_libinput_input_device *dev = + device_from_tablet_pad(wlr_tablet_pad); -struct wlr_tablet_pad *create_libinput_tablet_pad( - struct libinput_device *libinput_dev) { - assert(libinput_dev); - struct wlr_tablet_pad *wlr_tablet_pad = - calloc(1, sizeof(struct wlr_tablet_pad)); - if (!wlr_tablet_pad) { - wlr_log(WLR_ERROR, "Unable to allocate wlr_tablet_pad"); - return NULL; + struct wlr_tablet_pad_group *group, *tmp; + wl_list_for_each_safe(group, tmp, &wlr_tablet_pad->groups, link) { + group_destroy(group); + } + + int groups = libinput_device_tablet_pad_get_num_mode_groups(dev->handle); + for (int i = 0; i < groups; ++i) { + struct libinput_tablet_pad_mode_group *li_group = + libinput_device_tablet_pad_get_mode_group(dev->handle, i); + libinput_tablet_pad_mode_group_unref(li_group); } - const char *name = libinput_device_get_name(libinput_dev); +} + +const struct wlr_tablet_pad_impl libinput_tablet_pad_impl = { + .destroy = tablet_pad_destroy, +}; + +void init_device_tablet_pad(struct wlr_libinput_input_device *dev) { + struct libinput_device *handle = dev->handle; + const char *name = libinput_device_get_name(handle); + struct wlr_tablet_pad *wlr_tablet_pad = &dev->tablet_pad; wlr_tablet_pad_init(wlr_tablet_pad, &libinput_tablet_pad_impl, name); - wlr_tablet_pad->base.vendor = libinput_device_get_id_vendor(libinput_dev); - wlr_tablet_pad->base.product = libinput_device_get_id_product(libinput_dev); + wlr_tablet_pad->base.vendor = libinput_device_get_id_vendor(handle); + wlr_tablet_pad->base.product = libinput_device_get_id_product(handle); wlr_tablet_pad->button_count = - libinput_device_tablet_pad_get_num_buttons(libinput_dev); + libinput_device_tablet_pad_get_num_buttons(handle); wlr_tablet_pad->ring_count = - libinput_device_tablet_pad_get_num_rings(libinput_dev); + libinput_device_tablet_pad_get_num_rings(handle); wlr_tablet_pad->strip_count = - libinput_device_tablet_pad_get_num_strips(libinput_dev); + libinput_device_tablet_pad_get_num_strips(handle); - struct udev_device *udev = libinput_device_get_udev_device(libinput_dev); + struct udev_device *udev = libinput_device_get_udev_device(handle); char **dst = wl_array_add(&wlr_tablet_pad->paths, sizeof(char *)); *dst = strdup(udev_device_get_syspath(udev)); - int groups = libinput_device_tablet_pad_get_num_mode_groups(libinput_dev); + int groups = libinput_device_tablet_pad_get_num_mode_groups(handle); for (int i = 0; i < groups; ++i) { - add_pad_group_from_libinput(wlr_tablet_pad, libinput_dev, i); + add_pad_group_from_libinput(wlr_tablet_pad, handle, i); } +} + +struct wlr_libinput_input_device *device_from_tablet_pad( + struct wlr_tablet_pad *wlr_tablet_pad) { + assert(wlr_tablet_pad->impl == &libinput_tablet_pad_impl); - return wlr_tablet_pad; + struct wlr_libinput_input_device *dev = + wl_container_of(wlr_tablet_pad, dev, tablet_pad); + return dev; } void handle_tablet_pad_button(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_TABLET_PAD, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, - "Got a tablet pad event for a device with no tablet pad?"); - return; - } + struct wlr_tablet_pad *tablet_pad) { struct libinput_event_tablet_pad *pevent = libinput_event_get_tablet_pad_event(event); struct wlr_event_tablet_pad_button wlr_event = { 0 }; @@ -127,18 +162,11 @@ void handle_tablet_pad_button(struct libinput_event *event, wlr_event.state = WLR_BUTTON_RELEASED; break; } - wlr_signal_emit_safe(&wlr_dev->tablet_pad->events.button, &wlr_event); + wlr_signal_emit_safe(&tablet_pad->events.button, &wlr_event); } void handle_tablet_pad_ring(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_TABLET_PAD, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, - "Got a tablet pad event for a device with no tablet pad?"); - return; - } + struct wlr_tablet_pad *tablet_pad) { struct libinput_event_tablet_pad *pevent = libinput_event_get_tablet_pad_event(event); struct wlr_event_tablet_pad_ring wlr_event = { 0 }; @@ -155,18 +183,11 @@ void handle_tablet_pad_ring(struct libinput_event *event, wlr_event.source = WLR_TABLET_PAD_RING_SOURCE_FINGER; break; } - wlr_signal_emit_safe(&wlr_dev->tablet_pad->events.ring, &wlr_event); + wlr_signal_emit_safe(&tablet_pad->events.ring, &wlr_event); } void handle_tablet_pad_strip(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_TABLET_PAD, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, - "Got a tablet pad event for a device with no tablet pad?"); - return; - } + struct wlr_tablet_pad *tablet_pad) { struct libinput_event_tablet_pad *pevent = libinput_event_get_tablet_pad_event(event); struct wlr_event_tablet_pad_strip wlr_event = { 0 }; @@ -183,5 +204,5 @@ void handle_tablet_pad_strip(struct libinput_event *event, wlr_event.source = WLR_TABLET_PAD_STRIP_SOURCE_FINGER; break; } - wlr_signal_emit_safe(&wlr_dev->tablet_pad->events.strip, &wlr_event); + wlr_signal_emit_safe(&tablet_pad->events.strip, &wlr_event); } diff --git a/include/backend/libinput.h b/include/backend/libinput.h index 808da101..6579b1af 100644 --- a/include/backend/libinput.h +++ b/include/backend/libinput.h @@ -40,6 +40,7 @@ struct wlr_libinput_input_device { struct wlr_touch touch; struct wlr_tablet tablet; struct wl_list tablet_tools; // see backend/libinput/tablet_tool.c + struct wlr_tablet_pad tablet_pad; struct wl_list link; }; @@ -125,13 +126,14 @@ void handle_tablet_tool_tip(struct libinput_event *event, void handle_tablet_tool_button(struct libinput_event *event, struct wlr_tablet *tablet); -struct wlr_tablet_pad *create_libinput_tablet_pad( - struct libinput_device *device); +void init_device_tablet_pad(struct wlr_libinput_input_device *dev); +struct wlr_libinput_input_device *device_from_tablet_pad( + struct wlr_tablet_pad *tablet_pad); void handle_tablet_pad_button(struct libinput_event *event, - struct libinput_device *device); + struct wlr_tablet_pad *tablet_pad); void handle_tablet_pad_ring(struct libinput_event *event, - struct libinput_device *device); + struct wlr_tablet_pad *tablet_pad); void handle_tablet_pad_strip(struct libinput_event *event, - struct libinput_device *device); + struct wlr_tablet_pad *tablet_pad); #endif