diff --git a/src/libinput-private.h b/src/libinput-private.h index 8a7970c8..d245635a 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -29,14 +29,11 @@ struct libinput_device { const struct libinput_device_interface *device_interface; void *device_interface_data; - const struct libinput_keyboard_listener *keyboard_listener; - void *keyboard_listener_data; - - const struct libinput_pointer_listener *pointer_listener; - void *pointer_listener_data; - - const struct libinput_touch_listener *touch_listener; - void *touch_listener_data; + struct libinput_event **events; + size_t events_count; + size_t events_len; + size_t events_in; + size_t events_out; }; void diff --git a/src/libinput.c b/src/libinput.c index 10baf265..fd0fb1e7 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -22,22 +22,38 @@ #include "config.h" +#include #include +#include #include "libinput.h" #include "evdev.h" #include "libinput-private.h" +static void +post_event(struct libinput_device *device, + enum libinput_event_type type, + struct libinput_event *event); + void keyboard_notify_key(struct libinput_device *device, uint32_t time, uint32_t key, enum libinput_keyboard_key_state state) { - if (device->keyboard_listener) - device->keyboard_listener->notify_key( - time, key, state, - device->keyboard_listener_data); + struct libinput_event_keyboard_key *key_event; + + key_event = malloc(sizeof *key_event); + if (!key_event) + return; + + *key_event = (struct libinput_event_keyboard_key) { + .time = time, + .key = key, + .state = state, + }; + + post_event(device, LIBINPUT_EVENT_KEYBOARD_KEY, &key_event->base); } void @@ -46,10 +62,19 @@ pointer_notify_motion(struct libinput_device *device, li_fixed_t dx, li_fixed_t dy) { - if (device->pointer_listener) - device->pointer_listener->notify_motion( - time, dx, dy, - device->pointer_listener_data); + struct libinput_event_pointer_motion *motion_event; + + motion_event = malloc(sizeof *motion_event); + if (!motion_event) + return; + + *motion_event = (struct libinput_event_pointer_motion) { + .time = time, + .dx = dx, + .dy = dy, + }; + + post_event(device, LIBINPUT_EVENT_POINTER_MOTION, &motion_event->base); } void @@ -58,10 +83,21 @@ pointer_notify_motion_absolute(struct libinput_device *device, li_fixed_t x, li_fixed_t y) { - if (device->pointer_listener) - device->pointer_listener->notify_motion_absolute( - time, x, y, - device->pointer_listener_data); + struct libinput_event_pointer_motion_absolute *motion_absolute_event; + + motion_absolute_event = malloc(sizeof *motion_absolute_event); + if (!motion_absolute_event) + return; + + *motion_absolute_event = (struct libinput_event_pointer_motion_absolute) { + .time = time, + .x = x, + .y = y, + }; + + post_event(device, + LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE, + &motion_absolute_event->base); } void @@ -70,10 +106,19 @@ pointer_notify_button(struct libinput_device *device, int32_t button, enum libinput_pointer_button_state state) { - if (device->pointer_listener) - device->pointer_listener->notify_button( - time, button, state, - device->pointer_listener_data); + struct libinput_event_pointer_button *button_event; + + button_event = malloc(sizeof *button_event); + if (!button_event) + return; + + *button_event = (struct libinput_event_pointer_button) { + .time = time, + .button = button, + .state = state, + }; + + post_event(device, LIBINPUT_EVENT_POINTER_BUTTON, &button_event->base); } void @@ -82,10 +127,19 @@ pointer_notify_axis(struct libinput_device *device, enum libinput_pointer_axis axis, li_fixed_t value) { - if (device->pointer_listener) - device->pointer_listener->notify_axis( - time, axis, value, - device->pointer_listener_data); + struct libinput_event_pointer_axis *axis_event; + + axis_event = malloc(sizeof *axis_event); + if (!axis_event) + return; + + *axis_event = (struct libinput_event_pointer_axis) { + .time = time, + .axis = axis, + .value = value, + }; + + post_event(device, LIBINPUT_EVENT_POINTER_AXIS, &axis_event->base); } void @@ -96,40 +150,89 @@ touch_notify_touch(struct libinput_device *device, li_fixed_t y, enum libinput_touch_type touch_type) { - if (device->touch_listener) - device->touch_listener->notify_touch( - time, slot, x, y, touch_type, - device->touch_listener_data); + struct libinput_event_touch_touch *touch_event; + + touch_event = malloc(sizeof *touch_event); + if (!touch_event) + return; + + *touch_event = (struct libinput_event_touch_touch) { + .time = time, + .slot = slot, + .x = x, + .y = y, + .touch_type = touch_type, + }; + + post_event(device, LIBINPUT_EVENT_TOUCH_TOUCH, &touch_event->base); } -LIBINPUT_EXPORT void -libinput_device_set_keyboard_listener( - struct libinput_device *device, - const struct libinput_keyboard_listener *listener, - void *data) +static void +init_event_base(struct libinput_event *event, enum libinput_event_type type) { - device->keyboard_listener = listener; - device->keyboard_listener_data = data; + event->type = type; } -LIBINPUT_EXPORT void -libinput_device_set_pointer_listener( - struct libinput_device *device, - const struct libinput_pointer_listener *listener, - void *data) +static void +post_event(struct libinput_device *device, + enum libinput_event_type type, + struct libinput_event *event) { - device->pointer_listener = listener; - device->pointer_listener_data = data; + struct libinput_event **events = device->events; + size_t events_len = device->events_len; + size_t events_count = device->events_count; + size_t move_len; + size_t new_out; + + events_count++; + if (events_count > events_len) { + if (events_len == 0) + events_len = 4; + else + events_len *= 2; + events = realloc(events, events_len * sizeof *events); + if (!events) { + fprintf(stderr, "Failed to reallocate event ring " + "buffer"); + return; + } + + if (device->events_count > 0 && device->events_in == 0) { + device->events_in = device->events_len; + } else if (device->events_count > 0 && + device->events_out >= device->events_in) { + move_len = device->events_len - device->events_out; + new_out = events_len - move_len; + memmove(events + new_out, + device->events + device->events_out, + move_len * sizeof *events); + device->events_out = new_out; + } + + device->events = events; + device->events_len = events_len; + } + + init_event_base(event, type); + + device->events_count = events_count; + events[device->events_in] = event; + device->events_in = (device->events_in + 1) % device->events_len; } -LIBINPUT_EXPORT void -libinput_device_set_touch_listener( - struct libinput_device *device, - const struct libinput_touch_listener *listener, - void *data) +LIBINPUT_EXPORT struct libinput_event * +libinput_device_get_event(struct libinput_device *device) { - device->touch_listener = listener; - device->touch_listener_data = data; + struct libinput_event *event; + + if (device->events_count == 0) + return NULL; + + event = device->events[device->events_out]; + device->events_out = (device->events_out + 1) % device->events_len; + device->events_count--; + + return event; } LIBINPUT_EXPORT int @@ -141,6 +244,12 @@ libinput_device_dispatch(struct libinput_device *device) LIBINPUT_EXPORT void libinput_device_destroy(struct libinput_device *device) { + struct libinput_event *event; + + while ((event = libinput_device_get_event(device))) + free(event); + free(device->events); + evdev_device_destroy((struct evdev_device *) device); } diff --git a/src/libinput.h b/src/libinput.h index ac396b79..745660c2 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -63,6 +63,66 @@ enum libinput_touch_type { LIBINPUT_TOUCH_TYPE_CANCEL = 4, }; +enum libinput_event_type { + + LIBINPUT_EVENT_KEYBOARD_KEY = 300, + + LIBINPUT_EVENT_POINTER_MOTION = 400, + LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE, + LIBINPUT_EVENT_POINTER_BUTTON, + LIBINPUT_EVENT_POINTER_AXIS, + + LIBINPUT_EVENT_TOUCH_TOUCH = 500, +}; + +struct libinput_event { + enum libinput_event_type type; +}; + +struct libinput_event_keyboard_key { + struct libinput_event base; + uint32_t time; + uint32_t key; + enum libinput_keyboard_key_state state; +}; + +struct libinput_event_pointer_motion { + struct libinput_event base; + uint32_t time; + li_fixed_t dx; + li_fixed_t dy; +}; + +struct libinput_event_pointer_motion_absolute { + struct libinput_event base; + uint32_t time; + li_fixed_t x; + li_fixed_t y; +}; + +struct libinput_event_pointer_button { + struct libinput_event base; + uint32_t time; + int32_t button; + enum libinput_pointer_button_state state; +}; + +struct libinput_event_pointer_axis { + struct libinput_event base; + uint32_t time; + enum libinput_pointer_axis axis; + li_fixed_t value; +}; + +struct libinput_event_touch_touch { + struct libinput_event base; + uint32_t time; + int32_t slot; + li_fixed_t x; + li_fixed_t y; + enum libinput_touch_type touch_type; +}; + struct libinput_fd_handle; typedef void (*libinput_fd_callback)(int fd, void *data); @@ -90,41 +150,6 @@ struct libinput_device_interface { void (*device_lost)(void *data); }; -struct libinput_keyboard_listener { - void (*notify_key)(uint32_t time, - uint32_t key, - enum libinput_keyboard_key_state state, - void *data); -}; - -struct libinput_pointer_listener { - void (*notify_motion)(uint32_t time, - li_fixed_t dx, - li_fixed_t dy, - void *data); - void (*notify_motion_absolute)(uint32_t time, - li_fixed_t x, - li_fixed_t y, - void *data); - void (*notify_button)(uint32_t time, - int32_t button, - enum libinput_pointer_button_state state, - void *data); - void (*notify_axis)(uint32_t time, - enum libinput_pointer_axis axis, - li_fixed_t value, - void *data); -}; - -struct libinput_touch_listener { - void (*notify_touch)(uint32_t time, - int32_t slot, - li_fixed_t x, - li_fixed_t y, - enum libinput_touch_type touch_type, - void *data); -}; - struct libinput_seat; struct libinput_device; @@ -134,27 +159,12 @@ libinput_device_create_evdev(const char *devnode, const struct libinput_device_interface *interface, void *user_data); -void -libinput_device_set_keyboard_listener( - struct libinput_device *device, - const struct libinput_keyboard_listener *listener, - void *data); - -void -libinput_device_set_pointer_listener( - struct libinput_device *device, - const struct libinput_pointer_listener *listener, - void *data); - -void -libinput_device_set_touch_listener( - struct libinput_device *device, - const struct libinput_touch_listener *listener, - void *data); - int libinput_device_dispatch(struct libinput_device *device); +struct libinput_event * +libinput_device_get_event(struct libinput_device *device); + void libinput_device_destroy(struct libinput_device *device);