From 98218347ee9a479bfd2a0a43cc6377034df84a01 Mon Sep 17 00:00:00 2001 From: Hannes Winkler Date: Thu, 13 Jun 2024 20:15:32 +0200 Subject: [PATCH] set the stylus device type for tablet stylus events (#425) * set the stylus device type for tablet stylus events --- src/user_input.c | 127 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 104 insertions(+), 23 deletions(-) diff --git a/src/user_input.c b/src/user_input.c index b9bd517b..652d7df5 100644 --- a/src/user_input.c +++ b/src/user_input.c @@ -25,7 +25,6 @@ #define THIS_LIBINPUT_VER LIBINPUT_VER(LIBINPUT_VERSION_MAJOR, LIBINPUT_VERSION_MINOR, LIBINPUT_VERSION_PATCH) struct input_device_data { - int64_t flutter_device_id_offset; struct keyboard_state *keyboard_state; int64_t buttons; uint64_t timestamp; @@ -49,6 +48,9 @@ struct input_device_data { * */ struct vec2f *positions; + + int64_t touch_device_id_offset; + int64_t stylus_device_id; }; struct user_input { @@ -200,6 +202,57 @@ static inline FlutterPointerEvent make_mouse_hover_event(size_t timestamp, struc return make_mouse_event(kHover, timestamp, pos, device_id, kFlutterPointerSignalKindNone, VEC2F(0, 0), buttons); } +static inline FlutterPointerEvent make_stylus_event(FlutterPointerPhase phase, size_t timestamp, struct vec2f pos, int32_t device_id) { + FlutterPointerEvent event; + memset(&event, 0, sizeof(event)); + + event.struct_size = sizeof(event); + event.phase = phase; + event.timestamp = timestamp; + event.x = pos.x; + event.y = pos.y; + event.device = device_id; + event.signal_kind = kFlutterPointerSignalKindNone; + event.scroll_delta_x = 0.0; + event.scroll_delta_y = 0.0; + event.device_kind = kFlutterPointerDeviceKindStylus; + event.buttons = 0; + event.pan_x = 0.0; + event.pan_y = 0.0; + event.scale = 0.0; + event.rotation = 0.0; + + return event; +} + +UNUSED static inline FlutterPointerEvent make_stylus_cancel_event(size_t timestamp, struct vec2f pos, int32_t device_id) { + return make_stylus_event(kCancel, timestamp, pos, device_id); +} + +static inline FlutterPointerEvent make_stylus_up_event(size_t timestamp, struct vec2f pos, int32_t device_id) { + return make_stylus_event(kUp, timestamp, pos, device_id); +} + +static inline FlutterPointerEvent make_stylus_down_event(size_t timestamp, struct vec2f pos, int32_t device_id) { + return make_stylus_event(kDown, timestamp, pos, device_id); +} + +static inline FlutterPointerEvent make_stylus_move_event(size_t timestamp, struct vec2f pos, int32_t device_id) { + return make_stylus_event(kMove, timestamp, pos, device_id); +} + +static inline FlutterPointerEvent make_stylus_hover_event(size_t timestamp, struct vec2f pos, int32_t device_id) { + return make_stylus_event(kHover, timestamp, pos, device_id); +} + +static inline FlutterPointerEvent make_stylus_add_event(size_t timestamp, struct vec2f pos, int32_t device_id) { + return make_stylus_event(kAdd, timestamp, pos, device_id); +} + +static inline FlutterPointerEvent make_stylus_remove_event(size_t timestamp, struct vec2f pos, int32_t device_id) { + return make_stylus_event(kRemove, timestamp, pos, device_id); +} + // libinput interface static int on_open(const char *path, int flags, void *userdata) { struct user_input *input; @@ -492,7 +545,8 @@ static int on_device_added(struct user_input *input, struct libinput_event *even return ENOMEM; } - data->flutter_device_id_offset = input->next_unused_flutter_device_id; + data->touch_device_id_offset = -1; + data->stylus_device_id = -1; data->keyboard_state = NULL; data->buttons = 0; data->timestamp = timestamp; @@ -523,6 +577,8 @@ static int on_device_added(struct user_input *input, struct libinput_event *even goto fail_free_data; } + data->touch_device_id_offset = input->next_unused_flutter_device_id; + for (int i = 0; i < n_slots; i++) { device_id = input->next_unused_flutter_device_id++; @@ -550,8 +606,9 @@ static int on_device_added(struct user_input *input, struct libinput_event *even if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TABLET_TOOL)) { device_id = input->next_unused_flutter_device_id++; - /// TODO: Use kFlutterPointerDeviceKindStylus here - emit_pointer_event(input, make_touch_add_event(timestamp, VEC2F(0, 0), device_id)); + data->stylus_device_id = device_id; + + emit_pointer_event(input, make_stylus_add_event(timestamp, VEC2F(0, 0), device_id)); } return 0; @@ -594,14 +651,16 @@ static int on_device_removed(struct user_input *input, struct libinput_event *ev } } } + if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TOUCH)) { // add all touch slots as individual touch devices to flutter if (emit_flutter_events) { for (int i = 0; i < libinput_device_touch_get_touch_count(device); i++) { - emit_pointer_event(input, make_touch_remove_event(timestamp, VEC2F(0, 0), data->flutter_device_id_offset + i)); + emit_pointer_event(input, make_touch_remove_event(timestamp, VEC2F(0, 0), data->touch_device_id_offset + i)); } } } + if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_KEYBOARD)) { // create a new keyboard state for this keyboard if (data->keyboard_state != NULL) { @@ -609,6 +668,10 @@ static int on_device_removed(struct user_input *input, struct libinput_event *ev } } + if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TABLET_TOOL)) { + emit_pointer_event(input, make_stylus_remove_event(timestamp, VEC2F(0, 0), data->stylus_device_id)); + } + if (data != NULL) { if (data->positions != NULL) { free(data->positions); @@ -1020,7 +1083,7 @@ static int on_touch_down(struct user_input *input, struct libinput_event *event) slot = 0; } - device_id = data->flutter_device_id_offset + slot; + device_id = data->touch_device_id_offset + slot; // transform the display coordinates to view (flutter) coordinates pos_view = transform_point( @@ -1062,7 +1125,7 @@ static int on_touch_up(struct user_input *input, struct libinput_event *event) { slot = 0; } - device_id = data->flutter_device_id_offset + slot; + device_id = data->touch_device_id_offset + slot; emit_pointer_event(input, make_touch_up_event(timestamp, data->positions[slot], device_id)); @@ -1091,7 +1154,7 @@ static int on_touch_motion(struct user_input *input, struct libinput_event *even slot = 0; } - device_id = data->flutter_device_id_offset + slot; + device_id = data->touch_device_id_offset + slot; // transform the display coordinates to view (flutter) coordinates pos_view = transform_point( @@ -1150,29 +1213,48 @@ static int on_tablet_tool_axis(struct user_input *input, struct libinput_event * tablet_event = libinput_event_get_tablet_tool_event(event); timestamp = libinput_event_tablet_tool_get_time_usec(tablet_event); - device_id = data->flutter_device_id_offset; + device_id = data->stylus_device_id; - // Only report down events when the tool is in contact with the tablet. - /// TODO: Maybe report hover events when it's not in contact? - /// FIXME: Use kFlutterPointerDeviceKindStylus here - if (data->tip) { - pos.x = libinput_event_tablet_tool_get_x_transformed(tablet_event, input->display_width - 1); - pos.y = libinput_event_tablet_tool_get_y_transformed(tablet_event, input->display_height - 1); + pos.x = libinput_event_tablet_tool_get_x_transformed(tablet_event, input->display_width - 1); + pos.y = libinput_event_tablet_tool_get_y_transformed(tablet_event, input->display_height - 1); - pos = transform_point(input->display_to_view_transform, pos); + pos = transform_point(input->display_to_view_transform, pos); - emit_pointer_event(input, make_touch_move_event(timestamp, pos, device_id)); + if (data->tip) { + emit_pointer_event(input, make_stylus_move_event(timestamp, pos, device_id)); + } else { + emit_pointer_event(input, make_stylus_hover_event(timestamp, pos, device_id)); } return 0; } static int on_tablet_tool_proximity(struct user_input *input, struct libinput_event *event) { + struct libinput_event_tablet_tool *tablet_event; + struct input_device_data *data; + struct vec2f pos; + uint64_t timestamp; + int64_t device_id; + ASSERT_NOT_NULL(input); ASSERT_NOT_NULL(event); - (void) input; - (void) event; + data = libinput_device_get_user_data(libinput_event_get_device(event)); + ASSERT_NOT_NULL(data); + + tablet_event = libinput_event_get_tablet_tool_event(event); + timestamp = libinput_event_tablet_tool_get_time_usec(tablet_event); + + device_id = data->stylus_device_id; + + pos.x = libinput_event_tablet_tool_get_x_transformed(tablet_event, input->display_width - 1); + pos.y = libinput_event_tablet_tool_get_y_transformed(tablet_event, input->display_height - 1); + + pos = transform_point(input->display_to_view_transform, pos); + + if (!data->tip) { + emit_pointer_event(input, make_stylus_hover_event(timestamp, pos, device_id)); + } return 0; } @@ -1193,20 +1275,19 @@ static int on_tablet_tool_tip(struct user_input *input, struct libinput_event *e tablet_event = libinput_event_get_tablet_tool_event(event); timestamp = libinput_event_tablet_tool_get_time_usec(tablet_event); - device_id = data->flutter_device_id_offset; + device_id = data->stylus_device_id; pos.x = libinput_event_tablet_tool_get_x_transformed(tablet_event, input->display_width - 1); pos.y = libinput_event_tablet_tool_get_y_transformed(tablet_event, input->display_height - 1); pos = transform_point(input->display_to_view_transform, pos); - /// FIXME: Use kFlutterPointerDeviceKindStylus here if (libinput_event_tablet_tool_get_tip_state(tablet_event) == LIBINPUT_TABLET_TOOL_TIP_DOWN) { data->tip = true; - emit_pointer_event(input, make_touch_down_event(timestamp, pos, device_id)); + emit_pointer_event(input, make_stylus_down_event(timestamp, pos, device_id)); } else { data->tip = false; - emit_pointer_event(input, make_touch_up_event(timestamp, pos, device_id)); + emit_pointer_event(input, make_stylus_up_event(timestamp, pos, device_id)); } return 0;