[PATCH v2 libinput] tablet: support tool-specific pressure offsets

Peter Hutterer peter.hutterer at who-t.net
Thu Dec 10 21:01:14 PST 2015


On Thu, Dec 10, 2015 at 06:50:55PM -0800, Ping Cheng wrote:
> On Thu, Dec 10, 2015 at 1:31 AM, Peter Hutterer
> <peter.hutterer at who-t.net> wrote:
> > If a tool wears out, it may have a pre-loaded pressure offset. In that case,
> > even when the tool is not physically in contact with the tablet surface it
> > will send pressure events.
> >
> > Use automatic pressure offset detection, similar to what the X.Org wacom
> > driver does. On proximity-in, check the pressure and if the distance is above
> > 50% of the range and the pressure is nonzero but below 20% of the range, use
> > that value as pressure offset.
> >
> > Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
> 
> Patch looks good to me.
> 
> Reviewed-by: Ping Cheng <pingc at wacom.com>

thanks, much appreciated
> 
> Cheers,
> 
> Ping
> 
> PS, some users may want to use their tools until the pre-loaded
> pressure reached 80% or more. But, that's their problems :-).
> 
> PPS, I remember somewhere you mentioned libinput doesn't support
> click/pressure threshold. When do we send left button down event?

atm we're just using BTN_TOUCH for the tip down/up events, but I've got this
on my todo list.

Cheers,
   Peter

