[PATCH libinput 21/26] tablet: support artpen rotation

Peter Hutterer peter.hutterer at who-t.net
Tue Feb 24 16:16:51 PST 2015


On Tue, Feb 24, 2015 at 12:53:51PM -0500, Benjamin Tissoires wrote:
> On Tue, Feb 24, 2015 at 1:21 AM, Peter Hutterer
> <peter.hutterer at who-t.net> wrote:
> > Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
> > ---
> >  src/evdev-tablet.c | 35 +++++++++++++++-----
> >  src/evdev-tablet.h |  6 ++++
> >  src/libinput.h     |  3 +-
> >  test/tablet.c      | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  4 files changed, 130 insertions(+), 9 deletions(-)
> >
> > diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c
> > index 143d618..d05b6c2 100644
> > --- a/src/evdev-tablet.c
> > +++ b/src/evdev-tablet.c
> > @@ -103,6 +103,7 @@ tablet_process_absolute(struct tablet_dispatch *tablet,
> >         switch (e->code) {
> >         case ABS_X:
> >         case ABS_Y:
> > +       case ABS_Z:
> >         case ABS_PRESSURE:
> >         case ABS_TILT_X:
> >         case ABS_TILT_Y:
> > @@ -240,6 +241,16 @@ convert_tilt_to_rotation(struct tablet_dispatch *tablet)
> >         set_bit(tablet->changed_axes, LIBINPUT_TABLET_AXIS_ROTATION_Z);
> >  }
> >
> > +static double
> > +convert_to_degrees(const struct input_absinfo *absinfo, double offset)
> > +{
> > +       /* range is [0, 360[, i.e. range + 1 */
> > +       double range = absinfo->maximum - absinfo->minimum + 1;
> > +       double value = (absinfo->value - absinfo->minimum) / range;
> > +
> > +       return fmod(value * 360.0 + offset, 360.0);
> > +}
> > +
> >  static void
> >  tablet_check_notify_axes(struct tablet_dispatch *tablet,
> >                          struct evdev_device *device,
> > @@ -263,14 +274,13 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet,
> >
> >                 /* ROTATION_Z is higher than TILT_X/Y so we know that the
> >                    tilt axes are already normalized and set */
> > -               if (a == LIBINPUT_TABLET_AXIS_ROTATION_Z) {
> > -                       if (tablet->current_tool_type == LIBINPUT_TOOL_MOUSE ||
> > -                           tablet->current_tool_type == LIBINPUT_TOOL_LENS) {
> > -                               convert_tilt_to_rotation(tablet);
> > -                               axes[LIBINPUT_TABLET_AXIS_TILT_X] = 0;
> > -                               axes[LIBINPUT_TABLET_AXIS_TILT_Y] = 0;
> > -                               axes[a] = tablet->axes[a];
> > -                       }
> > +               if (a == LIBINPUT_TABLET_AXIS_ROTATION_Z &&
> > +                  (tablet->current_tool_type == LIBINPUT_TOOL_MOUSE ||
> > +                   tablet->current_tool_type == LIBINPUT_TOOL_LENS)) {
> > +                       convert_tilt_to_rotation(tablet);
> > +                       axes[LIBINPUT_TABLET_AXIS_TILT_X] = 0;
> > +                       axes[LIBINPUT_TABLET_AXIS_TILT_Y] = 0;
> > +                       axes[a] = tablet->axes[a];
> >                         continue;
> >                 }
> >
> > @@ -294,6 +304,10 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet,
> >                 case LIBINPUT_TABLET_AXIS_TILT_Y:
> >                         tablet->axes[a] = normalize_tilt(absinfo);
> >                         break;
> > +               case LIBINPUT_TABLET_AXIS_ROTATION_Z:
> > +                       /* artpen has 0 with buttons pointing east */
> > +                       tablet->axes[a] = convert_to_degrees(absinfo, 90);
> > +                       break;
> >                 default:
> >                         log_bug_libinput(device->base.seat->libinput,
> >                                          "Invalid axis update: %d\n", a);
> > @@ -506,6 +520,10 @@ tool_set_bits_from_libwacom(const struct tablet_dispatch *tablet,
> >                 copy_axis_cap(tablet, tool, LIBINPUT_TABLET_AXIS_SLIDER);
> >                 /* fall-through */
> >         case WSTYLUS_MARKER:
> > +               if (type == WSTYLUS_MARKER)
> > +                       copy_axis_cap(tablet, tool,
> > +                                     LIBINPUT_TABLET_AXIS_ROTATION_Z);
> 
> This unfortunately does not work for the eraser side of the art pen :(
> 
> Same remark for the airbrush and its slider.
> 
> Besides, if we rely on libwacom to provide individual axes, we will
> remove this not-so-friendly if within the switch case.

yeah, I'd rather leave this as-is for now and fix this in libwacom directly.
There is no good way for us to tell which axes exist on the artpen eraser
right now.

Cheers,
   Peter

> > +               /* fallthrough */
> >         case WSTYLUS_GENERAL:
> >         case WSTYLUS_INKING:
> >         case WSTYLUS_CLASSIC:
> > @@ -555,6 +573,7 @@ tool_set_bits(const struct tablet_dispatch *tablet,
> >                 copy_axis_cap(tablet, tool, LIBINPUT_TABLET_AXIS_TILT_X);
> >                 copy_axis_cap(tablet, tool, LIBINPUT_TABLET_AXIS_TILT_Y);
> >                 copy_axis_cap(tablet, tool, LIBINPUT_TABLET_AXIS_SLIDER);
> > +               copy_axis_cap(tablet, tool, LIBINPUT_TABLET_AXIS_ROTATION_Z);
> >                 break;
> >         case LIBINPUT_TOOL_MOUSE:
> >         case LIBINPUT_TOOL_LENS:
> > diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h
> > index d86bf9e..7c472cf 100644
> > --- a/src/evdev-tablet.h
> > +++ b/src/evdev-tablet.h
> > @@ -75,6 +75,9 @@ evcode_to_axis(const uint32_t evcode)
> >         case ABS_Y:
> >                 axis = LIBINPUT_TABLET_AXIS_Y;
> >                 break;
> > +       case ABS_Z:
> > +               axis = LIBINPUT_TABLET_AXIS_ROTATION_Z;
> > +               break;
> >         case ABS_DISTANCE:
> >                 axis = LIBINPUT_TABLET_AXIS_DISTANCE;
> >                 break;
> > @@ -122,6 +125,9 @@ axis_to_evcode(const enum libinput_tablet_axis axis)
> >         case LIBINPUT_TABLET_AXIS_TILT_Y:
> >                 evcode = ABS_TILT_Y;
> >                 break;
> > +       case LIBINPUT_TABLET_AXIS_ROTATION_Z:
> > +               evcode = ABS_Z;
> > +               break;
> >         case LIBINPUT_TABLET_AXIS_SLIDER:
> >                 evcode = ABS_WHEEL;
> >                 break;
> > diff --git a/src/libinput.h b/src/libinput.h
> > index fb6b803..87d220b 100644
> > --- a/src/libinput.h
> > +++ b/src/libinput.h
> > @@ -1056,7 +1056,8 @@ libinput_event_tablet_axis_has_changed(struct libinput_event_tablet *event,
> >   *   degrees, clockwise from the tool's logical neutral position. For the
> >   *   @ref LIBINPUT_TOOL_MOUSE and @ref LIBINPUT_TOOL_LENS tools the logical
> >   *   neutral position is pointing to the current logical north of the
> > - *   tablet.
> > + *   tablet. For the @ref LIBINPUT_TOOL_BRUSH tool, the logical neutral
> > + *   position is with the buttons pointing up.
> >   * - @ref LIBINPUT_TABLET_AXIS_SLIDER - A slider on the tool, normalized
> >   *   from 0 to 1. e.g. the wheel-like tool on the Wacom Airbrush.
> >   *
> > diff --git a/test/tablet.c b/test/tablet.c
> > index fef4fc5..afc654e 100644
> > --- a/test/tablet.c
> > +++ b/test/tablet.c
> > @@ -1359,6 +1359,99 @@ START_TEST(airbrush_wheel)
> >  }
> >  END_TEST
> >
> > +START_TEST(artpen_tool)
> > +{
> > +       struct litest_device *dev = litest_current_device();
> > +       struct libinput *li = dev->libinput;
> > +       struct libinput_event *event;
> > +       struct libinput_event_tablet *tev;
> > +       struct libinput_tool *tool;
> > +
> > +       if (!libevdev_has_event_code(dev->evdev,
> > +                                   EV_ABS,
> > +                                   ABS_Z))
> > +               return;
> > +
> > +       litest_drain_events(li);
> > +
> > +       litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
> > +       litest_event(dev, EV_ABS, ABS_MISC, 0x804); /* Art Pen */
> > +       litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
> > +       litest_event(dev, EV_SYN, SYN_REPORT, 0);
> > +
> > +       litest_wait_for_event_of_type(li,
> > +                                     LIBINPUT_EVENT_TABLET_PROXIMITY,
> > +                                     -1);
> > +       event = libinput_get_event(li);
> > +       tev = libinput_event_get_tablet_event(event);
> > +       tool = libinput_event_tablet_get_tool(tev);
> > +       ck_assert_notnull(tool);
> > +       ck_assert_int_eq(libinput_tool_get_type(tool),
> > +                        LIBINPUT_TOOL_PEN);
> > +       ck_assert(libinput_tool_has_axis(tool,
> > +                                        LIBINPUT_TABLET_AXIS_ROTATION_Z));
> > +
> > +       libinput_event_destroy(event);
> > +}
> > +END_TEST
> > +
> > +START_TEST(artpen_rotation)
> > +{
> > +       struct litest_device *dev = litest_current_device();
> > +       struct libinput *li = dev->libinput;
> > +       struct libinput_event *event;
> > +       struct libinput_event_tablet *tev;
> > +       const struct input_absinfo *abs;
> > +       double val;
> > +       double scale;
> > +       int angle;
> > +
> > +       if (!libevdev_has_event_code(dev->evdev,
> > +                                   EV_ABS,
> > +                                   ABS_Z))
> > +               return;
> > +
> > +       litest_drain_events(li);
> > +
> > +       abs = libevdev_get_abs_info(dev->evdev, ABS_Z);
> > +       ck_assert_notnull(abs);
> > +
> > +       litest_event(dev, EV_KEY, BTN_TOOL_BRUSH, 1);
> > +       litest_event(dev, EV_ABS, ABS_MISC, 0x804); /* Art Pen */
> > +       litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
> > +       litest_event(dev, EV_SYN, SYN_REPORT, 0);
> > +
> > +       /* start with non-zero */
> > +       litest_event(dev, EV_ABS, ABS_Z, 10);
> > +       litest_event(dev, EV_SYN, SYN_REPORT, 0);
> > +
> > +       litest_drain_events(li);
> > +
> > +       scale = (abs->maximum - abs->minimum + 1)/360.0;
> > +       for (angle = 0; angle < 360; angle += 8) {
> > +               int a = angle * scale + abs->minimum;
> > +
> > +               litest_event(dev, EV_ABS, ABS_Z, a);
> > +               litest_event(dev, EV_SYN, SYN_REPORT, 0);
> > +
> > +               litest_wait_for_event_of_type(li,
> > +                                             LIBINPUT_EVENT_TABLET_AXIS,
> > +                                             -1);
> > +               event = libinput_get_event(li);
> > +               tev = libinput_event_get_tablet_event(event);
> > +               ck_assert(libinput_event_tablet_axis_has_changed(tev,
> > +                                        LIBINPUT_TABLET_AXIS_ROTATION_Z));
> > +               val = libinput_event_tablet_get_axis_value(tev,
> > +                                        LIBINPUT_TABLET_AXIS_ROTATION_Z);
> > +
> > +               /* artpen has a 90 deg offset cw */
> > +               ck_assert_int_eq(round(val), (angle + 90) % 360);
> > +               libinput_event_destroy(event);
> > +               litest_assert_empty_queue(li);
> > +       }
> > +}
> > +END_TEST
> > +
> >  int
> >  main(int argc, char **argv)
> >  {
> > @@ -1384,6 +1477,8 @@ main(int argc, char **argv)
> >         litest_add("tablet:mouse", mouse_rotation, LITEST_TABLET, LITEST_ANY);
> >         litest_add("tablet:airbrush", airbrush_tool, LITEST_TABLET, LITEST_ANY);
> >         litest_add("tablet:airbrush", airbrush_wheel, LITEST_TABLET, LITEST_ANY);
> > +       litest_add("tablet:artpen", artpen_tool, LITEST_TABLET, LITEST_ANY);
> > +       litest_add("tablet:artpen", artpen_rotation, LITEST_TABLET, LITEST_ANY);
> >
> >         return litest_run(argc, argv);
> >  }
> > --
> > 2.1.0
> >
> > _______________________________________________
> > wayland-devel mailing list
> > wayland-devel at lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list