mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-05-09 05:58:01 +02:00
tablet: change tilt axes to use degrees
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@who-t.net> Reviewed-by: Jason Gerecke <jason.gerecke@wacom.com>
This commit is contained in:
parent
0e87dc9af2
commit
c9abcb2e1c
5 changed files with 67 additions and 41 deletions
|
|
@ -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"
|
@image html tablet-axes.svg "Illustration of the distance, pressure and tilt axes"
|
||||||
|
|
||||||
The granularity and precision of these axes varies between tablet devices
|
The granularity and precision of the distance and pressure axes varies
|
||||||
and cannot usually be mapped into a physical unit.
|
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
|
libinput normalizes distance and pressure into the [0, 1] range.
|
||||||
axes into the [-1, 1] range with 0 as the neutral point.
|
|
||||||
|
|
||||||
While the normalization range is identical for these axes, a caller should
|
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
|
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 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
|
@section tablet-fake-proximity Handling of proximity events
|
||||||
|
|
||||||
libinput's @ref LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY events notify a caller
|
libinput's @ref LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY events notify a caller
|
||||||
|
|
|
||||||
|
|
@ -225,13 +225,22 @@ normalize_pressure(const struct input_absinfo *absinfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline double
|
static inline double
|
||||||
normalize_tilt(const struct input_absinfo *absinfo)
|
adjust_tilt(const struct input_absinfo *absinfo)
|
||||||
{
|
{
|
||||||
double range = absinfo->maximum - absinfo->minimum;
|
double range = absinfo->maximum - absinfo->minimum;
|
||||||
double value = (absinfo->value - absinfo->minimum) / range;
|
double value = (absinfo->value - absinfo->minimum) / range;
|
||||||
|
const int WACOM_MAX_DEGREES = 64;
|
||||||
|
|
||||||
/* Map to the (-1, 1) range */
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return value * WACOM_MAX_DEGREES;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int32_t
|
static inline int32_t
|
||||||
|
|
@ -398,17 +407,17 @@ tablet_handle_slider(struct tablet_dispatch *tablet,
|
||||||
return tablet->axes.slider;
|
return tablet->axes.slider;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct normalized_range_coords
|
static inline struct tilt_degrees
|
||||||
tablet_handle_tilt(struct tablet_dispatch *tablet,
|
tablet_handle_tilt(struct tablet_dispatch *tablet,
|
||||||
struct evdev_device *device)
|
struct evdev_device *device)
|
||||||
{
|
{
|
||||||
struct normalized_range_coords tilt;
|
struct tilt_degrees tilt;
|
||||||
const struct input_absinfo *absinfo;
|
const struct input_absinfo *absinfo;
|
||||||
|
|
||||||
if (bit_is_set(tablet->changed_axes,
|
if (bit_is_set(tablet->changed_axes,
|
||||||
LIBINPUT_TABLET_TOOL_AXIS_TILT_X)) {
|
LIBINPUT_TABLET_TOOL_AXIS_TILT_X)) {
|
||||||
absinfo = libevdev_get_abs_info(device->evdev, ABS_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)
|
if (device->left_handed.enabled)
|
||||||
tablet->axes.tilt.x *= -1;
|
tablet->axes.tilt.x *= -1;
|
||||||
}
|
}
|
||||||
|
|
@ -417,7 +426,7 @@ tablet_handle_tilt(struct tablet_dispatch *tablet,
|
||||||
if (bit_is_set(tablet->changed_axes,
|
if (bit_is_set(tablet->changed_axes,
|
||||||
LIBINPUT_TABLET_TOOL_AXIS_TILT_Y)) {
|
LIBINPUT_TABLET_TOOL_AXIS_TILT_Y)) {
|
||||||
absinfo = libevdev_get_abs_info(device->evdev, ABS_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)
|
if (device->left_handed.enabled)
|
||||||
tablet->axes.tilt.y *= -1;
|
tablet->axes.tilt.y *= -1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,11 @@ struct normalized_range_coords {
|
||||||
double x, y;
|
double x, y;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* A pair of angles in degrees */
|
||||||
|
struct tilt_degrees {
|
||||||
|
double x, y;
|
||||||
|
};
|
||||||
|
|
||||||
/* A threshold with an upper and lower limit */
|
/* A threshold with an upper and lower limit */
|
||||||
struct threshold {
|
struct threshold {
|
||||||
int upper;
|
int upper;
|
||||||
|
|
@ -74,7 +79,7 @@ struct tablet_axes {
|
||||||
struct normalized_coords delta;
|
struct normalized_coords delta;
|
||||||
double distance;
|
double distance;
|
||||||
double pressure;
|
double pressure;
|
||||||
struct normalized_range_coords tilt;
|
struct tilt_degrees tilt;
|
||||||
double rotation;
|
double rotation;
|
||||||
double slider;
|
double slider;
|
||||||
double wheel;
|
double wheel;
|
||||||
|
|
|
||||||
|
|
@ -1648,12 +1648,16 @@ libinput_event_tablet_tool_get_distance(struct libinput_event_tablet_tool *event
|
||||||
* @ingroup event_tablet
|
* @ingroup event_tablet
|
||||||
*
|
*
|
||||||
* Returns the current tilt along the X axis of the tablet's current logical
|
* 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.
|
* If this axis does not exist on the current tool, this function returns 0.
|
||||||
*
|
*
|
||||||
* @param event The libinput tablet tool event
|
* @param event The libinput tablet tool event
|
||||||
* @return The current value of the the axis
|
* @return The current value of the the axis in degrees
|
||||||
*/
|
*/
|
||||||
double
|
double
|
||||||
libinput_event_tablet_tool_get_tilt_x(struct libinput_event_tablet_tool *event);
|
libinput_event_tablet_tool_get_tilt_x(struct libinput_event_tablet_tool *event);
|
||||||
|
|
@ -1662,12 +1666,16 @@ libinput_event_tablet_tool_get_tilt_x(struct libinput_event_tablet_tool *event);
|
||||||
* @ingroup event_tablet
|
* @ingroup event_tablet
|
||||||
*
|
*
|
||||||
* Returns the current tilt along the Y axis of the tablet's current logical
|
* 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.
|
* If this axis does not exist on the current tool, this function returns 0.
|
||||||
*
|
*
|
||||||
* @param event The libinput tablet tool event
|
* @param event The libinput tablet tool event
|
||||||
* @return The current value of the the axis
|
* @return The current value of the the axis in degrees
|
||||||
*/
|
*/
|
||||||
double
|
double
|
||||||
libinput_event_tablet_tool_get_tilt_y(struct libinput_event_tablet_tool *event);
|
libinput_event_tablet_tool_get_tilt_y(struct libinput_event_tablet_tool *event);
|
||||||
|
|
|
||||||
|
|
@ -3081,7 +3081,7 @@ START_TEST(tilt_x)
|
||||||
struct axis_replacement axes[] = {
|
struct axis_replacement axes[] = {
|
||||||
{ ABS_DISTANCE, 10 },
|
{ ABS_DISTANCE, 10 },
|
||||||
{ ABS_PRESSURE, 0 },
|
{ ABS_PRESSURE, 0 },
|
||||||
{ ABS_TILT_X, 90 },
|
{ ABS_TILT_X, 10 },
|
||||||
{ ABS_TILT_Y, 0 },
|
{ ABS_TILT_Y, 0 },
|
||||||
{ -1, -1 }
|
{ -1, -1 }
|
||||||
};
|
};
|
||||||
|
|
@ -3097,19 +3097,18 @@ START_TEST(tilt_x)
|
||||||
tev = litest_is_tablet_event(event,
|
tev = litest_is_tablet_event(event,
|
||||||
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
|
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
|
||||||
|
|
||||||
/* 90% of the actual axis but mapped into a [-1, 1] range, so we
|
/* 90% of the actual axis but mapped into a [-64, 64] tilt range, so
|
||||||
* expect a pos. value of 80. Rounding errors in the scaling though,
|
* we expect 51 degrees ± rounding errors */
|
||||||
* we'll get something between 0.79 and 0.80 */
|
|
||||||
tx = libinput_event_tablet_tool_get_tilt_x(tev);
|
tx = libinput_event_tablet_tool_get_tilt_x(tev);
|
||||||
ck_assert_double_gt(tx, 0.79);
|
ck_assert_double_le(tx, -50);
|
||||||
ck_assert_double_le(tx, 0.80);
|
ck_assert_double_ge(tx, -52);
|
||||||
|
|
||||||
ty = libinput_event_tablet_tool_get_tilt_y(tev);
|
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);
|
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_DISTANCE, 0);
|
||||||
litest_axis_set_value(axes, ABS_PRESSURE, 1);
|
litest_axis_set_value(axes, ABS_PRESSURE, 1);
|
||||||
|
|
@ -3123,19 +3122,20 @@ START_TEST(tilt_x)
|
||||||
LIBINPUT_EVENT_TABLET_TOOL_AXIS);
|
LIBINPUT_EVENT_TABLET_TOOL_AXIS);
|
||||||
|
|
||||||
tx = libinput_event_tablet_tool_get_tilt_x(tev);
|
tx = libinput_event_tablet_tool_get_tilt_x(tev);
|
||||||
ck_assert_double_gt(tx, expected_tx - 0.1);
|
ck_assert_double_ge(tx, expected_tx - 2);
|
||||||
ck_assert_double_lt(tx, expected_tx + 0.1);
|
ck_assert_double_le(tx, expected_tx + 2);
|
||||||
|
|
||||||
ty = libinput_event_tablet_tool_get_tilt_y(tev);
|
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);
|
libinput_event_destroy(event);
|
||||||
|
|
||||||
expected_tx += 0.1;
|
expected_tx = tx + 6.04;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the last event must reach the max */
|
/* the last event must reach the max */
|
||||||
ck_assert_double_eq(tx, 1.0);
|
ck_assert_double_ge(tx, 63.0);
|
||||||
|
ck_assert_double_le(tx, 64.0);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
@ -3149,7 +3149,7 @@ START_TEST(tilt_y)
|
||||||
{ ABS_DISTANCE, 10 },
|
{ ABS_DISTANCE, 10 },
|
||||||
{ ABS_PRESSURE, 0 },
|
{ ABS_PRESSURE, 0 },
|
||||||
{ ABS_TILT_X, 0 },
|
{ ABS_TILT_X, 0 },
|
||||||
{ ABS_TILT_Y, 90 },
|
{ ABS_TILT_Y, 10 },
|
||||||
{ -1, -1 }
|
{ -1, -1 }
|
||||||
};
|
};
|
||||||
double tx, ty;
|
double tx, ty;
|
||||||
|
|
@ -3164,19 +3164,18 @@ START_TEST(tilt_y)
|
||||||
tev = litest_is_tablet_event(event,
|
tev = litest_is_tablet_event(event,
|
||||||
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
|
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
|
||||||
|
|
||||||
/* 90% of the actual axis but mapped into a [-1, 1] range, so we
|
/* 90% of the actual axis but mapped into a [-64, 64] tilt range, so
|
||||||
* expect a pos. value of 80. Rounding errors in the scaling though,
|
* we expect 50 degrees ± rounding errors */
|
||||||
* we'll get something between 0.79 and 0.80 */
|
|
||||||
ty = libinput_event_tablet_tool_get_tilt_y(tev);
|
ty = libinput_event_tablet_tool_get_tilt_y(tev);
|
||||||
ck_assert_double_gt(ty, 0.79);
|
ck_assert_double_le(ty, -50);
|
||||||
ck_assert_double_le(ty, 0.80);
|
ck_assert_double_ge(ty, -52);
|
||||||
|
|
||||||
tx = libinput_event_tablet_tool_get_tilt_x(tev);
|
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);
|
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_DISTANCE, 0);
|
||||||
litest_axis_set_value(axes, ABS_PRESSURE, 1);
|
litest_axis_set_value(axes, ABS_PRESSURE, 1);
|
||||||
|
|
@ -3190,19 +3189,20 @@ START_TEST(tilt_y)
|
||||||
LIBINPUT_EVENT_TABLET_TOOL_AXIS);
|
LIBINPUT_EVENT_TABLET_TOOL_AXIS);
|
||||||
|
|
||||||
ty = libinput_event_tablet_tool_get_tilt_y(tev);
|
ty = libinput_event_tablet_tool_get_tilt_y(tev);
|
||||||
ck_assert_double_gt(ty, expected_ty - 0.1);
|
ck_assert_double_ge(ty, expected_ty - 2);
|
||||||
ck_assert_double_lt(ty, expected_ty + 0.1);
|
ck_assert_double_le(ty, expected_ty + 2);
|
||||||
|
|
||||||
tx = libinput_event_tablet_tool_get_tilt_x(tev);
|
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);
|
libinput_event_destroy(event);
|
||||||
|
|
||||||
expected_ty += 0.1;
|
expected_ty = ty + 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the last event must reach the max */
|
/* the last event must reach the max */
|
||||||
ck_assert_double_eq(ty, 1.0);
|
ck_assert_double_ge(ty, 63.0);
|
||||||
|
ck_assert_double_le(tx, 64.0);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue