Skip to content

Commit

Permalink
set the stylus device type for tablet stylus events (#425)
Browse files Browse the repository at this point in the history
* set the stylus device type for tablet stylus events
  • Loading branch information
ardera authored Jun 13, 2024
1 parent 18ef368 commit 9821834
Showing 1 changed file with 104 additions and 23 deletions.
127 changes: 104 additions & 23 deletions src/user_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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++;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -594,21 +651,27 @@ 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) {
keyboard_state_destroy(data->keyboard_state);
}
}

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);
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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));

Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
Expand Down

0 comments on commit 9821834

Please sign in to comment.