diff --git a/src/evdev-frame.h b/src/evdev-frame.h index 82e80c02..bc1f6832 100644 --- a/src/evdev-frame.h +++ b/src/evdev-frame.h @@ -476,6 +476,21 @@ evdev_frame_append(struct evdev_frame *frame, return 0; } +static inline int +evdev_frame_append_one(struct evdev_frame *frame, evdev_usage_t usage, int32_t value) +{ + if (evdev_usage_eq(usage, EVDEV_SYN_REPORT)) + return 0; + + if (frame->count >= frame->max_size) + return -ENOMEM; + + struct evdev_event *e = &frame->events[frame->count - 1]; + *e = (struct evdev_event){ .usage = usage, .value = value }; + frame->count++; + return 0; +} + static inline int evdev_frame_append_input_event(struct evdev_frame *frame, const struct input_event *event) diff --git a/src/libinput-plugin-tablet-double-tool.c b/src/libinput-plugin-tablet-double-tool.c index d910c4df..9642cb82 100644 --- a/src/libinput-plugin-tablet-double-tool.c +++ b/src/libinput-plugin-tablet-double-tool.c @@ -122,18 +122,14 @@ double_tool_plugin_filter_frame(struct libinput_plugin *plugin, } if (filter & (PEN_IN_PROX | PEN_OUT_OF_PROX)) { - struct evdev_event event = { - .usage = evdev_usage_from(EVDEV_BTN_TOOL_PEN), - .value = (filter & PEN_IN_PROX) ? 1 : 0, - }; - evdev_frame_append(frame_out, &event, 1); + evdev_frame_append_one(frame_out, + evdev_usage_from(EVDEV_BTN_TOOL_PEN), + (filter & PEN_IN_PROX) ? 1 : 0); } if (filter & (ERASER_IN_PROX | ERASER_OUT_OF_PROX)) { - struct evdev_event event = { - .usage = evdev_usage_from(EVDEV_BTN_TOOL_RUBBER), - .value = (filter & ERASER_IN_PROX) ? 1 : 0, - }; - evdev_frame_append(frame_out, &event, 1); + evdev_frame_append_one(frame_out, + evdev_usage_from(EVDEV_BTN_TOOL_RUBBER), + (filter & ERASER_IN_PROX) ? 1 : 0); } return frame_out; diff --git a/src/libinput-plugin-tablet-eraser-button.c b/src/libinput-plugin-tablet-eraser-button.c index f8b12ba7..00cf399e 100644 --- a/src/libinput-plugin-tablet-eraser-button.c +++ b/src/libinput-plugin-tablet-eraser-button.c @@ -209,26 +209,20 @@ eraser_button_insert_frame(struct plugin_device *device, } if (filter & (PEN_IN_PROX | PEN_OUT_OF_PROX)) { - struct evdev_event event = { - .usage = evdev_usage_from(EVDEV_BTN_TOOL_PEN), - .value = (filter & PEN_IN_PROX) ? 1 : 0, - }; - evdev_frame_append(frame_out, &event, 1); + evdev_frame_append_one(frame_out, + evdev_usage_from(EVDEV_BTN_TOOL_PEN), + (filter & PEN_IN_PROX) ? 1 : 0); } if (filter & (ERASER_IN_PROX | ERASER_OUT_OF_PROX)) { - struct evdev_event event = { - .usage = evdev_usage_from(EVDEV_BTN_TOOL_RUBBER), - .value = (filter & ERASER_IN_PROX) ? 1 : 0, - }; - evdev_frame_append(frame_out, &event, 1); + evdev_frame_append_one(frame_out, + evdev_usage_from(EVDEV_BTN_TOOL_RUBBER), + (filter & ERASER_IN_PROX) ? 1 : 0); } if (filter & (BUTTON_UP | BUTTON_DOWN)) { assert(button != NULL); - struct evdev_event event = { - .usage = *button, - .value = (filter & BUTTON_DOWN) ? 1 : 0, - }; - evdev_frame_append(frame_out, &event, 1); + evdev_frame_append_one(frame_out, + *button, + (filter & BUTTON_DOWN) ? 1 : 0); } evdev_frame_set_time(frame_out, evdev_frame_get_time(frame_in)); diff --git a/src/libinput-plugin-tablet-proximity-timer.c b/src/libinput-plugin-tablet-proximity-timer.c index 90efe0ab..c735aabf 100644 --- a/src/libinput-plugin-tablet-proximity-timer.c +++ b/src/libinput-plugin-tablet-proximity-timer.c @@ -115,13 +115,9 @@ tablet_proximity_out_quirk_timer_func(struct libinput_plugin *plugin, plugin_log_debug(device->parent->plugin, "%s: forcing proximity out after timeout\n", libinput_device_get_name(device->device)); - const struct evdev_event prox_out_event = { - .usage = evdev_usage_from(EVDEV_BTN_TOOL_PEN), - .value = 0, - }; _unref_(evdev_frame) *prox_out_frame = evdev_frame_new(2); - evdev_frame_append(prox_out_frame, &prox_out_event, 1); + evdev_frame_append_one(prox_out_frame, evdev_usage_from(EVDEV_BTN_TOOL_PEN), 0); evdev_frame_set_time(prox_out_frame, now); libinput_plugin_prepend_evdev_frame(device->parent->plugin, @@ -215,16 +211,10 @@ proximity_timer_plugin_device_handle_frame(struct libinput_plugin *libinput_plug return; } } else if (device->proximity_out_forced) { - struct evdev_event pen_in_event = { - .usage = evdev_usage_from(EVDEV_BTN_TOOL_PEN), - .value = 1, - }; plugin_log_debug(libinput_plugin, "%s: forcing proximity in\n", libinput_device_get_name(device->device)); - evdev_frame_append(frame, - &pen_in_event, - 1); /* libinput's event frame will have space */ + evdev_frame_append_one(frame, evdev_usage_from(EVDEV_BTN_TOOL_PEN), 1); device->proximity_out_forced = false; proximity_timer_plugin_set_timer(device, time); } diff --git a/test/test-utils.c b/test/test-utils.c index 7bb38016..d1a43220 100644 --- a/test/test-utils.c +++ b/test/test-utils.c @@ -3005,6 +3005,52 @@ START_TEST(evdev_frames) /* We never appended a timestamp */ litest_assert_int_eq(evdev_frame_get_time(frame), 0U); } + { + struct evdev_event events[] = { + { + .usage = U(EVDEV_ABS_X), + .value = 1, + }, + { + .usage = U(EVDEV_ABS_Y), + .value = 2, + }, + { + .usage = U(EVDEV_SYN_REPORT), + .value = 0, + }, + }; + + _unref_(evdev_frame) *frame = evdev_frame_new(3); + int rc = evdev_frame_append_one(frame, U(EVDEV_ABS_X), 1); + litest_assert_neg_errno_success(rc); + rc = evdev_frame_append_one(frame, U(EVDEV_ABS_Y), 2); + litest_assert_neg_errno_success(rc); + rc = evdev_frame_append_one(frame, U(EV_SYN), 0); + litest_assert_neg_errno_success(rc); + + litest_assert_int_eq(evdev_frame_get_count(frame), + ARRAY_LENGTH(events)); + litest_assert_int_eq(frame->max_size, ARRAY_LENGTH(events)); + + size_t nevents; + rc = memcmp(evdev_frame_get_events(frame, &nevents), + events, + sizeof(events)); + litest_assert_int_eq(rc, 0); + litest_assert_int_eq(nevents, ARRAY_LENGTH(events)); + + /* Already full, can't append */ + rc = evdev_frame_append_one(frame, U(EVDEV_ABS_Z), 1); + litest_assert_int_eq(rc, -ENOMEM); + + /* Appending SYN_REPORT is a noop */ + rc = evdev_frame_append_one(frame, U(EVDEV_SYN_REPORT), 0); + litest_assert_neg_errno_success(rc); + litest_assert_int_eq(evdev_frame_get_count(frame), + ARRAY_LENGTH(events)); + litest_assert_int_eq(frame->max_size, ARRAY_LENGTH(events)); + } } END_TEST