[PATCH libinput] tablet: change tilt axes to use degrees

Peter Hutterer peter.hutterer at who-t.net
Tue Feb 9 02:18:24 UTC 2016


On Mon, Feb 08, 2016 at 05:01:11PM -0800, Jason Gerecke wrote:
> On Tue, Feb 2, 2016 at 2:59 PM, Peter Hutterer <peter.hutterer at who-t.net> wrote:
> > The Wacom tilt range is 64 degrees so we map everything into that until we
> > know otherwise.
> >
> > This commit also switches the tilt axes around to align the angles with the
> > x/y orientation, i.e. tilting the top of the stylus towards the positive x
> > axis now generates a positive x tilt.
> >
> > Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
> > ---
> >  doc/tablet-support.dox | 12 ++++++++----
> >  src/evdev-tablet.c     | 28 +++++++++++++++++++--------
> >  src/libinput-private.h |  7 ++++++-
> >  src/libinput.h         | 16 ++++++++++++----
> >  test/tablet.c          | 52 +++++++++++++++++++++++++-------------------------
> >  5 files changed, 72 insertions(+), 43 deletions(-)
> >
> > diff --git a/doc/tablet-support.dox b/doc/tablet-support.dox
> > index cc5d409..ff4e460 100644
> > --- a/doc/tablet-support.dox
> > +++ b/doc/tablet-support.dox
> > @@ -83,15 +83,19 @@ additionally provide tilt information along the x and y axis.
> >
> >  @image html tablet-axes.svg "Illustration of the distance, pressure and tilt axes"
> >
> > -The granularity and precision of these axes varies between tablet devices
> > -and cannot usually be mapped into a physical unit.
> > -libinput normalizes distance and pressure into the [0, 1] range and the tilt
> > -axes into the [-1, 1] range with 0 as the neutral point.
> > +The granularity and precision of the distance and pressure axes varies
> > +between tablet devices and cannot usually be mapped into a physical unit.
> > +libinput normalizes distance and pressure into the [0, 1] range.
> >
> >  While the normalization range is identical for these axes, a caller should
> >  not interpret identical values as identical across axes, i.e. a value v1 on
> >  the distance axis has no relation to the same value v1 on the pressure axis.
> >
> > +The tilt axes provide the angle in degrees between a vertical line out of
> > +the tablet and the top of the stylus. The angle is measured along the x and
> > +y axis, respectively, a positive tilt angle thus means that the stylus' top
> > +is tilted towards the logical right and/or bottom of the tablet.
> > +
> >  @section tablet-fake-proximity Handling of proximity events
> >
> >  libinput's @ref LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY events notify a caller
> > diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c
> > index e684055..2157dfc 100644
> > --- a/src/evdev-tablet.c
> > +++ b/src/evdev-tablet.c
> > @@ -225,13 +225,25 @@ normalize_pressure(const struct input_absinfo *absinfo,
> >  }
> >
> >  static inline double
> > -normalize_tilt(const struct input_absinfo *absinfo)
> > +adjust_tilt(const struct input_absinfo *absinfo)
> >  {
> >         double range = absinfo->maximum - absinfo->minimum;
> >         double value = (absinfo->value - absinfo->minimum) / range;
> > +       const int WACOM_MAX_DEGREES = 64;
> >
> >         /* Map to the (-1, 1) range */
> > -       return (value * 2) - 1;
> > +       value = (value * 2) - 1;
> > +
> > +       /* Wacom supports physical [-64, 64] degrees, so map to that by
> > +        * default. If other tablets have a different physical range or
> > +        * nonzero physical offsets, they need extra treatment
> > +        * here.
> > +        *
> > +        * And invert because we flip the axes to align with the x/y
> > +        * positive direction.
> > +        */
> > +
> > +       return value * WACOM_MAX_DEGREES  * -1;
> 
> The axes should already be aligned to positive X/Y, so I'm not sure
> what this is about. Watching the output from evemu-record, tilt values
> are positive for right/down and negative for left/up. Am I missing
> something?

urgh. I have no idea how this happened... You're correct, they're aligned,
I've fixed the two instances and the tests to expect the real thing. Thanks
for the review.

Cheers,
   Peter

> 
> >  }
> >
> >  static inline int32_t
> > @@ -251,8 +263,8 @@ convert_tilt_to_rotation(struct tablet_dispatch *tablet)
> >            values. The device has a 175 degree CCW hardware offset but since we use
> >            atan2 the effective offset is just 5 degrees.
> >            */
> > -       x = tablet->axes.tilt.x;
> > -       y = tablet->axes.tilt.y;
> > +       x = -tablet->axes.tilt.x;
> > +       y = -tablet->axes.tilt.y;
> 
> Ditto.
> 
> Otherwise,
> 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....
> 
> 
> >         clear_bit(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_TILT_X);
> >         clear_bit(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_TILT_Y);
> >
> > @@ -398,17 +410,17 @@ tablet_handle_slider(struct tablet_dispatch *tablet,
> >         return tablet->axes.slider;
> >  }
> >
> > -static inline struct normalized_range_coords
> > +static inline struct tilt_degrees
> >  tablet_handle_tilt(struct tablet_dispatch *tablet,
> >                    struct evdev_device *device)
> >  {
> > -       struct normalized_range_coords tilt;
> > +       struct tilt_degrees tilt;
> >         const struct input_absinfo *absinfo;
> >
> >         if (bit_is_set(tablet->changed_axes,
> >                        LIBINPUT_TABLET_TOOL_AXIS_TILT_X)) {
> >                 absinfo = libevdev_get_abs_info(device->evdev, ABS_TILT_X);
> > -               tablet->axes.tilt.x = normalize_tilt(absinfo);
> > +               tablet->axes.tilt.x = adjust_tilt(absinfo);
> >                 if (device->left_handed.enabled)
> >                         tablet->axes.tilt.x *= -1;
> >         }
> > @@ -417,7 +429,7 @@ tablet_handle_tilt(struct tablet_dispatch *tablet,
> >         if (bit_is_set(tablet->changed_axes,
> >                        LIBINPUT_TABLET_TOOL_AXIS_TILT_Y)) {
> >                 absinfo = libevdev_get_abs_info(device->evdev, ABS_TILT_Y);
> > -               tablet->axes.tilt.y = normalize_tilt(absinfo);
> > +               tablet->axes.tilt.y = adjust_tilt(absinfo);
> >                 if (device->left_handed.enabled)
> >                         tablet->axes.tilt.y *= -1;
> >         }
> > diff --git a/src/libinput-private.h b/src/libinput-private.h
> > index bc7000d..8d2492a 100644
> > --- a/src/libinput-private.h
> > +++ b/src/libinput-private.h
> > @@ -63,6 +63,11 @@ struct normalized_range_coords {
> >         double x, y;
> >  };
> >
> > +/* A pair of angles in degrees */
> > +struct tilt_degrees {
> > +       double x, y;
> > +};
> > +
> >  /* A threshold with an upper and lower limit */
> >  struct threshold {
> >         int upper;
> > @@ -74,7 +79,7 @@ struct tablet_axes {
> >         struct normalized_coords delta;
> >         double distance;
> >         double pressure;
> > -       struct normalized_range_coords tilt;
> > +       struct tilt_degrees tilt;
> >         double rotation;
> >         double slider;
> >         double wheel;
> > diff --git a/src/libinput.h b/src/libinput.h
> > index 8ed5632..0b6fbc4 100644
> > --- a/src/libinput.h
> > +++ b/src/libinput.h
> > @@ -1646,12 +1646,16 @@ libinput_event_tablet_tool_get_distance(struct libinput_event_tablet_tool *event
> >   * @ingroup event_tablet
> >   *
> >   * Returns the current tilt along the X axis of the tablet's current logical
> > - * orientation, normalized to the range [-1, 1].
> > + * orientation, in degrees off the tablet's z axis. That is, if the tool is
> > + * perfectly orthogonal to the tablet, the tilt angle is 0. When the top
> > + * tilts towards the logical top/left of the tablet, the x/y tilt angles are
> > + * negative, if the top tilts towards the logical bottom/right of the
> > + * tablet, the x/y tilt angles are positive.
> >   *
> >   * If this axis does not exist on the current tool, this function returns 0.
> >   *
> >   * @param event The libinput tablet event
> > - * @return The current value of the the axis
> > + * @return The current value of the the axis in degrees
> >   */
> >  double
> >  libinput_event_tablet_tool_get_tilt_x(struct libinput_event_tablet_tool *event);
> > @@ -1660,12 +1664,16 @@ libinput_event_tablet_tool_get_tilt_x(struct libinput_event_tablet_tool *event);
> >   * @ingroup event_tablet
> >   *
> >   * Returns the current tilt along the Y axis of the tablet's current logical
> > - * orientation, normalized to the range [-1, 1].
> > + * orientation, in degrees off the tablet's z axis. That is, if the tool is
> > + * perfectly orthogonal to the tablet, the tilt angle is 0. When the top
> > + * tilts towards the logical top/left of the tablet, the x/y tilt angles are
> > + * negative, if the top tilts towards the logical bottom/right of the
> > + * tablet, the x/y tilt angles are positive.
> >   *
> >   * If this axis does not exist on the current tool, this function returns 0.
> >   *
> >   * @param event The libinput tablet event
> > - * @return The current value of the the axis
> > + * @return The current value of the the axis in degrees
> >   */
> >  double
> >  libinput_event_tablet_tool_get_tilt_y(struct libinput_event_tablet_tool *event);
> > diff --git a/test/tablet.c b/test/tablet.c
> > index 8936d57..a09deb2 100644
> > --- a/test/tablet.c
> > +++ b/test/tablet.c
> > @@ -1415,8 +1415,8 @@ START_TEST(left_handed_tilt)
> >         tx = libinput_event_tablet_tool_get_tilt_x(tev);
> >         ty = libinput_event_tablet_tool_get_tilt_y(tev);
> >
> > -       ck_assert_double_lt(tx, 0);
> > -       ck_assert_double_gt(ty, 0);
> > +       ck_assert_double_gt(tx, 0);
> > +       ck_assert_double_lt(ty, 0);
> >
> >         libinput_event_destroy(event);
> >  #endif
> > @@ -3097,19 +3097,18 @@ START_TEST(tilt_x)
> >         tev = litest_is_tablet_event(event,
> >                                      LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
> >
> > -       /* 90% of the actual axis but mapped into a [-1, 1] range, so we
> > -        * expect a pos. value of 80. Rounding errors in the scaling though,
> > -        * we'll get something between 0.79 and 0.80 */
> > +       /* 90% of the actual axis but mapped into a [-64, 64] tilt range, so
> > +        * we expect 50 degrees ą rounding errors */
> >         tx = libinput_event_tablet_tool_get_tilt_x(tev);
> > -       ck_assert_double_gt(tx, 0.79);
> > -       ck_assert_double_le(tx, 0.80);
> > +       ck_assert_double_le(tx, -50);
> > +       ck_assert_double_ge(tx, -51);
> >
> >         ty = libinput_event_tablet_tool_get_tilt_y(tev);
> > -       ck_assert_double_eq(ty, -1);
> > +       ck_assert_double_eq(ty, 64);
> >
> >         libinput_event_destroy(event);
> >
> > -       expected_tx = -1.0;
> > +       expected_tx = 64.0;
> >
> >         litest_axis_set_value(axes, ABS_DISTANCE, 0);
> >         litest_axis_set_value(axes, ABS_PRESSURE, 1);
> > @@ -3123,19 +3122,20 @@ START_TEST(tilt_x)
> >                                              LIBINPUT_EVENT_TABLET_TOOL_AXIS);
> >
> >                 tx = libinput_event_tablet_tool_get_tilt_x(tev);
> > -               ck_assert_double_gt(tx, expected_tx - 0.1);
> > -               ck_assert_double_lt(tx, expected_tx + 0.1);
> > +               ck_assert_double_ge(tx, expected_tx - 1);
> > +               ck_assert_double_le(tx, expected_tx + 1);
> >
> >                 ty = libinput_event_tablet_tool_get_tilt_y(tev);
> > -               ck_assert_double_eq(ty, -1);
> > +               ck_assert_double_eq(ty, 64);
> >
> >                 libinput_event_destroy(event);
> >
> > -               expected_tx += 0.1;
> > +               expected_tx = tx - 6;
> >         }
> >
> >         /* the last event must reach the max */
> > -       ck_assert_double_eq(tx, 1.0);
> > +       ck_assert_double_le(tx, -63.0);
> > +       ck_assert_double_ge(tx, -64.0);
> >  }
> >  END_TEST
> >
> > @@ -3164,19 +3164,18 @@ START_TEST(tilt_y)
> >         tev = litest_is_tablet_event(event,
> >                                      LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
> >
> > -       /* 90% of the actual axis but mapped into a [-1, 1] range, so we
> > -        * expect a pos. value of 80. Rounding errors in the scaling though,
> > -        * we'll get something between 0.79 and 0.80 */
> > +       /* 90% of the actual axis but mapped into a [-64, 64] tilt range, so
> > +        * we expect 50 degrees ą rounding errors */
> >         ty = libinput_event_tablet_tool_get_tilt_y(tev);
> > -       ck_assert_double_gt(ty, 0.79);
> > -       ck_assert_double_le(ty, 0.80);
> > +       ck_assert_double_le(ty, -50);
> > +       ck_assert_double_ge(ty, -51);
> >
> >         tx = libinput_event_tablet_tool_get_tilt_x(tev);
> > -       ck_assert_double_eq(tx, -1);
> > +       ck_assert_double_eq(tx, 64);
> >
> >         libinput_event_destroy(event);
> >
> > -       expected_ty = -1.0;
> > +       expected_ty = 64;
> >
> >         litest_axis_set_value(axes, ABS_DISTANCE, 0);
> >         litest_axis_set_value(axes, ABS_PRESSURE, 1);
> > @@ -3190,19 +3189,20 @@ START_TEST(tilt_y)
> >                                              LIBINPUT_EVENT_TABLET_TOOL_AXIS);
> >
> >                 ty = libinput_event_tablet_tool_get_tilt_y(tev);
> > -               ck_assert_double_gt(ty, expected_ty - 0.1);
> > -               ck_assert_double_lt(ty, expected_ty + 0.1);
> > +               ck_assert_double_ge(ty, expected_ty - 1);
> > +               ck_assert_double_le(ty, expected_ty + 1);
> >
> >                 tx = libinput_event_tablet_tool_get_tilt_x(tev);
> > -               ck_assert_double_eq(tx, -1);
> > +               ck_assert_double_eq(tx, 64);
> >
> >                 libinput_event_destroy(event);
> >
> > -               expected_ty += 0.1;
> > +               expected_ty = ty - 6;
> >         }
> >
> >         /* the last event must reach the max */
> > -       ck_assert_double_eq(ty, 1.0);
> > +       ck_assert_double_le(ty, -63.0);
> > +       ck_assert_double_ge(tx, -64.0);
> >  }
> >  END_TEST
> >
> > --
> > 2.5.0
> >
> 


More information about the wayland-devel mailing list