[PATCH v2 libinput] tablet: sync tools already in proximity at startup
Peter Hutterer
peter.hutterer at who-t.net
Wed Mar 4 17:23:43 PST 2015
On Tue, Mar 03, 2015 at 12:29:28PM -0500, Benjamin Tissoires wrote:
> On Mon, Mar 2, 2015 at 10:29 PM, Benjamin Tissoires
> <benjamin.tissoires at gmail.com> wrote:
> > On Mon, Mar 2, 2015 at 7:59 PM, Peter Hutterer <peter.hutterer at who-t.net> wrote:
> >> If a tool is in proximity when we init, send a proximity event immediately.
> >>
> >> This is only partially reliable due to the current kernel behavior:
> >> * if the tool comes into proximity when there is no evdev client, the device
> >> won't send any events and must be lifted out-of-proximity first.
> >
> > This only affect the pro line (Intuos 1-5/pro + Cintiq), and is rather
> > easy to fix. I'll send a patch for it.
>
> Patch on the LKML: https://patchwork.kernel.org/patch/5924611/
> >> @@ -467,6 +467,27 @@ tablet_evcode_to_tool(int code)
[...]
> >> return type;
> >> }
> >>
> >> +static inline int
> >> +tablet_tool_to_evcode(enum libinput_tool_type type)
> >> +{
> >> + int code;
> >> +
> >> + switch (type) {
> >> + case LIBINPUT_TOOL_PEN: code = BTN_TOOL_PEN; break;
> >> + case LIBINPUT_TOOL_ERASER: code = BTN_TOOL_RUBBER; break;
> >> + case LIBINPUT_TOOL_BRUSH: code = BTN_TOOL_BRUSH; break;
> >> + case LIBINPUT_TOOL_PENCIL: code = BTN_TOOL_PENCIL; break;
> >> + case LIBINPUT_TOOL_AIRBRUSH: code = BTN_TOOL_AIRBRUSH; break;
> >> + case LIBINPUT_TOOL_FINGER: code = BTN_TOOL_FINGER; break;
> >> + case LIBINPUT_TOOL_MOUSE: code = BTN_TOOL_MOUSE; break;
> >> + case LIBINPUT_TOOL_LENS: code = BTN_TOOL_LENS; break;
> >> + default:
> >> + abort();
> >> + }
> >> +
> >> + return code;
> >> +}
> >> +
>
> Shouldn't this one be in evdev-tablet.h instead? (for consistency)
moved, thanks
Cheers,
Peter
> The rest looks good:
> Acked-by: Benjamin Tissoires <benjamin.tissoires at gmail.com>
>
> Cheers,
> Benjamin
>
> >> static void
> >> tablet_process_key(struct tablet_dispatch *tablet,
> >> struct evdev_device *device,
> >> @@ -869,6 +890,9 @@ tablet_flush(struct tablet_dispatch *tablet,
> >> tablet->current_tool_id,
> >> tablet->current_tool_serial);
> >>
> >> + if (tablet_has_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY))
> >> + return;
> >> +
> >> if (tablet_has_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY)) {
> >> /* Release all stylus buttons */
> >> memset(tablet->button_state.stylus_buttons,
> >> @@ -916,7 +940,11 @@ tablet_flush(struct tablet_dispatch *tablet,
> >>
> >> tablet_change_to_left_handed(device);
> >> }
> >> +}
> >>
> >> +static inline void
> >> +tablet_reset_state(struct tablet_dispatch *tablet)
> >> +{
> >> /* Update state */
> >> memcpy(&tablet->prev_button_state,
> >> &tablet->button_state,
> >> @@ -947,6 +975,7 @@ tablet_process(struct evdev_dispatch *dispatch,
> >> break;
> >> case EV_SYN:
> >> tablet_flush(tablet, device, time);
> >> + tablet_reset_state(tablet);
> >> break;
> >> default:
> >> log_error(device->base.seat->libinput,
> >> @@ -971,6 +1000,49 @@ tablet_destroy(struct evdev_dispatch *dispatch)
> >> free(tablet);
> >> }
> >>
> >> +static void
> >> +tablet_check_initial_proximity(struct evdev_device *device,
> >> + struct evdev_dispatch *dispatch)
> >> +{
> >> + bool tool_in_prox = false;
> >> + int code, state;
> >> + enum libinput_tool_type tool;
> >> + struct tablet_dispatch *tablet = (struct tablet_dispatch*)dispatch;
> >> +
> >> + for (tool = LIBINPUT_TOOL_PEN; tool <= LIBINPUT_TOOL_MAX; tool++) {
> >> + code = tablet_tool_to_evcode(tool);
> >> +
> >> + /* we only expect one tool to be in proximity at a time */
> >> + if (libevdev_fetch_event_value(device->evdev,
> >> + EV_KEY,
> >> + code,
> >> + &state) && state) {
> >> + tool_in_prox = true;
> >> + break;
> >> + }
> >> + }
> >> +
> >> + if (!tool_in_prox) {
> >> + tablet_set_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY);
> >> + return;
> >> + }
> >> +
> >> + tablet_update_tool(tablet, device, tool, state);
> >> +
> >> + tablet->current_tool_id =
> >> + libevdev_get_event_value(device->evdev,
> >> + EV_ABS,
> >> + ABS_MISC);
> >> + tablet->current_tool_serial =
> >> + libevdev_get_event_value(device->evdev,
> >> + EV_MSC,
> >> + MSC_SERIAL);
> >> +
> >> + tablet_flush(tablet,
> >> + device,
> >> + libinput_now(device->base.seat->libinput));
> >> +}
> >> +
> >> static struct evdev_dispatch_interface tablet_interface = {
> >> tablet_process,
> >> NULL, /* remove */
> >> @@ -980,6 +1052,7 @@ static struct evdev_dispatch_interface tablet_interface = {
> >> NULL, /* device_suspended */
> >> NULL, /* device_resumed */
> >> NULL, /* tag_device */
> >> + tablet_check_initial_proximity,
> >> };
> >>
> >> static int
> >> @@ -1002,9 +1075,6 @@ tablet_init(struct tablet_dispatch *tablet,
> >> }
> >>
> >> tablet_mark_all_axes_changed(tablet, device);
> >> -
> >> - tablet_set_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY);
> >> -
> >> return 0;
> >> }
> >>
> >> diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h
> >> index ea103b0..76a9677 100644
> >> --- a/src/evdev-tablet.h
> >> +++ b/src/evdev-tablet.h
> >> @@ -28,6 +28,7 @@
> >>
> >> #define LIBINPUT_TABLET_AXIS_NONE 0
> >> #define LIBINPUT_TOOL_NONE 0
> >> +#define LIBINPUT_TOOL_MAX LIBINPUT_TOOL_LENS
> >>
> >> enum tablet_status {
> >> TABLET_NONE = 0,
> >> diff --git a/src/evdev.c b/src/evdev.c
> >> index b90ea7c..2c4d1f1 100644
> >> --- a/src/evdev.c
> >> +++ b/src/evdev.c
> >> @@ -803,6 +803,7 @@ struct evdev_dispatch_interface fallback_interface = {
> >> NULL, /* device_suspended */
> >> NULL, /* device_resumed */
> >> fallback_tag_device,
> >> + NULL, /* post_added */
> >> };
> >>
> >> static uint32_t
> >> @@ -1592,6 +1593,10 @@ evdev_notify_added_device(struct evdev_device *device)
> >> }
> >>
> >> notify_added_device(&device->base);
> >> +
> >> + if (device->dispatch->interface->post_added)
> >> + device->dispatch->interface->post_added(device,
> >> + device->dispatch);
> >> }
> >>
> >> static int
> >> diff --git a/src/evdev.h b/src/evdev.h
> >> index 7469675..26f321e 100644
> >> --- a/src/evdev.h
> >> +++ b/src/evdev.h
> >> @@ -196,6 +196,11 @@ struct evdev_dispatch_interface {
> >> /* Tag device with one of EVDEV_TAG */
> >> void (*tag_device)(struct evdev_device *device,
> >> struct udev_device *udev_device);
> >> +
> >> + /* Called immediately after the LIBINPUT_EVENT_DEVICE_ADDED event
> >> + * was sent */
> >> + void (*post_added)(struct evdev_device *device,
> >> + struct evdev_dispatch *dispatch);
> >> };
> >>
> >> struct evdev_dispatch {
> >> diff --git a/test/tablet.c b/test/tablet.c
> >> index d7486cb..ba61e0e 100644
> >> --- a/test/tablet.c
> >> +++ b/test/tablet.c
> >> @@ -1157,6 +1157,58 @@ START_TEST(tool_capabilities)
> >> }
> >> END_TEST
> >>
> >> +START_TEST(tool_in_prox_before_start)
> >> +{
> >> + struct libinput *li;
> >> + struct litest_device *dev = litest_current_device();
> >> + struct libinput_event *event;
> >> + struct axis_replacement axes[] = {
> >> + { ABS_DISTANCE, 10 },
> >> + { ABS_TILT_X, 0 },
> >> + { ABS_TILT_Y, 0 },
> >> + { -1, -1 }
> >> + };
> >> + const char *devnode;
> >> +
> >> + litest_tablet_proximity_in(dev, 10, 10, axes);
> >> +
> >> + /* for simplicity, we create a new litest context */
> >> + devnode = libevdev_uinput_get_devnode(dev->uinput);
> >> + li = litest_create_context();
> >> + libinput_path_add_device(li, devnode);
> >> +
> >> + litest_wait_for_event_of_type(li,
> >> + LIBINPUT_EVENT_DEVICE_ADDED,
> >> + -1);
> >> + event = libinput_get_event(li);
> >> + libinput_event_destroy(event);
> >> +
> >> + litest_wait_for_event_of_type(li,
> >> + LIBINPUT_EVENT_TABLET_PROXIMITY,
> >> + -1);
> >> + event = libinput_get_event(li);
> >> + libinput_event_destroy(event);
> >> + litest_assert_empty_queue(li);
> >> +
> >> + litest_tablet_motion(dev, 10, 20, axes);
> >> + litest_tablet_motion(dev, 30, 40, axes);
> >> +
> >> + litest_assert_only_typed_events(li, LIBINPUT_EVENT_TABLET_AXIS);
> >> + litest_assert_empty_queue(li);
> >> + litest_event(dev, EV_KEY, BTN_STYLUS, 1);
> >> + litest_event(dev, EV_SYN, SYN_REPORT, 0);
> >> + litest_event(dev, EV_KEY, BTN_STYLUS, 1);
> >> + litest_event(dev, EV_SYN, SYN_REPORT, 0);
> >> + litest_assert_only_typed_events(li, LIBINPUT_EVENT_TABLET_BUTTON);
> >> + litest_tablet_proximity_out(dev);
> >> +
> >> + litest_wait_for_event_of_type(li,
> >> + LIBINPUT_EVENT_TABLET_PROXIMITY,
> >> + -1);
> >> + libinput_unref(li);
> >> +}
> >> +END_TEST
> >> +
> >> START_TEST(mouse_tool)
> >> {
> >> struct litest_device *dev = litest_current_device();
> >> @@ -1615,6 +1667,7 @@ main(int argc, char **argv)
> >> {
> >> litest_add("tablet:tool", tool_ref, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
> >> litest_add_no_device("tablet:tool", tool_capabilities);
> >> + litest_add("tablet:tool", tool_in_prox_before_start, LITEST_TABLET, LITEST_ANY);
> >> litest_add("tablet:tool_serial", tool_serial, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
> >> litest_add("tablet:tool_serial", serial_changes_tool, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
> >> litest_add("tablet:tool_serial", invalid_serials, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
> >> --
> >> 2.1.0
> >>
More information about the wayland-devel
mailing list