[PATCH v2 libinput 6/6] tablet: add touch arbitration
Jason Gerecke
killertofu at gmail.com
Tue Sep 6 18:21:42 UTC 2016
On 09/05/2016 06:04 PM, Peter Hutterer wrote:
> So far we've relied on the wacom kernel module to do touch arbitration for us
> but that won't be the case in upcoming kernels. Implement touch arbitration in
> userspace by pairing the two devices and suspending the touch device whenever
> a tool comes into proximity.
>
> In the future more sophisticated arbitration can be done (e.g. only touches
> which are close to the pen) but let's burn that bridge when we have to cross
> it.
>
> Note that touch arbitration is "device suspend light", i.e. we leave the
> device enabled and the fd is active. Tablet interactions are comparatively
> short-lived, so closing the fd and asking logind for a new one every time the
> pen changes proximity is suboptimal. Instead, we just keep a boolean around
> and discard all events while it is set.
>
> Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
The revised series looks good to me -- thanks again :)
Reviewed-by: Jason Gerecke <jason.gerecke at wacom.com>
Jason
---
Now instead of four in the eights place /
you’ve got three, ‘Cause you added one /
(That is to say, eight) to the two, /
But you can’t take seven from three, /
So you look at the sixty-fours....
> ---
> Changes to v1:
> - drop the previous evdev_device_suspend() approach and use a ignore_events
> boolean in the dispatch instead.
> - add test for suspending/resuming the touch device during arbitration
> - use a common helper for each arbitration test. the tests only differ in
> the second device created and what events we expect so let's re-use
> everything else
>
> doc/tablet-support.dox | 13 ++
> src/evdev-mt-touchpad.c | 21 +++
> src/evdev-mt-touchpad.h | 4 +
> src/evdev-tablet-pad.c | 1 +
> src/evdev-tablet.c | 80 ++++++++++-
> src/evdev-tablet.h | 3 +
> src/evdev.c | 21 +++
> src/evdev.h | 8 ++
> test/tablet.c | 344 ++++++++++++++++++++++++++++++++++++++++++++++++
> 9 files changed, 492 insertions(+), 3 deletions(-)
>
> diff --git a/doc/tablet-support.dox b/doc/tablet-support.dox
> index cda0d70..19c5d8f 100644
> --- a/doc/tablet-support.dox
> +++ b/doc/tablet-support.dox
> @@ -331,4 +331,17 @@ button and ring events on the right. When one of the three mode toggle
> buttons on the right is pressed, the right mode switches to that button's
> mode but the left mode remains unchanged.
>
> + at section tablet-touch-arbitration Tablet touch arbitration
> +
> +"Touch arbitration" is the terminology used when touch events are suppressed
> +while the pen is in proximity. Since it is almost impossible to use a stylus
> +or other tool without triggering touches with the hand holding the tool,
> +touch arbitration serves to reduce the number of accidental inputs.
> +The wacom kernel driver currently provides touch arbitration but for other
> +devices arbitration has to be done in userspace.
> +
> +libinput uses the @ref libinput_device_group to decide on touch arbitration
> +and automatically discards touch events whenever a tool is in proximity.
> +The exact behavior is device-dependent.
> +
> */
> diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
> index 65b0abf..2354061 100644
> --- a/src/evdev-mt-touchpad.c
> +++ b/src/evdev-mt-touchpad.c
> @@ -1165,6 +1165,9 @@ tp_interface_process(struct evdev_dispatch *dispatch,
> struct tp_dispatch *tp =
> (struct tp_dispatch *)dispatch;
>
> + if (tp->ignore_events)
> + return;
> +
> switch (e->type) {
> case EV_ABS:
> if (tp->has_mt)
> @@ -1679,6 +1682,23 @@ evdev_tag_touchpad(struct evdev_device *device,
> }
> }
>
> +static void
> +tp_interface_toggle_touch(struct evdev_dispatch *dispatch,
> + struct evdev_device *device,
> + bool enable)
> +{
> + struct tp_dispatch *tp = (struct tp_dispatch*)dispatch;
> + bool ignore_events = !enable;
> +
> + if (ignore_events == tp->ignore_events)
> + return;
> +
> + if (ignore_events)
> + tp_clear_state(tp);
> +
> + tp->ignore_events = ignore_events;
> +}
> +
> static struct evdev_dispatch_interface tp_interface = {
> tp_interface_process,
> tp_interface_suspend,
> @@ -1689,6 +1709,7 @@ static struct evdev_dispatch_interface tp_interface = {
> tp_interface_device_removed, /* device_suspended, treat as remove */
> tp_interface_device_added, /* device_resumed, treat as add */
> NULL, /* post_added */
> + tp_interface_toggle_touch,
> };
>
> static void
> diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
> index 8a8d2db..de9bdb5 100644
> --- a/src/evdev-mt-touchpad.h
> +++ b/src/evdev-mt-touchpad.h
> @@ -231,6 +231,10 @@ struct tp_dispatch {
> bool semi_mt;
> bool reports_distance; /* does the device support true hovering */
>
> + /* true if we're reading events (i.e. not suspended) but we're
> + * ignoring them */
> + bool ignore_events;
> +
> unsigned int num_slots; /* number of slots */
> unsigned int ntouches; /* no slots inc. fakes */
> struct tp_touch *touches; /* len == ntouches */
> diff --git a/src/evdev-tablet-pad.c b/src/evdev-tablet-pad.c
> index 0e95408..82542bc 100644
> --- a/src/evdev-tablet-pad.c
> +++ b/src/evdev-tablet-pad.c
> @@ -512,6 +512,7 @@ static struct evdev_dispatch_interface pad_interface = {
> NULL, /* device_suspended */
> NULL, /* device_resumed */
> NULL, /* post_added */
> + NULL, /* toggle_touch */
> };
>
> static void
> diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c
> index 254d669..14023b6 100644
> --- a/src/evdev-tablet.c
> +++ b/src/evdev-tablet.c
> @@ -1434,6 +1434,39 @@ tablet_flush(struct tablet_dispatch *tablet,
> }
>
> static inline void
> +tablet_set_touch_device_enabled(struct evdev_device *touch_device,
> + bool enable)
> +{
> + struct evdev_dispatch *dispatch;
> +
> + if (touch_device == NULL)
> + return;
> +
> + dispatch = touch_device->dispatch;
> + if (dispatch->interface->toggle_touch)
> + dispatch->interface->toggle_touch(dispatch,
> + touch_device,
> + enable);
> +}
> +
> +static inline void
> +tablet_toggle_touch_device(struct tablet_dispatch *tablet,
> + struct evdev_device *tablet_device)
> +{
> + bool enable_events;
> +
> + enable_events = tablet_has_status(tablet,
> + TABLET_TOOL_OUT_OF_RANGE) ||
> + tablet_has_status(tablet, TABLET_NONE) ||
> + tablet_has_status(tablet,
> + TABLET_TOOL_LEAVING_PROXIMITY) ||
> + tablet_has_status(tablet,
> + TABLET_TOOL_OUT_OF_PROXIMITY);
> +
> + tablet_set_touch_device_enabled(tablet->touch_device, enable_events);
> +}
> +
> +static inline void
> tablet_reset_state(struct tablet_dispatch *tablet)
> {
> /* Update state */
> @@ -1466,6 +1499,7 @@ tablet_process(struct evdev_dispatch *dispatch,
> break;
> case EV_SYN:
> tablet_flush(tablet, device, time);
> + tablet_toggle_touch_device(tablet, device);
> tablet_reset_state(tablet);
> break;
> default:
> @@ -1478,6 +1512,16 @@ tablet_process(struct evdev_dispatch *dispatch,
> }
>
> static void
> +tablet_suspend(struct evdev_dispatch *dispatch,
> + struct evdev_device *device)
> +{
> + struct tablet_dispatch *tablet =
> + (struct tablet_dispatch *)dispatch;
> +
> + tablet_set_touch_device_enabled(tablet->touch_device, true);
> +}
> +
> +static void
> tablet_destroy(struct evdev_dispatch *dispatch)
> {
> struct tablet_dispatch *tablet =
> @@ -1492,6 +1536,35 @@ tablet_destroy(struct evdev_dispatch *dispatch)
> }
>
> static void
> +tablet_device_added(struct evdev_device *device,
> + struct evdev_device *added_device)
> +{
> + struct tablet_dispatch *tablet =
> + (struct tablet_dispatch*)device->dispatch;
> +
> + if (libinput_device_get_device_group(&device->base) !=
> + libinput_device_get_device_group(&added_device->base))
> + return;
> +
> + /* Touch screens or external touchpads only */
> + if (evdev_device_has_capability(added_device, LIBINPUT_DEVICE_CAP_TOUCH) ||
> + (evdev_device_has_capability(added_device, LIBINPUT_DEVICE_CAP_POINTER) &&
> + (added_device->tags & EVDEV_TAG_EXTERNAL_TOUCHPAD)))
> + tablet->touch_device = added_device;
> +}
> +
> +static void
> +tablet_device_removed(struct evdev_device *device,
> + struct evdev_device *removed_device)
> +{
> + struct tablet_dispatch *tablet =
> + (struct tablet_dispatch*)device->dispatch;
> +
> + if (tablet->touch_device == removed_device)
> + tablet->touch_device = NULL;
> +}
> +
> +static void
> tablet_check_initial_proximity(struct evdev_device *device,
> struct evdev_dispatch *dispatch)
> {
> @@ -1532,14 +1605,15 @@ tablet_check_initial_proximity(struct evdev_device *device,
>
> static struct evdev_dispatch_interface tablet_interface = {
> tablet_process,
> - NULL, /* suspend */
> + tablet_suspend,
> NULL, /* remove */
> tablet_destroy,
> - NULL, /* device_added */
> - NULL, /* device_removed */
> + tablet_device_added,
> + tablet_device_removed,
> NULL, /* device_suspended */
> NULL, /* device_resumed */
> tablet_check_initial_proximity,
> + NULL, /* toggle_touch */
> };
>
> static void
> diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h
> index f66de5d..2279e03 100644
> --- a/src/evdev-tablet.h
> +++ b/src/evdev-tablet.h
> @@ -71,6 +71,9 @@ struct tablet_dispatch {
> uint32_t cursor_proximity_threshold;
>
> struct libinput_device_config_calibration calibration;
> +
> + /* The paired touch device on devices with both pen & touch */
> + struct evdev_device *touch_device;
> };
>
> static inline enum libinput_tablet_tool_axis
> diff --git a/src/evdev.c b/src/evdev.c
> index 3b48c3e..03384c8 100644
> --- a/src/evdev.c
> +++ b/src/evdev.c
> @@ -1055,6 +1055,9 @@ fallback_process(struct evdev_dispatch *evdev_dispatch,
> struct fallback_dispatch *dispatch = (struct fallback_dispatch*)evdev_dispatch;
> enum evdev_event_type sent;
>
> + if (dispatch->ignore_events)
> + return;
> +
> switch (event->type) {
> case EV_REL:
> fallback_process_relative(dispatch, device, event, time);
> @@ -1184,6 +1187,23 @@ fallback_suspend(struct evdev_dispatch *evdev_dispatch,
> }
>
> static void
> +fallback_toggle_touch(struct evdev_dispatch *evdev_dispatch,
> + struct evdev_device *device,
> + bool enable)
> +{
> + struct fallback_dispatch *dispatch = (struct fallback_dispatch*)evdev_dispatch;
> + bool ignore_events = !enable;
> +
> + if (ignore_events == dispatch->ignore_events)
> + return;
> +
> + if (ignore_events)
> + fallback_return_to_neutral_state(dispatch, device);
> +
> + dispatch->ignore_events = ignore_events;
> +}
> +
> +static void
> fallback_destroy(struct evdev_dispatch *evdev_dispatch)
> {
> struct fallback_dispatch *dispatch = (struct fallback_dispatch*)evdev_dispatch;
> @@ -1243,6 +1263,7 @@ struct evdev_dispatch_interface fallback_interface = {
> NULL, /* device_suspended */
> NULL, /* device_resumed */
> NULL, /* post_added */
> + fallback_toggle_touch, /* toggle_touch */
> };
>
> static uint32_t
> diff --git a/src/evdev.h b/src/evdev.h
> index 10b0e58..b240615 100644
> --- a/src/evdev.h
> +++ b/src/evdev.h
> @@ -265,6 +265,10 @@ struct evdev_dispatch_interface {
> * was sent */
> void (*post_added)(struct evdev_device *device,
> struct evdev_dispatch *dispatch);
> +
> + void (*toggle_touch)(struct evdev_dispatch *dispatch,
> + struct evdev_device *device,
> + bool enable);
> };
>
> struct evdev_dispatch {
> @@ -308,6 +312,10 @@ struct fallback_dispatch {
> unsigned long hw_key_mask[NLONGS(KEY_CNT)];
>
> enum evdev_event_type pending_event;
> +
> + /* true if we're reading events (i.e. not suspended) but we're
> + ignoring them */
> + bool ignore_events;
> };
>
> struct evdev_device *
> diff --git a/test/tablet.c b/test/tablet.c
> index 30588a4..212ef0c 100644
> --- a/test/tablet.c
> +++ b/test/tablet.c
> @@ -3767,6 +3767,338 @@ START_TEST(relative_calibration)
> }
> END_TEST
>
> +static void
> +touch_arbitration(struct litest_device *dev,
> + enum litest_device_type other,
> + bool is_touchpad)
> +{
> + struct litest_device *finger;
> + struct libinput *li = dev->libinput;
> + struct axis_replacement axes[] = {
> + { ABS_DISTANCE, 10 },
> + { ABS_PRESSURE, 0 },
> + { -1, -1 }
> + };
> +
> + finger = litest_add_device(li, other);
> + litest_drain_events(li);
> +
> + litest_tablet_proximity_in(dev, 10, 10, axes);
> + litest_tablet_motion(dev, 10, 10, axes);
> + litest_tablet_motion(dev, 20, 40, axes);
> + litest_drain_events(li);
> +
> + litest_touch_down(finger, 0, 30, 30);
> + litest_touch_move_to(finger, 0, 30, 30, 80, 80, 10, 1);
> + litest_assert_empty_queue(li);
> +
> + litest_tablet_motion(dev, 10, 10, axes);
> + litest_tablet_motion(dev, 20, 40, axes);
> + litest_assert_only_typed_events(li,
> + LIBINPUT_EVENT_TABLET_TOOL_AXIS);
> + litest_tablet_proximity_out(dev);
> + litest_assert_only_typed_events(li,
> + LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
> +
> + /* finger still down */
> + litest_touch_move_to(finger, 0, 80, 80, 30, 30, 10, 1);
> + litest_touch_up(finger, 0);
> + litest_assert_empty_queue(li);
> +
> + /* lift finger, expect expect events */
> + litest_touch_down(finger, 0, 30, 30);
> + litest_touch_move_to(finger, 0, 30, 30, 80, 80, 10, 1);
> + litest_touch_up(finger, 0);
> + libinput_dispatch(li);
> +
> + if (is_touchpad)
> + litest_assert_only_typed_events(li,
> + LIBINPUT_EVENT_POINTER_MOTION);
> + else
> + litest_assert_touch_sequence(li);
> +
> + litest_delete_device(finger);
> +}
> +
> +START_TEST(intuos_touch_arbitration)
> +{
> + touch_arbitration(litest_current_device(), LITEST_WACOM_FINGER, true);
> +}
> +END_TEST
> +
> +START_TEST(cintiq_touch_arbitration)
> +{
> + touch_arbitration(litest_current_device(),
> + LITEST_WACOM_CINTIQ_13HDT_FINGER,
> + false);
> +}
> +END_TEST
> +
> +static void
> +touch_arbitration_stop_touch(struct litest_device *dev,
> + enum litest_device_type other,
> + bool is_touchpad)
> +{
> + struct litest_device *finger;
> + struct libinput *li = dev->libinput;
> + struct axis_replacement axes[] = {
> + { ABS_DISTANCE, 10 },
> + { ABS_PRESSURE, 0 },
> + { -1, -1 }
> + };
> +
> + finger = litest_add_device(li, other);
> + litest_touch_down(finger, 0, 30, 30);
> + litest_touch_move_to(finger, 0, 30, 30, 80, 80, 10, 1);
> +
> + litest_tablet_proximity_in(dev, 10, 10, axes);
> + litest_tablet_motion(dev, 10, 10, axes);
> + litest_tablet_motion(dev, 20, 40, axes);
> + litest_drain_events(li);
> +
> + litest_touch_move_to(finger, 0, 80, 80, 30, 30, 10, 1);
> + /* start another finger to make sure that one doesn't send events
> + either */
> + litest_touch_down(finger, 1, 30, 30);
> + litest_touch_move_to(finger, 1, 30, 30, 80, 80, 10, 1);
> + litest_assert_empty_queue(li);
> +
> + litest_tablet_motion(dev, 10, 10, axes);
> + litest_tablet_motion(dev, 20, 40, axes);
> + litest_assert_only_typed_events(li,
> + LIBINPUT_EVENT_TABLET_TOOL_AXIS);
> + litest_tablet_proximity_out(dev);
> + litest_drain_events(li);
> +
> + /* Finger needs to be lifted for events to happen*/
> + litest_touch_move_to(finger, 0, 30, 30, 80, 80, 10, 1);
> + litest_assert_empty_queue(li);
> + litest_touch_move_to(finger, 1, 80, 80, 30, 30, 10, 1);
> + litest_assert_empty_queue(li);
> + litest_touch_up(finger, 0);
> + litest_touch_move_to(finger, 1, 30, 30, 80, 80, 10, 1);
> + litest_assert_empty_queue(li);
> + litest_touch_up(finger, 1);
> + litest_touch_down(finger, 0, 30, 30);
> + litest_touch_move_to(finger, 0, 30, 30, 80, 80, 10, 1);
> + litest_touch_up(finger, 0);
> + libinput_dispatch(li);
> +
> + if (is_touchpad)
> + litest_assert_only_typed_events(li,
> + LIBINPUT_EVENT_POINTER_MOTION);
> + else
> + litest_assert_touch_sequence(li);
> +
> + litest_delete_device(finger);
> + litest_assert_only_typed_events(li, LIBINPUT_EVENT_DEVICE_REMOVED);
> +}
> +
> +START_TEST(intuos_touch_arbitration_stop_touch)
> +{
> + touch_arbitration_stop_touch(litest_current_device(),
> + LITEST_WACOM_FINGER,
> + true);
> +}
> +END_TEST
> +
> +START_TEST(cintiq_touch_arbitration_stop_touch)
> +{
> + touch_arbitration_stop_touch(litest_current_device(),
> + LITEST_WACOM_CINTIQ_13HDT_FINGER,
> + false);
> +}
> +END_TEST
> +
> +static void
> +touch_arbitration_suspend_touch(struct litest_device *dev,
> + enum litest_device_type other,
> + bool is_touchpad)
> +{
> + struct litest_device *tablet;
> + struct libinput *li = dev->libinput;
> + enum libinput_config_status status;
> + struct axis_replacement axes[] = {
> + { ABS_DISTANCE, 10 },
> + { ABS_PRESSURE, 0 },
> + { -1, -1 }
> + };
> +
> + tablet = litest_add_device(li, other);
> +
> + /* we can't force a device suspend, but we can at least make sure
> + the device doesn't send events */
> + status = libinput_device_config_send_events_set_mode(
> + dev->libinput_device,
> + LIBINPUT_CONFIG_SEND_EVENTS_DISABLED);
> + ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
> +
> + litest_drain_events(li);
> +
> + litest_tablet_proximity_in(tablet, 10, 10, axes);
> + litest_tablet_motion(tablet, 10, 10, axes);
> + litest_tablet_motion(tablet, 20, 40, axes);
> + litest_drain_events(li);
> +
> + litest_touch_down(dev, 0, 30, 30);
> + litest_touch_move_to(dev, 0, 30, 30, 80, 80, 10, 1);
> + litest_touch_up(dev, 0);
> + litest_assert_empty_queue(li);
> +
> + /* Remove tablet device to unpair, still disabled though */
> + litest_delete_device(tablet);
> + litest_assert_only_typed_events(li, LIBINPUT_EVENT_DEVICE_REMOVED);
> +
> + litest_touch_down(dev, 0, 30, 30);
> + litest_touch_move_to(dev, 0, 30, 30, 80, 80, 10, 1);
> + litest_touch_up(dev, 0);
> + litest_assert_empty_queue(li);
> +
> + /* Touch device is still disabled */
> + litest_touch_down(dev, 0, 30, 30);
> + litest_touch_move_to(dev, 0, 30, 30, 80, 80, 10, 1);
> + litest_touch_up(dev, 0);
> + litest_assert_empty_queue(li);
> +
> + status = libinput_device_config_send_events_set_mode(
> + dev->libinput_device,
> + LIBINPUT_CONFIG_SEND_EVENTS_ENABLED);
> + ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
> +
> + litest_touch_down(dev, 0, 30, 30);
> + litest_touch_move_to(dev, 0, 30, 30, 80, 80, 10, 1);
> + litest_touch_up(dev, 0);
> + libinput_dispatch(li);
> +
> + if (is_touchpad)
> + litest_assert_only_typed_events(li,
> + LIBINPUT_EVENT_POINTER_MOTION);
> + else
> + litest_assert_touch_sequence(li);
> +}
> +
> +START_TEST(intuos_touch_arbitration_suspend_touch_device)
> +{
> + touch_arbitration_suspend_touch(litest_current_device(),
> + LITEST_WACOM_INTUOS,
> + true);
> +}
> +END_TEST
> +
> +START_TEST(cintiq_touch_arbitration_suspend_touch_device)
> +{
> + touch_arbitration_suspend_touch(litest_current_device(),
> + LITEST_WACOM_CINTIQ_13HDT_PEN,
> + false);
> +}
> +END_TEST
> +
> +static void
> +touch_arbitration_remove_touch(struct litest_device *dev,
> + enum litest_device_type other,
> + bool is_touchpad)
> +{
> + struct litest_device *finger;
> + struct libinput *li = dev->libinput;
> + struct axis_replacement axes[] = {
> + { ABS_DISTANCE, 10 },
> + { ABS_PRESSURE, 0 },
> + { -1, -1 }
> + };
> +
> + finger = litest_add_device(li, other);
> + litest_touch_down(finger, 0, 30, 30);
> + litest_touch_move_to(finger, 0, 30, 30, 80, 80, 10, 1);
> +
> + litest_tablet_proximity_in(dev, 10, 10, axes);
> + litest_drain_events(li);
> +
> + litest_delete_device(finger);
> + libinput_dispatch(li);
> + litest_assert_only_typed_events(li, LIBINPUT_EVENT_DEVICE_REMOVED);
> + litest_assert_empty_queue(li);
> +
> + litest_tablet_motion(dev, 10, 10, axes);
> + litest_tablet_motion(dev, 20, 40, axes);
> + litest_assert_only_typed_events(li,
> + LIBINPUT_EVENT_TABLET_TOOL_AXIS);
> +}
> +
> +START_TEST(intuos_touch_arbitration_remove_touch)
> +{
> + touch_arbitration_remove_touch(litest_current_device(),
> + LITEST_WACOM_INTUOS,
> + true);
> +}
> +END_TEST
> +
> +START_TEST(cintiq_touch_arbitration_remove_touch)
> +{
> + touch_arbitration_remove_touch(litest_current_device(),
> + LITEST_WACOM_CINTIQ_13HDT_FINGER,
> + false);
> +}
> +END_TEST
> +
> +static void
> +touch_arbitration_remove_tablet(struct litest_device *dev,
> + enum litest_device_type other,
> + bool is_touchpad)
> +{
> + struct litest_device *tablet;
> + struct libinput *li = dev->libinput;
> + struct axis_replacement axes[] = {
> + { ABS_DISTANCE, 10 },
> + { ABS_PRESSURE, 0 },
> + { -1, -1 }
> + };
> +
> + tablet = litest_add_device(li, other);
> + libinput_dispatch(li);
> + litest_tablet_proximity_in(tablet, 10, 10, axes);
> + litest_tablet_motion(tablet, 10, 10, axes);
> + litest_tablet_motion(tablet, 20, 40, axes);
> + litest_drain_events(li);
> +
> + litest_touch_down(dev, 0, 30, 30);
> + litest_touch_move_to(dev, 0, 30, 30, 80, 80, 10, 1);
> + litest_assert_empty_queue(li);
> +
> + litest_delete_device(tablet);
> + litest_assert_only_typed_events(li, LIBINPUT_EVENT_DEVICE_REMOVED);
> +
> + /* Touch is still down, don't enable */
> + litest_touch_move_to(dev, 0, 80, 80, 30, 30, 10, 1);
> + litest_touch_up(dev, 0);
> + litest_assert_empty_queue(li);
> +
> + litest_touch_down(dev, 0, 30, 30);
> + litest_touch_move_to(dev, 0, 30, 30, 80, 80, 10, 1);
> + litest_touch_up(dev, 0);
> + libinput_dispatch(li);
> +
> + if (is_touchpad)
> + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
> + else
> + litest_assert_touch_sequence(li);
> +}
> +
> +START_TEST(intuos_touch_arbitration_remove_tablet)
> +{
> + touch_arbitration_remove_tablet(litest_current_device(),
> + LITEST_WACOM_INTUOS,
> + true);
> +}
> +END_TEST
> +
> +START_TEST(cintiq_touch_arbitration_remove_tablet)
> +{
> + touch_arbitration_remove_tablet(litest_current_device(),
> + LITEST_WACOM_CINTIQ_13HDT_PEN,
> + false);
> +}
> +END_TEST
> +
> void
> litest_setup_tests_tablet(void)
> {
> @@ -3844,4 +4176,16 @@ litest_setup_tests_tablet(void)
> litest_add("tablet:relative", relative_no_delta_prox_in, LITEST_TABLET, LITEST_ANY);
> litest_add("tablet:relative", relative_delta, LITEST_TABLET, LITEST_ANY);
> litest_add("tablet:relative", relative_calibration, LITEST_TABLET, LITEST_ANY);
> +
> + litest_add_for_device("tablet:touch-arbitration", intuos_touch_arbitration, LITEST_WACOM_INTUOS);
> + litest_add_for_device("tablet:touch-arbitration", intuos_touch_arbitration_stop_touch, LITEST_WACOM_INTUOS);
> + litest_add_for_device("tablet:touch-arbitration", intuos_touch_arbitration_suspend_touch_device, LITEST_WACOM_FINGER);
> + litest_add_for_device("tablet:touch-arbitration", intuos_touch_arbitration_remove_touch, LITEST_WACOM_INTUOS);
> + litest_add_for_device("tablet:touch-arbitration", intuos_touch_arbitration_remove_tablet, LITEST_WACOM_FINGER);
> +
> + litest_add_for_device("tablet:touch-arbitration", cintiq_touch_arbitration, LITEST_WACOM_CINTIQ_13HDT_PEN);
> + litest_add_for_device("tablet:touch-arbitration", cintiq_touch_arbitration_stop_touch, LITEST_WACOM_CINTIQ_13HDT_PEN);
> + litest_add_for_device("tablet:touch-arbitration", cintiq_touch_arbitration_suspend_touch_device, LITEST_WACOM_CINTIQ_13HDT_FINGER);
> + litest_add_for_device("tablet:touch-arbitration", cintiq_touch_arbitration_remove_touch, LITEST_WACOM_CINTIQ_13HDT_PEN);
> + litest_add_for_device("tablet:touch-arbitration", cintiq_touch_arbitration_remove_tablet, LITEST_WACOM_CINTIQ_13HDT_FINGER);
> }
>
More information about the wayland-devel
mailing list