On Mon, Mar 2, 2015 at 7:59 PM, Peter Hutterer <peter.hutte...@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. > * if the tool was in proximity (with an evdev client attached), but goes out > of proximity and back in with no client connected, we get an immediate > proximity out event from the kernel once we connect to the device and no > further events after that. This has been fixed in b905811a49bcd6e6726ce5bbb591f57aaddfd3be in Linus' tree, so this is in v3.19 and above. I guess the fact that no events are sent after the prox in event means that this one does not affect the Bamboos either. Cheers, Benjamin PS: tomorrow for the review, not tonight :) > > Otherwise, things work as expected. The above should be fixed in the kernel > anyway. > > Note that this changes the order of events during a udev seat init, before we > had all DEVICE_ADDED events in a row, now the proximity event may be > interspersed. > > Reported-by: Jason Gerecke <killert...@gmail.com> > Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net> > --- > src/evdev-mt-touchpad.c | 1 + > src/evdev-tablet.c | 78 > ++++++++++++++++++++++++++++++++++++++++++++++--- > src/evdev-tablet.h | 1 + > src/evdev.c | 5 ++++ > src/evdev.h | 5 ++++ > test/tablet.c | 53 +++++++++++++++++++++++++++++++++ > 6 files changed, 139 insertions(+), 4 deletions(-) > > diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c > index b90d84c..b3a8b08 100644 > --- a/src/evdev-mt-touchpad.c > +++ b/src/evdev-mt-touchpad.c > @@ -897,6 +897,7 @@ static struct evdev_dispatch_interface tp_interface = { > tp_device_removed, /* device_suspended, treat as remove */ > tp_device_added, /* device_resumed, treat as add */ > tp_tag_device, > + NULL, /* post_added */ > }; > > static void > diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c > index 6d3b9b7..12cca79 100644 > --- a/src/evdev-tablet.c > +++ b/src/evdev-tablet.c > @@ -190,7 +190,7 @@ tablet_update_tool(struct tablet_dispatch *tablet, > tablet_set_status(tablet, TABLET_TOOL_ENTERING_PROXIMITY); > tablet_unset_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY); > } > - else > + else if (!tablet_has_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY)) > tablet_set_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY); > } > > @@ -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; > +} > + > 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 > _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel