tablet: add a the Totem tool type to the tablet interface

This is the public API only, not the internal bits, so nothing will work just
yet.

This interface addition is for the Dell Canvas Totem tool, so let's go with
the same name because options like "Rotary" are too ambiguous.

The totem is a knob that can be placed on the surface, it provides us with
location and rotation data. The touch major/minor fields are filled in by the
current totem, but they're always the same size.

The totem exports BTN_0 as well, so let's add that to the debug-events output.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Peter Hutterer 2018-09-13 13:26:22 +10:00
parent 52e86f4b2a
commit 17d792445e
7 changed files with 232 additions and 2 deletions

View file

@ -200,6 +200,12 @@ axis_to_evcode(const enum libinput_tablet_tool_axis axis)
case LIBINPUT_TABLET_TOOL_AXIS_SLIDER:
evcode = ABS_WHEEL;
break;
case LIBINPUT_TABLET_TOOL_AXIS_SIZE_MAJOR:
evcode = ABS_MT_TOUCH_MAJOR;
break;
case LIBINPUT_TABLET_TOOL_AXIS_SIZE_MINOR:
evcode = ABS_MT_TOUCH_MINOR;
break;
default:
abort();
}

View file

@ -111,6 +111,12 @@ struct device_coord_rect {
int w, h;
};
/* A pair of major/minor in mm */
struct phys_ellipsis {
double major;
double minor;
};
/* A pair of tilt flags */
struct wheel_tilt_flags {
bool vertical, horizontal;
@ -349,9 +355,11 @@ enum libinput_tablet_tool_axis {
LIBINPUT_TABLET_TOOL_AXIS_ROTATION_Z = 7,
LIBINPUT_TABLET_TOOL_AXIS_SLIDER = 8,
LIBINPUT_TABLET_TOOL_AXIS_REL_WHEEL = 9,
LIBINPUT_TABLET_TOOL_AXIS_SIZE_MAJOR = 10,
LIBINPUT_TABLET_TOOL_AXIS_SIZE_MINOR = 11,
};
#define LIBINPUT_TABLET_TOOL_AXIS_MAX LIBINPUT_TABLET_TOOL_AXIS_REL_WHEEL
#define LIBINPUT_TABLET_TOOL_AXIS_MAX LIBINPUT_TABLET_TOOL_AXIS_SIZE_MINOR
struct tablet_axes {
struct device_coords point;
@ -363,6 +371,7 @@ struct tablet_axes {
double slider;
double wheel;
int wheel_discrete;
struct phys_ellipsis size;
};
struct libinput_tablet_tool {

View file

@ -1,6 +1,6 @@
/*
* Copyright © 2013 Jonas Ådahl
* Copyright © 2013-2015 Red Hat, Inc.
* Copyright © 2013-2018 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -1153,6 +1153,38 @@ libinput_event_tablet_tool_slider_has_changed(
LIBINPUT_TABLET_TOOL_AXIS_SLIDER);
}
LIBINPUT_EXPORT int
libinput_event_tablet_tool_size_major_has_changed(
struct libinput_event_tablet_tool *event)
{
require_event_type(libinput_event_get_context(&event->base),
event->base.type,
0,
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
return bit_is_set(event->changed_axes,
LIBINPUT_TABLET_TOOL_AXIS_SIZE_MAJOR);
}
LIBINPUT_EXPORT int
libinput_event_tablet_tool_size_minor_has_changed(
struct libinput_event_tablet_tool *event)
{
require_event_type(libinput_event_get_context(&event->base),
event->base.type,
0,
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
return bit_is_set(event->changed_axes,
LIBINPUT_TABLET_TOOL_AXIS_SIZE_MINOR);
}
LIBINPUT_EXPORT int
libinput_event_tablet_tool_wheel_has_changed(
struct libinput_event_tablet_tool *event)
@ -1315,6 +1347,34 @@ libinput_event_tablet_tool_get_slider_position(struct libinput_event_tablet_tool
return event->axes.slider;
}
LIBINPUT_EXPORT double
libinput_event_tablet_tool_get_size_major(struct libinput_event_tablet_tool *event)
{
require_event_type(libinput_event_get_context(&event->base),
event->base.type,
0,
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
return event->axes.size.major;
}
LIBINPUT_EXPORT double
libinput_event_tablet_tool_get_size_minor(struct libinput_event_tablet_tool *event)
{
require_event_type(libinput_event_get_context(&event->base),
event->base.type,
0,
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
return event->axes.size.minor;
}
LIBINPUT_EXPORT double
libinput_event_tablet_tool_get_wheel_delta(struct libinput_event_tablet_tool *event)
{
@ -1551,6 +1611,13 @@ libinput_tablet_tool_has_wheel(struct libinput_tablet_tool *tool)
LIBINPUT_TABLET_TOOL_AXIS_REL_WHEEL);
}
LIBINPUT_EXPORT int
libinput_tablet_tool_has_size(struct libinput_tablet_tool *tool)
{
return bit_is_set(tool->axis_caps,
LIBINPUT_TABLET_TOOL_AXIS_SIZE_MAJOR);
}
LIBINPUT_EXPORT int
libinput_tablet_tool_has_button(struct libinput_tablet_tool *tool,
uint32_t code)

View file

@ -341,6 +341,9 @@ enum libinput_tablet_tool_type {
LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH, /**< An airbrush-like tool */
LIBINPUT_TABLET_TOOL_TYPE_MOUSE, /**< A mouse bound to the tablet */
LIBINPUT_TABLET_TOOL_TYPE_LENS, /**< A mouse tool with a lens */
LIBINPUT_TABLET_TOOL_TYPE_TOTEM, /**< A rotary device with
positional and rotation
data */
};
/**
@ -2082,6 +2085,49 @@ libinput_event_tablet_tool_rotation_has_changed(
int
libinput_event_tablet_tool_slider_has_changed(
struct libinput_event_tablet_tool *event);
/**
* @ingroup event_tablet
*
* Check if the size major axis was updated in this event.
* For events that are not of type @ref LIBINPUT_EVENT_TABLET_TOOL_AXIS,
* @ref LIBINPUT_EVENT_TABLET_TOOL_TIP, or
* @ref LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY, this function returns 0.
*
* @note It is an application bug to call this function for events other
* than @ref LIBINPUT_EVENT_TABLET_TOOL_AXIS, @ref
* LIBINPUT_EVENT_TABLET_TOOL_TIP, or @ref
* LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY, or @ref
* LIBINPUT_EVENT_TABLET_TOOL_BUTTON.
*
* @param event The libinput tablet tool event
* @return 1 if the axis was updated or 0 otherwise
*/
int
libinput_event_tablet_tool_size_major_has_changed(
struct libinput_event_tablet_tool *event);
/**
* @ingroup event_tablet
*
* Check if the size minor axis was updated in this event.
* For events that are not of type @ref LIBINPUT_EVENT_TABLET_TOOL_AXIS,
* @ref LIBINPUT_EVENT_TABLET_TOOL_TIP, or
* @ref LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY, this function returns 0.
*
* @note It is an application bug to call this function for events other
* than @ref LIBINPUT_EVENT_TABLET_TOOL_AXIS, @ref
* LIBINPUT_EVENT_TABLET_TOOL_TIP, or @ref
* LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY, or @ref
* LIBINPUT_EVENT_TABLET_TOOL_BUTTON.
*
* @param event The libinput tablet tool event
* @return 1 if the axis was updated or 0 otherwise
*/
int
libinput_event_tablet_tool_size_minor_has_changed(
struct libinput_event_tablet_tool *event);
/**
* @ingroup event_tablet
*
@ -2293,6 +2339,42 @@ libinput_event_tablet_tool_get_rotation(struct libinput_event_tablet_tool *event
double
libinput_event_tablet_tool_get_slider_position(struct libinput_event_tablet_tool *event);
/**
* @ingroup event_tablet
*
* Returns the current size in mm along the major axis of the touching
* ellipse. This axis is not necessarily aligned with either x or y, the
* rotation must be taken into account.
*
* Where no rotation is available on a tool, or where rotation is zero, the
* major axis aligns with the y axis and the minor axis with the x axis.
*
* If this axis does not exist on the current tool, this function returns 0.
*
* @param event The libinput tablet tool event
* @return The current value of the axis major in mm
*/
double
libinput_event_tablet_tool_get_size_major(struct libinput_event_tablet_tool *event);
/**
* @ingroup event_tablet
*
* Returns the current size in mm along the minor axis of the touching
* ellipse. This axis is not necessarily aligned with either x or y, the
* rotation must be taken into account.
*
* Where no rotation is available on a tool, or where rotation is zero, the
* minor axis aligns with the y axis and the minor axis with the x axis.
*
* If this axis does not exist on the current tool, this function returns 0.
*
* @param event The libinput tablet tool event
* @return The current value of the axis minor in mm
*/
double
libinput_event_tablet_tool_get_size_minor(struct libinput_event_tablet_tool *event);
/**
* @ingroup event_tablet
*
@ -2664,6 +2746,20 @@ libinput_tablet_tool_has_rotation(struct libinput_tablet_tool *tool);
int
libinput_tablet_tool_has_slider(struct libinput_tablet_tool *tool);
/**
* @ingroup event_tablet
*
* Return whether the tablet tool has a ellipsis major and minor.
* Where the underlying hardware only supports one of either major or minor,
* libinput emulates the other axis as a circular contact, i.e. major ==
* minor for all values of major.
*
* @param tool The tool to check the axis capabilities of
* @return Nonzero if the axis is available, zero otherwise.
*/
int
libinput_tablet_tool_has_size(struct libinput_tablet_tool *tool);
/**
* @ingroup event_tablet
*

View file

@ -297,3 +297,11 @@ LIBINPUT_1.9 {
LIBINPUT_1.11 {
libinput_device_touch_get_touch_count;
} LIBINPUT_1.9;
LIBINPUT_1.14 {
libinput_tablet_tool_has_size;
libinput_event_tablet_tool_get_size_major;
libinput_event_tablet_tool_get_size_minor;
libinput_event_tablet_tool_size_major_has_changed;
libinput_event_tablet_tool_size_minor_has_changed;
} LIBINPUT_1.11;

View file

@ -366,6 +366,7 @@ print_tablet_axes(struct libinput_event_tablet_tool *t)
double dist, pressure;
double rotation, slider, wheel;
double delta;
double major, minor;
#define changed_sym(ev, ax) \
(libinput_event_tablet_tool_##ax##_has_changed(ev) ? "*" : "")
@ -415,6 +416,14 @@ print_tablet_axes(struct libinput_event_tablet_tool *t)
wheel, changed_sym(t, wheel),
(int)delta);
}
if (libinput_tablet_tool_has_size(tool)) {
major = libinput_event_tablet_tool_get_size_major(t);
minor = libinput_event_tablet_tool_get_size_minor(t);
printq("\tsize: %.2f%s/%.2f%s",
major, changed_sym(t, size_major),
minor, changed_sym(t, size_minor));
}
}
static void
@ -548,6 +557,9 @@ print_proximity_event(struct libinput_event *ev)
case LIBINPUT_TABLET_TOOL_TYPE_LENS:
tool_str = "lens";
break;
case LIBINPUT_TABLET_TOOL_TYPE_TOTEM:
tool_str = "totem";
break;
default:
abort();
}
@ -586,6 +598,8 @@ print_proximity_event(struct libinput_event *ev)
printq("s");
if (libinput_tablet_tool_has_wheel(tool))
printq("w");
if (libinput_tablet_tool_has_size(tool))
printq("S");
printq("\tbtn:");
if (libinput_tablet_tool_has_button(tool, BTN_TOUCH))
@ -604,6 +618,8 @@ print_proximity_event(struct libinput_event *ev)
printq("Sd");
if (libinput_tablet_tool_has_button(tool, BTN_EXTRA))
printq("Ex");
if (libinput_tablet_tool_has_button(tool, BTN_0))
printq("0");
}
printq("\n");

View file

@ -134,6 +134,8 @@ struct window {
double pressure;
double distance;
double tilt_x, tilt_y;
double rotation;
double size_major, size_minor;
/* these are for the delta coordinates, but they're not
* deltas, they are converted into abs positions */
@ -473,13 +475,36 @@ draw_tablet(struct window *w, cairo_t *cr)
cairo_set_source_rgb(cr, .2, .8, .8);
cairo_translate(cr, w->tool.x, w->tool.y);
/* scale of 2.5 is large enough to make the marker visible around the
physical totem */
cairo_scale(cr,
1.0 + w->tool.size_major * 2.5,
1.0 + w->tool.size_minor * 2.5);
cairo_scale(cr, 1.0 + w->tool.tilt_x/30.0, 1.0 + w->tool.tilt_y/30.0);
if (w->tool.rotation)
cairo_rotate(cr, w->tool.rotation * M_PI/180.0);
if (w->tool.pressure)
cairo_set_source_rgb(cr, .8, .8, .2);
cairo_arc(cr, 0, 0,
1 + 10 * max(w->tool.pressure, w->tool.distance),
0, 2 * M_PI);
cairo_fill(cr);
cairo_restore(cr);
/* The line to indicate the origin */
if (w->tool.size_major) {
cairo_save(cr);
cairo_scale(cr, 1.0, 1.0);
cairo_translate(cr, w->tool.x, w->tool.y);
if (w->tool.rotation)
cairo_rotate(cr, w->tool.rotation * M_PI/180.0);
cairo_set_source_rgb(cr, .0, .0, .0);
cairo_move_to(cr, 0, 0);
cairo_rel_line_to(cr, 0, -w->tool.size_major * 2.5);
cairo_stroke(cr);
cairo_restore(cr);
}
/* tablet deltas */
mask = ARRAY_LENGTH(w->tool.deltas);
first = max(w->tool.ndeltas + 1, mask) - mask;
@ -1207,6 +1232,9 @@ handle_event_tablet(struct libinput_event *ev, struct window *w)
w->tool.distance = libinput_event_tablet_tool_get_distance(t);
w->tool.tilt_x = libinput_event_tablet_tool_get_tilt_x(t);
w->tool.tilt_y = libinput_event_tablet_tool_get_tilt_y(t);
w->tool.rotation = libinput_event_tablet_tool_get_rotation(t);
w->tool.size_major = libinput_event_tablet_tool_get_size_major(t);
w->tool.size_minor = libinput_event_tablet_tool_get_size_minor(t);
/* Add the delta to the last position and store them as abs
* coordinates */