> 
> > ---
> > Changes to v1:
> > - don't use a static udev property, try to detect the offset on proximity in
> >
> >  doc/tablet-support.dox                   |  29 +++
> >  src/evdev-tablet.c                       |  84 ++++++++-
> >  src/evdev-tablet.h                       |  21 +++
> >  src/libinput-private.h                   |   2 +
> >  test/litest-device-wacom-intuos-tablet.c |   1 +
> >  test/tablet.c                            | 313 ++++++++++++++++++++++++++++++-
> >  6 files changed, 446 insertions(+), 4 deletions(-)
> >
> > diff --git a/doc/tablet-support.dox b/doc/tablet-support.dox
> > index 24d08d2..5468c6f 100644
> > --- a/doc/tablet-support.dox
> > +++ b/doc/tablet-support.dox
> > @@ -92,4 +92,33 @@ if (value < min) {
> >  }
> >  @endcode
> >
> > + at section tablet-pressure-offset Pressure offset on worn-out tools
> > +
> > +When a tool is used for an extended period it can wear down physically. A
> > +worn-down tool may never return a zero pressure value. Even when hovering
> > +above the surface, the pressure value returned by the tool is nonzero,
> > +creating a fake surface touch and making interaction with the tablet less
> > +predictable.
> > +
> > +libinput automatically detects pressure offsets and rescales the remaining
> > +pressure range into the available range, making pressure-offsets transparent
> > +to the caller. A tool with a pressure offset will thus send a 0 pressure
> > +value for the detected offset and nonzero pressure values for values higher
> > +than that offset.
> > +
> > +Some limitations apply to avoid misdetection of pressure offsets,
> > +specifically:
> > +- pressure offset is only detected on proximity in, and if a device is
> > +  capable of detection distances,
> > +- pressure offset is only detected if the distance between the tool and the
> > +  tablet is high enough,
> > +- pressure offset is only used if it is 20% or less of the pressure range
> > +  available to the tool. A pressure offset higher than 20% indicates either
> > +  a misdetection or a tool that should be replaced, and
> > +- if a pressure value less than the current pressure offset is seen, the
> > +  offset resets to that value.
> > +
> > +Pressure offsets are not detected on @ref LIBINPUT_TABLET_TOOL_TYPE_MOUSE
> > +and @ref LIBINPUT_TABLET_TOOL_TYPE_LENS tools.
> > +
> >  */
> > diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c
> > index cd208a8..909cc76 100644
> > --- a/src/evdev-tablet.c
> > +++ b/src/evdev-tablet.c
> > @@ -21,9 +21,11 @@
> >   * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >   */
> >  #include "config.h"
> > +#include "libinput-version.h"
> >  #include "evdev-tablet.h"
> >
> >  #include <assert.h>
> > +#include <inttypes.h>
> >  #include <stdbool.h>
> >  #include <string.h>
> >
> > @@ -202,7 +204,7 @@ tablet_update_tool(struct tablet_dispatch *tablet,
> >  }
> >
> >  static inline double
> > -normalize_pressure_dist_slider(const struct input_absinfo *absinfo)
> > +normalize_dist_slider(const struct input_absinfo *absinfo)
> >  {
> >         double range = absinfo->maximum - absinfo->minimum;
> >         double value = (absinfo->value - absinfo->minimum) / range;
> > @@ -211,6 +213,18 @@ normalize_pressure_dist_slider(const struct input_absinfo *absinfo)
> >  }
> >
> >  static inline double
> > +normalize_pressure(const struct input_absinfo *absinfo,
> > +                  struct libinput_tablet_tool *tool)
> > +{
> > +       double range = absinfo->maximum - absinfo->minimum;
> > +       int offset = tool->pressure_offset != INT_MIN ?
> > +                       tool->pressure_offset : 0;
> > +       double value = (absinfo->value - offset - absinfo->minimum) / range;
> > +
> > +       return value;
> > +}
> > +
> > +static inline double
> >  normalize_tilt(const struct input_absinfo *absinfo)
> >  {
> >         double range = absinfo->maximum - absinfo->minimum;
> > @@ -405,10 +419,12 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet,
> >                         else
> >                                 tablet->axes[a] = absinfo->value;
> >                         break;
> > -               case LIBINPUT_TABLET_TOOL_AXIS_DISTANCE:
> >                 case LIBINPUT_TABLET_TOOL_AXIS_PRESSURE:
> > +                       tablet->axes[a] = normalize_pressure(absinfo, tool);
> > +                       break;
> > +               case LIBINPUT_TABLET_TOOL_AXIS_DISTANCE:
> >                 case LIBINPUT_TABLET_TOOL_AXIS_SLIDER:
> > -                       tablet->axes[a] = normalize_pressure_dist_slider(absinfo);
> > +                       tablet->axes[a] = normalize_dist_slider(absinfo);
> >                         break;
> >                 case LIBINPUT_TABLET_TOOL_AXIS_TILT_X:
> >                 case LIBINPUT_TABLET_TOOL_AXIS_TILT_Y:
> > @@ -816,6 +832,7 @@ tablet_get_tool(struct tablet_dispatch *tablet,
> >                         .refcount = 1,
> >                 };
> >
> > +               tool->pressure_offset = INT_MIN;
> >                 tool_set_bits(tablet, tool);
> >
> >                 list_insert(tool_list, &tool->link);
> > @@ -929,6 +946,66 @@ sanitize_tablet_axes(struct tablet_dispatch *tablet)
> >                 set_bit(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_ROTATION_Z);
> >  }
> >
> > +static inline int
> > +axis_range_percentage(const struct input_absinfo *a, int percent)
> > +{
> > +       return (a->maximum - a->minimum) * percent/100 + a->minimum;
> > +}
> > +
> > +static void
> > +detect_pressure_offset(struct tablet_dispatch *tablet,
> > +                      struct evdev_device *device,
> > +                      struct libinput_tablet_tool *tool)
> > +{
> > +       const struct input_absinfo *pressure, *distance;
> > +       int offset;
> > +
> > +       if (!bit_is_set(tablet->changed_axes,
> > +                       LIBINPUT_TABLET_TOOL_AXIS_PRESSURE))
> > +               return;
> > +
> > +       pressure = libevdev_get_abs_info(device->evdev, ABS_PRESSURE);
> > +       distance = libevdev_get_abs_info(device->evdev, ABS_DISTANCE);
> > +
> > +       if (!pressure || !distance)
> > +               return;
> > +
> > +       offset = pressure->value - pressure->minimum;
> > +
> > +       if (tool->pressure_offset != INT_MIN) {
> > +               if (offset < tool->pressure_offset)
> > +                       tool->pressure_offset = offset;
> > +               return;
> > +       }
> > +
> > +       /* we only set a pressure offset on proximity in */
> > +       if (!tablet_has_status(tablet, TABLET_TOOL_ENTERING_PROXIMITY))
> > +               return;
> > +
> > +       /* If we're closer than 50% of the distance axis, skip pressure
> > +        * offset detection, too likely to be wrong */
> > +       if (distance->value < axis_range_percentage(distance, 50))
> > +               return;
> > +
> > +       if (offset > axis_range_percentage(pressure, 20)) {
> > +               log_error(device->base.seat->libinput,
> > +                        "Ignoring pressure offset greater than 20%% detected on tool %s (serial %#x). "
> > +                        "See http://wayland.freedesktop.org/libinput/doc/%s/tablet-support.html\n",
> > +                        tablet_tool_type_to_string(tool->type),
> > +                        tool->serial,
> > +                        LIBINPUT_VERSION);
> > +               return;
> > +       }
> > +
> > +       log_info(device->base.seat->libinput,
> > +                "Pressure offset detected on tool %s (serial %#x).  "
> > +                "See http://wayland.freedesktop.org/libinput/doc/%s/tablet-support.html\n",
> > +                tablet_tool_type_to_string(tool->type),
> > +                tool->serial,
> > +                LIBINPUT_VERSION);
> > +       tool->pressure_offset = offset;
> > +}
> > +
> >  static void
> >  tablet_flush(struct tablet_dispatch *tablet,
> >              struct evdev_device *device,
> > @@ -953,6 +1030,7 @@ tablet_flush(struct tablet_dispatch *tablet,
> >                         tablet_set_status(tablet, TABLET_TOOL_LEAVING_CONTACT);
> >         } else if (tablet_has_status(tablet, TABLET_AXES_UPDATED) ||
> >                    tablet_has_status(tablet, TABLET_TOOL_ENTERING_PROXIMITY)) {
> > +               detect_pressure_offset(tablet, device, tool);
> >                 sanitize_tablet_axes(tablet);
> >                 tablet_check_notify_axes(tablet, device, time, tool);
> >
> > diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h
> > index 162b536..4dcbccc 100644
> > --- a/src/evdev-tablet.h
> > +++ b/src/evdev-tablet.h
> > @@ -178,4 +178,25 @@ tablet_tool_to_evcode(enum libinput_tablet_tool_type type)
> >
> >         return code;
> >  }
> > +
> > +static inline const char *
> > +tablet_tool_type_to_string(enum libinput_tablet_tool_type type)
> > +{
> > +       const char *str;
> > +
> > +       switch (type) {
> > +       case LIBINPUT_TABLET_TOOL_TYPE_PEN:       str = "pen";          break;
> > +       case LIBINPUT_TABLET_TOOL_TYPE_ERASER:    str = "eraser";       break;
> > +       case LIBINPUT_TABLET_TOOL_TYPE_BRUSH:     str = "brush";        break;
> > +       case LIBINPUT_TABLET_TOOL_TYPE_PENCIL:    str = "pencil";       break;
> > +       case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH:  str = "airbrush";     break;
> > +       case LIBINPUT_TABLET_TOOL_TYPE_MOUSE:     str = "mouse";        break;
> > +       case LIBINPUT_TABLET_TOOL_TYPE_LENS:      str = "lens";         break;
> > +       default:
> > +               abort();
> > +       }
> > +
> > +       return str;
> > +}
> > +
> >  #endif
> > diff --git a/src/libinput-private.h b/src/libinput-private.h
> > index 38a14b8..091fd98 100644
> > --- a/src/libinput-private.h
> > +++ b/src/libinput-private.h
> > @@ -259,6 +259,8 @@ struct libinput_tablet_tool {
> >         unsigned char buttons[NCHARS(KEY_MAX) + 1];
> >         int refcount;
> >         void *user_data;
> > +
> > +       int pressure_offset;
> >  };
> >
> >  struct libinput_event {
> > diff --git a/test/litest-device-wacom-intuos-tablet.c b/test/litest-device-wacom-intuos-tablet.c
> > index e0e1d44..ef0a1f1 100644
> > --- a/test/litest-device-wacom-intuos-tablet.c
> > +++ b/test/litest-device-wacom-intuos-tablet.c
> > @@ -37,6 +37,7 @@ static struct input_event proximity_in[] = {
> >         { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN },
> >         { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN },
> >         { .type = EV_ABS, .code = ABS_DISTANCE, .value = LITEST_AUTO_ASSIGN },
> > +       { .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN },
> >         { .type = EV_ABS, .code = ABS_TILT_X, .value = LITEST_AUTO_ASSIGN },
> >         { .type = EV_ABS, .code = ABS_TILT_Y, .value = LITEST_AUTO_ASSIGN },
> >         { .type = EV_ABS, .code = ABS_MISC, .value = 1050626 },
> > diff --git a/test/tablet.c b/test/tablet.c
> > index 18f08b2..9cfc42f 100644
> > --- a/test/tablet.c
> > +++ b/test/tablet.c
> > @@ -2313,7 +2313,7 @@ START_TEST(tablet_pressure_distance_exclusive)
> >         struct libinput_event_tablet_tool *tev;
> >         struct axis_replacement axes[] = {
> >                 { ABS_DISTANCE, 10 },
> > -               { ABS_PRESSURE, 20 },
> > +               { ABS_PRESSURE, 20 }, /* see the litest device */
> >                 { -1, -1 },
> >         };
> >         double pressure, distance;
> > @@ -2530,6 +2530,310 @@ START_TEST(tablet_calibration_set_matrix)
> >  }
> >  END_TEST
> >
> > +START_TEST(tablet_pressure_offset)
> > +{
> > +       struct litest_device *dev = litest_current_device();
> > +       struct libinput *li = dev->libinput;
> > +       struct libinput_event *event;
> > +       struct libinput_event_tablet_tool *tev;
> > +       struct axis_replacement axes[] = {
> > +               { ABS_DISTANCE, 70 },
> > +               { ABS_PRESSURE, 20 },
> > +               { -1, -1 },
> > +       };
> > +       double pressure;
> > +
> > +       litest_tablet_proximity_in(dev, 5, 100, axes);
> > +       litest_drain_events(li);
> > +
> > +       axes[0].value = 0;
> > +       axes[1].value = 21;
> > +       litest_push_event_frame(dev);
> > +       litest_tablet_motion(dev, 70, 70, axes);
> > +       litest_event(dev, EV_KEY, BTN_TOUCH, 1);
> > +       litest_pop_event_frame(dev);
> > +       libinput_dispatch(li);
> > +       litest_drain_events(li);
> > +
> > +       axes[1].value = 20;
> > +       litest_tablet_motion(dev, 70, 70, axes);
> > +       libinput_dispatch(li);
> > +
> > +       event = libinput_get_event(li);
> > +       tev = litest_is_tablet_event(event,
> > +                                    LIBINPUT_EVENT_TABLET_TOOL_AXIS);
> > +       pressure = libinput_event_tablet_tool_get_axis_value(tev,
> > +                                                            LIBINPUT_TABLET_TOOL_AXIS_PRESSURE);
> > +       ck_assert_double_eq(pressure, 0.0);
> > +
> > +       libinput_event_destroy(event);
> > +       litest_drain_events(li);
> > +
> > +       axes[1].value = 21;
> > +       litest_tablet_motion(dev, 70, 70, axes);
> > +
> > +       libinput_dispatch(li);
> > +       event = libinput_get_event(li);
> > +       tev = litest_is_tablet_event(event,
> > +                                    LIBINPUT_EVENT_TABLET_TOOL_AXIS);
> > +
> > +       pressure = libinput_event_tablet_tool_get_axis_value(tev,
> > +                                                            LIBINPUT_TABLET_TOOL_AXIS_PRESSURE);
> > +
> > +       /* can't use the double_eq here, the pressure value is too tiny */
> > +       ck_assert(pressure > 0.0);
> > +       ck_assert(pressure < 1.0);
> > +       libinput_event_destroy(event);
> > +}
> > +END_TEST
> > +
> > +START_TEST(tablet_pressure_offset_decrease)
> > +{
> > +       struct litest_device *dev = litest_current_device();
> > +       struct libinput *li = dev->libinput;
> > +       struct libinput_event *event;
> > +       struct libinput_event_tablet_tool *tev;
> > +       struct axis_replacement axes[] = {
> > +               { ABS_DISTANCE, 70 },
> > +               { ABS_PRESSURE, 20 },
> > +               { -1, -1 },
> > +       };
> > +       double pressure;
> > +
> > +       /* offset 20 on prox in */
> > +       litest_tablet_proximity_in(dev, 5, 100, axes);
> > +       litest_drain_events(li);
> > +
> > +       /* a reduced pressure value must reduce the offset */
> > +       axes[0].value = 0;
> > +       axes[1].value = 10;
> > +       litest_push_event_frame(dev);
> > +       litest_tablet_motion(dev, 70, 70, axes);
> > +       litest_event(dev, EV_KEY, BTN_TOUCH, 1);
> > +       litest_pop_event_frame(dev);
> > +       libinput_dispatch(li);
> > +
> > +       event = libinput_get_event(li);
> > +       tev = litest_is_tablet_event(event,
> > +                                    LIBINPUT_EVENT_TABLET_TOOL_AXIS);
> > +       pressure = libinput_event_tablet_tool_get_axis_value(tev,
> > +                                                            LIBINPUT_TABLET_TOOL_AXIS_PRESSURE);
> > +       ck_assert_double_eq(pressure, 0.0);
> > +
> > +       libinput_event_destroy(event);
> > +       litest_drain_events(li);
> > +
> > +       axes[1].value = 11;
> > +       litest_tablet_motion(dev, 70, 70, axes);
> > +       libinput_dispatch(li);
> > +
> > +       event = libinput_get_event(li);
> > +       tev = litest_is_tablet_event(event,
> > +                                    LIBINPUT_EVENT_TABLET_TOOL_AXIS);
> > +
> > +       pressure = libinput_event_tablet_tool_get_axis_value(tev,
> > +                                                            LIBINPUT_TABLET_TOOL_AXIS_PRESSURE);
> > +
> > +       /* can't use the double_eq here, the pressure value is too tiny */
> > +       ck_assert(pressure > 0.0);
> > +       ck_assert(pressure < 1.0);
> > +       libinput_event_destroy(event);
> > +}
> > +END_TEST
> > +
> > +START_TEST(tablet_pressure_offset_increase)
> > +{
> > +       struct litest_device *dev = litest_current_device();
> > +       struct libinput *li = dev->libinput;
> > +       struct libinput_event *event;
> > +       struct libinput_event_tablet_tool *tev;
> > +       struct axis_replacement axes[] = {
> > +               { ABS_DISTANCE, 70 },
> > +               { ABS_PRESSURE, 20 },
> > +               { -1, -1 },
> > +       };
> > +       double pressure;
> > +
> > +       /* offset 20 on first prox in */
> > +       litest_tablet_proximity_in(dev, 5, 100, axes);
> > +       litest_tablet_proximity_out(dev);
> > +       litest_drain_events(li);
> > +
> > +       /* offset 30 on second prox in - must not change the offset */
> > +       axes[1].value = 30;
> > +       litest_tablet_proximity_in(dev, 5, 100, axes);
> > +       litest_drain_events(li);
> > +
> > +       axes[0].value = 0;
> > +       axes[1].value = 31;
> > +       litest_push_event_frame(dev);
> > +       litest_tablet_motion(dev, 70, 70, axes);
> > +       litest_event(dev, EV_KEY, BTN_TOUCH, 1);
> > +       litest_pop_event_frame(dev);
> > +       libinput_dispatch(li);
> > +       litest_drain_events(li);
> > +
> > +       axes[1].value = 30;
> > +       litest_tablet_motion(dev, 70, 70, axes);
> > +       libinput_dispatch(li);
> > +
> > +       event = libinput_get_event(li);
> > +       tev = litest_is_tablet_event(event,
> > +                                    LIBINPUT_EVENT_TABLET_TOOL_AXIS);
> > +       pressure = libinput_event_tablet_tool_get_axis_value(tev,
> > +                                                            LIBINPUT_TABLET_TOOL_AXIS_PRESSURE);
> > +       /* can't use the double_eq here, the pressure value is too tiny */
> > +       ck_assert(pressure > 0.0);
> > +       ck_assert(pressure < 1.0);
> > +       libinput_event_destroy(event);
> > +
> > +       litest_drain_events(li);
> > +
> > +       axes[1].value = 20;
> > +       litest_tablet_motion(dev, 70, 70, axes);
> > +       libinput_dispatch(li);
> > +
> > +       event = libinput_get_event(li);
> > +       tev = litest_is_tablet_event(event,
> > +                                    LIBINPUT_EVENT_TABLET_TOOL_AXIS);
> > +
> > +       pressure = libinput_event_tablet_tool_get_axis_value(tev,
> > +                                                            LIBINPUT_TABLET_TOOL_AXIS_PRESSURE);
> > +
> > +       ck_assert_double_eq(pressure, 0.0);
> > +       libinput_event_destroy(event);
> > +}
> > +END_TEST
> > +
> > +START_TEST(tablet_pressure_offset_exceed_threshold)
> > +{
> > +       struct litest_device *dev = litest_current_device();
> > +       struct libinput *li = dev->libinput;
> > +       struct libinput_event *event;
> > +       struct libinput_event_tablet_tool *tev;
> > +       struct axis_replacement axes[] = {
> > +               { ABS_DISTANCE, 70 },
> > +               { ABS_PRESSURE, 30 },
> > +               { -1, -1 },
> > +       };
> > +       double pressure;
> > +
> > +       litest_drain_events(li);
> > +
> > +       litest_disable_log_handler(li);
> > +       litest_tablet_proximity_in(dev, 5, 100, axes);
> > +       libinput_dispatch(li);
> > +       event = libinput_get_event(li);
> > +       tev = litest_is_tablet_event(event,
> > +                                    LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
> > +       pressure = libinput_event_tablet_tool_get_axis_value(tev,
> > +                                                            LIBINPUT_TABLET_TOOL_AXIS_PRESSURE);
> > +       ck_assert_double_eq(pressure, 0.0);
> > +       libinput_event_destroy(event);
> > +       litest_restore_log_handler(li);
> > +
> > +       axes[0].value = 0;
> > +       axes[1].value = 31;
> > +       litest_push_event_frame(dev);
> > +       litest_tablet_motion(dev, 70, 70, axes);
> > +       litest_event(dev, EV_KEY, BTN_TOUCH, 1);
> > +       litest_pop_event_frame(dev);
> > +       libinput_dispatch(li);
> > +       litest_drain_events(li);
> > +
> > +       axes[1].value = 30;
> > +       litest_tablet_motion(dev, 70, 70, axes);
> > +       libinput_dispatch(li);
> > +
> > +       event = libinput_get_event(li);
> > +       tev = litest_is_tablet_event(event,
> > +                                    LIBINPUT_EVENT_TABLET_TOOL_AXIS);
> > +       pressure = libinput_event_tablet_tool_get_axis_value(tev,
> > +                                                            LIBINPUT_TABLET_TOOL_AXIS_PRESSURE);
> > +       ck_assert_double_gt(pressure, 0.0);
> > +
> > +       libinput_event_destroy(event);
> > +}
> > +END_TEST
> > +
> > +START_TEST(tablet_pressure_offset_none_for_zero_distance)
> > +{
> > +       struct litest_device *dev = litest_current_device();
> > +       struct libinput *li = dev->libinput;
> > +       struct libinput_event *event;
> > +       struct libinput_event_tablet_tool *tev;
> > +       struct axis_replacement axes[] = {
> > +               { ABS_DISTANCE, 0 },
> > +               { ABS_PRESSURE, 20 },
> > +               { -1, -1 },
> > +       };
> > +       double pressure;
> > +
> > +       litest_drain_events(li);
> > +
> > +       /* we're going straight to touch on proximity, make sure we don't
> > +        * offset the pressure here */
> > +       litest_push_event_frame(dev);
> > +       litest_tablet_proximity_in(dev, 5, 100, axes);
> > +       litest_event(dev, EV_KEY, BTN_TOUCH, 1);
> > +       litest_pop_event_frame(dev);
> > +       libinput_dispatch(li);
> > +
> > +       event = libinput_get_event(li);
> > +       tev = litest_is_tablet_event(event,
> > +                                    LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
> > +       pressure = libinput_event_tablet_tool_get_axis_value(tev,
> > +                                                            LIBINPUT_TABLET_TOOL_AXIS_PRESSURE);
> > +       ck_assert_double_gt(pressure, 0.0);
> > +
> > +       libinput_event_destroy(event);
> > +}
> > +END_TEST
> > +
> > +START_TEST(tablet_pressure_offset_none_for_small_distance)
> > +{
> > +       struct litest_device *dev = litest_current_device();
> > +       struct libinput *li = dev->libinput;
> > +       struct libinput_event *event;
> > +       struct libinput_event_tablet_tool *tev;
> > +       struct axis_replacement axes[] = {
> > +               { ABS_DISTANCE, 20 },
> > +               { ABS_PRESSURE, 20 },
> > +               { -1, -1 },
> > +       };
> > +       double pressure;
> > +
> > +       /* stylus too close to the tablet on the proximity in, ignore any
> > +        * pressure offset */
> > +       litest_tablet_proximity_in(dev, 5, 100, axes);
> > +       litest_drain_events(li);
> > +       libinput_dispatch(li);
> > +
> > +       axes[0].value = 0;
> > +       axes[1].value = 21;
> > +       litest_push_event_frame(dev);
> > +       litest_tablet_motion(dev, 70, 70, axes);
> > +       litest_event(dev, EV_KEY, BTN_TOUCH, 1);
> > +       litest_pop_event_frame(dev);
> > +       litest_drain_events(li);
> > +
> > +       axes[1].value = 20;
> > +       litest_tablet_motion(dev, 70, 70, axes);
> > +       libinput_dispatch(li);
> > +
> > +       litest_wait_for_event_of_type(li,
> > +                                     LIBINPUT_EVENT_TABLET_TOOL_AXIS,
> > +                                     -1);
> > +       event = libinput_get_event(li);
> > +       tev = libinput_event_get_tablet_tool_event(event);
> > +       pressure = libinput_event_tablet_tool_get_axis_value(tev,
> > +                                                            LIBINPUT_TABLET_TOOL_AXIS_PRESSURE);
> > +       ck_assert_double_gt(pressure, 0.0);
> > +
> > +       libinput_event_destroy(event);
> > +}
> > +END_TEST
> > +
> >  void
> >  litest_setup_tests(void)
> >  {
> > @@ -2578,4 +2882,11 @@ litest_setup_tests(void)
> >         litest_add("tablet:calibration", tablet_calibration_has_matrix, LITEST_TABLET, LITEST_ANY);
> >         litest_add("tablet:calibration", tablet_calibration_set_matrix, LITEST_TABLET, LITEST_ANY);
> >         litest_add("tablet:calibration", tablet_calibration_set_matrix_delta, LITEST_TABLET, LITEST_ANY);
> > +
> > +       litest_add_for_device("tablet:pressure", tablet_pressure_offset, LITEST_WACOM_INTUOS);
> > +       litest_add_for_device("tablet:pressure", tablet_pressure_offset_decrease, LITEST_WACOM_INTUOS);
> > +       litest_add_for_device("tablet:pressure", tablet_pressure_offset_increase, LITEST_WACOM_INTUOS);
> > +       litest_add_for_device("tablet:pressure", tablet_pressure_offset_exceed_threshold, LITEST_WACOM_INTUOS);
> > +       litest_add_for_device("tablet:pressure", tablet_pressure_offset_none_for_zero_distance, LITEST_WACOM_INTUOS);
> > +       litest_add_for_device("tablet:pressure", tablet_pressure_offset_none_for_small_distance, LITEST_WACOM_INTUOS);
> >  }
> > --
> > 2.5.0
> >


More information about the wayland-devel mailing list