mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-01-05 04:20:13 +01:00
Merge branch 'wip/tablet-wobbly-lines-v2'
This commit is contained in:
commit
078d5cb332
4 changed files with 454 additions and 224 deletions
|
|
@ -76,6 +76,56 @@ tablet_force_button_presses(struct tablet_dispatch *tablet)
|
|||
}
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
tablet_history_size(const struct tablet_dispatch *tablet)
|
||||
{
|
||||
return ARRAY_LENGTH(tablet->history.samples);
|
||||
}
|
||||
|
||||
static inline void
|
||||
tablet_history_reset(struct tablet_dispatch *tablet)
|
||||
{
|
||||
tablet->history.count = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
tablet_history_push(struct tablet_dispatch *tablet,
|
||||
const struct tablet_axes *axes)
|
||||
{
|
||||
unsigned int index = (tablet->history.index + 1) %
|
||||
tablet_history_size(tablet);
|
||||
|
||||
tablet->history.samples[index] = *axes;
|
||||
tablet->history.index = index;
|
||||
tablet->history.count = min(tablet->history.count + 1,
|
||||
tablet_history_size(tablet));
|
||||
|
||||
if (tablet->history.count < tablet_history_size(tablet))
|
||||
tablet_history_push(tablet, axes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a previous axis state, where index of 0 means "most recent", 1 is
|
||||
* "one before most recent", etc.
|
||||
*/
|
||||
static inline const struct tablet_axes*
|
||||
tablet_history_get(const struct tablet_dispatch *tablet, unsigned int index)
|
||||
{
|
||||
size_t sz = tablet_history_size(tablet);
|
||||
|
||||
assert(index < sz);
|
||||
assert(index < tablet->history.count);
|
||||
|
||||
index = (tablet->history.index + sz - index) % sz;
|
||||
return &tablet->history.samples[index];
|
||||
}
|
||||
|
||||
static inline void
|
||||
tablet_reset_changed_axes(struct tablet_dispatch *tablet)
|
||||
{
|
||||
memset(tablet->changed_axes, 0, sizeof(tablet->changed_axes));
|
||||
}
|
||||
|
||||
static bool
|
||||
tablet_device_has_axis(struct tablet_dispatch *tablet,
|
||||
enum libinput_tablet_tool_axis axis)
|
||||
|
|
@ -339,17 +389,14 @@ normalize_wheel(struct tablet_dispatch *tablet,
|
|||
}
|
||||
|
||||
static inline void
|
||||
tablet_handle_xy(struct tablet_dispatch *tablet,
|
||||
struct evdev_device *device,
|
||||
struct device_coords *point_out,
|
||||
struct device_coords *delta_out)
|
||||
tablet_update_xy(struct tablet_dispatch *tablet,
|
||||
struct evdev_device *device)
|
||||
{
|
||||
struct device_coords point;
|
||||
struct device_coords delta = { 0, 0 };
|
||||
const struct input_absinfo *absinfo;
|
||||
int value;
|
||||
|
||||
if (bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_X)) {
|
||||
if (bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_X) ||
|
||||
bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_Y)) {
|
||||
absinfo = libevdev_get_abs_info(device->evdev, ABS_X);
|
||||
|
||||
if (device->left_handed.enabled)
|
||||
|
|
@ -357,14 +404,8 @@ tablet_handle_xy(struct tablet_dispatch *tablet,
|
|||
else
|
||||
value = absinfo->value;
|
||||
|
||||
if (!tablet_has_status(tablet,
|
||||
TABLET_TOOL_ENTERING_PROXIMITY))
|
||||
delta.x = value - tablet->axes.point.x;
|
||||
tablet->axes.point.x = value;
|
||||
}
|
||||
point.x = tablet->axes.point.x;
|
||||
|
||||
if (bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_Y)) {
|
||||
absinfo = libevdev_get_abs_info(device->evdev, ABS_Y);
|
||||
|
||||
if (device->left_handed.enabled)
|
||||
|
|
@ -372,31 +413,35 @@ tablet_handle_xy(struct tablet_dispatch *tablet,
|
|||
else
|
||||
value = absinfo->value;
|
||||
|
||||
if (!tablet_has_status(tablet,
|
||||
TABLET_TOOL_ENTERING_PROXIMITY))
|
||||
delta.y = value - tablet->axes.point.y;
|
||||
tablet->axes.point.y = value;
|
||||
|
||||
evdev_transform_absolute(device, &tablet->axes.point);
|
||||
}
|
||||
point.y = tablet->axes.point.y;
|
||||
|
||||
evdev_transform_absolute(device, &point);
|
||||
evdev_transform_relative(device, &delta);
|
||||
|
||||
*delta_out = delta;
|
||||
*point_out = point;
|
||||
}
|
||||
|
||||
static inline struct normalized_coords
|
||||
tool_process_delta(struct libinput_tablet_tool *tool,
|
||||
const struct evdev_device *device,
|
||||
const struct device_coords *delta,
|
||||
uint64_t time)
|
||||
tablet_tool_process_delta(struct tablet_dispatch *tablet,
|
||||
struct libinput_tablet_tool *tool,
|
||||
const struct evdev_device *device,
|
||||
struct tablet_axes *axes,
|
||||
uint64_t time)
|
||||
{
|
||||
const struct normalized_coords zero = { 0.0, 0.0 };
|
||||
struct device_coords delta = { 0, 0 };
|
||||
struct device_float_coords accel;
|
||||
|
||||
accel.x = 1.0 * delta->x;
|
||||
accel.y = 1.0 * delta->y;
|
||||
if (!tablet_has_status(tablet,
|
||||
TABLET_TOOL_ENTERING_PROXIMITY) &&
|
||||
(bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_X) ||
|
||||
bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_Y))) {
|
||||
delta.x = axes->point.x - tablet->last_smooth_point.x;
|
||||
delta.y = axes->point.y - tablet->last_smooth_point.y;
|
||||
}
|
||||
|
||||
tablet->last_smooth_point = axes->point;
|
||||
|
||||
accel.x = 1.0 * delta.x;
|
||||
accel.y = 1.0 * delta.y;
|
||||
|
||||
if (device_float_is_zero(accel))
|
||||
return zero;
|
||||
|
|
@ -407,8 +452,8 @@ tool_process_delta(struct libinput_tablet_tool *tool,
|
|||
time);
|
||||
}
|
||||
|
||||
static inline double
|
||||
tablet_handle_pressure(struct tablet_dispatch *tablet,
|
||||
static inline void
|
||||
tablet_update_pressure(struct tablet_dispatch *tablet,
|
||||
struct evdev_device *device,
|
||||
struct libinput_tablet_tool *tool)
|
||||
{
|
||||
|
|
@ -419,12 +464,10 @@ tablet_handle_pressure(struct tablet_dispatch *tablet,
|
|||
absinfo = libevdev_get_abs_info(device->evdev, ABS_PRESSURE);
|
||||
tablet->axes.pressure = normalize_pressure(absinfo, tool);
|
||||
}
|
||||
|
||||
return tablet->axes.pressure;
|
||||
}
|
||||
|
||||
static inline double
|
||||
tablet_handle_distance(struct tablet_dispatch *tablet,
|
||||
static inline void
|
||||
tablet_update_distance(struct tablet_dispatch *tablet,
|
||||
struct evdev_device *device)
|
||||
{
|
||||
const struct input_absinfo *absinfo;
|
||||
|
|
@ -434,12 +477,10 @@ tablet_handle_distance(struct tablet_dispatch *tablet,
|
|||
absinfo = libevdev_get_abs_info(device->evdev, ABS_DISTANCE);
|
||||
tablet->axes.distance = normalize_distance(absinfo);
|
||||
}
|
||||
|
||||
return tablet->axes.distance;
|
||||
}
|
||||
|
||||
static inline double
|
||||
tablet_handle_slider(struct tablet_dispatch *tablet,
|
||||
static inline void
|
||||
tablet_update_slider(struct tablet_dispatch *tablet,
|
||||
struct evdev_device *device)
|
||||
{
|
||||
const struct input_absinfo *absinfo;
|
||||
|
|
@ -449,40 +490,36 @@ tablet_handle_slider(struct tablet_dispatch *tablet,
|
|||
absinfo = libevdev_get_abs_info(device->evdev, ABS_WHEEL);
|
||||
tablet->axes.slider = normalize_slider(absinfo);
|
||||
}
|
||||
|
||||
return tablet->axes.slider;
|
||||
}
|
||||
|
||||
static inline struct tilt_degrees
|
||||
tablet_handle_tilt(struct tablet_dispatch *tablet,
|
||||
static inline void
|
||||
tablet_update_tilt(struct tablet_dispatch *tablet,
|
||||
struct evdev_device *device)
|
||||
{
|
||||
struct tilt_degrees tilt;
|
||||
const struct input_absinfo *absinfo;
|
||||
|
||||
/* mouse rotation resets tilt to 0 so always fetch both axes if
|
||||
* either has changed */
|
||||
if (bit_is_set(tablet->changed_axes,
|
||||
LIBINPUT_TABLET_TOOL_AXIS_TILT_X)) {
|
||||
LIBINPUT_TABLET_TOOL_AXIS_TILT_X) ||
|
||||
bit_is_set(tablet->changed_axes,
|
||||
LIBINPUT_TABLET_TOOL_AXIS_TILT_Y)) {
|
||||
|
||||
absinfo = libevdev_get_abs_info(device->evdev, ABS_TILT_X);
|
||||
tablet->axes.tilt.x = adjust_tilt(absinfo);
|
||||
if (device->left_handed.enabled)
|
||||
tablet->axes.tilt.x *= -1;
|
||||
}
|
||||
tilt.x = tablet->axes.tilt.x;
|
||||
|
||||
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 = adjust_tilt(absinfo);
|
||||
if (device->left_handed.enabled)
|
||||
tablet->axes.tilt.y *= -1;
|
||||
}
|
||||
tilt.y = tablet->axes.tilt.y;
|
||||
|
||||
return tilt;
|
||||
if (device->left_handed.enabled) {
|
||||
tablet->axes.tilt.x *= -1;
|
||||
tablet->axes.tilt.y *= -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline double
|
||||
tablet_handle_artpen_rotation(struct tablet_dispatch *tablet,
|
||||
static inline void
|
||||
tablet_update_artpen_rotation(struct tablet_dispatch *tablet,
|
||||
struct evdev_device *device)
|
||||
{
|
||||
const struct input_absinfo *absinfo;
|
||||
|
|
@ -494,12 +531,10 @@ tablet_handle_artpen_rotation(struct tablet_dispatch *tablet,
|
|||
/* artpen has 0 with buttons pointing east */
|
||||
tablet->axes.rotation = convert_to_degrees(absinfo, 90);
|
||||
}
|
||||
|
||||
return tablet->axes.rotation;
|
||||
}
|
||||
|
||||
static inline double
|
||||
tablet_handle_mouse_rotation(struct tablet_dispatch *tablet,
|
||||
static inline void
|
||||
tablet_update_mouse_rotation(struct tablet_dispatch *tablet,
|
||||
struct evdev_device *device)
|
||||
{
|
||||
if (bit_is_set(tablet->changed_axes,
|
||||
|
|
@ -508,28 +543,76 @@ tablet_handle_mouse_rotation(struct tablet_dispatch *tablet,
|
|||
LIBINPUT_TABLET_TOOL_AXIS_TILT_Y)) {
|
||||
convert_tilt_to_rotation(tablet);
|
||||
}
|
||||
|
||||
return tablet->axes.rotation;
|
||||
}
|
||||
|
||||
static inline double
|
||||
tablet_handle_wheel(struct tablet_dispatch *tablet,
|
||||
struct evdev_device *device,
|
||||
int *wheel_discrete)
|
||||
static inline void
|
||||
tablet_update_rotation(struct tablet_dispatch *tablet,
|
||||
struct evdev_device *device)
|
||||
{
|
||||
/* We must check ROTATION_Z after TILT_X/Y so that the tilt axes are
|
||||
* already normalized and set if we have the mouse/lens tool */
|
||||
if (tablet->current_tool_type == LIBINPUT_TABLET_TOOL_TYPE_MOUSE ||
|
||||
tablet->current_tool_type == LIBINPUT_TABLET_TOOL_TYPE_LENS) {
|
||||
tablet_update_mouse_rotation(tablet, device);
|
||||
clear_bit(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_TILT_X);
|
||||
clear_bit(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_TILT_Y);
|
||||
tablet->axes.tilt.x = 0;
|
||||
tablet->axes.tilt.y = 0;
|
||||
tablet->axes.rotation = tablet->axes.rotation;
|
||||
|
||||
/* tilt is already converted to left-handed, so mouse
|
||||
* rotation is converted to left-handed automatically */
|
||||
} else {
|
||||
|
||||
tablet_update_artpen_rotation(tablet, device);
|
||||
|
||||
if (device->left_handed.enabled) {
|
||||
double r = tablet->axes.rotation;
|
||||
tablet->axes.rotation = fmod(180 + r, 360);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
tablet_update_wheel(struct tablet_dispatch *tablet,
|
||||
struct evdev_device *device)
|
||||
{
|
||||
int a;
|
||||
|
||||
a = LIBINPUT_TABLET_TOOL_AXIS_REL_WHEEL;
|
||||
if (bit_is_set(tablet->changed_axes, a)) {
|
||||
*wheel_discrete = tablet->axes.wheel_discrete;
|
||||
/* tablet->axes.wheel_discrete is already set */
|
||||
tablet->axes.wheel = normalize_wheel(tablet,
|
||||
tablet->axes.wheel_discrete);
|
||||
} else {
|
||||
tablet->axes.wheel = 0;
|
||||
*wheel_discrete = 0;
|
||||
tablet->axes.wheel_discrete = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_smoothen_axes(const struct tablet_dispatch *tablet,
|
||||
struct tablet_axes *axes)
|
||||
{
|
||||
size_t i;
|
||||
size_t count = tablet_history_size(tablet);
|
||||
struct tablet_axes smooth = { 0 };
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
const struct tablet_axes *a = tablet_history_get(tablet, i);
|
||||
|
||||
smooth.point.x += a->point.x;
|
||||
smooth.point.y += a->point.y;
|
||||
|
||||
smooth.tilt.x += a->tilt.x;
|
||||
smooth.tilt.y += a->tilt.y;
|
||||
}
|
||||
|
||||
return tablet->axes.wheel;
|
||||
axes->point.x = smooth.point.x/count;
|
||||
axes->point.y = smooth.point.y/count;
|
||||
|
||||
axes->tilt.x = smooth.tilt.x/count;
|
||||
axes->tilt.y = smooth.tilt.y/count;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -541,41 +624,44 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet,
|
|||
{
|
||||
struct tablet_axes axes = {0};
|
||||
const char tmp[sizeof(tablet->changed_axes)] = {0};
|
||||
struct device_coords delta;
|
||||
bool rc = false;
|
||||
|
||||
if (memcmp(tmp, tablet->changed_axes, sizeof(tmp)) == 0)
|
||||
return false;
|
||||
|
||||
tablet_handle_xy(tablet, device, &axes.point, &delta);
|
||||
axes.pressure = tablet_handle_pressure(tablet, device, tool);
|
||||
axes.distance = tablet_handle_distance(tablet, device);
|
||||
axes.slider = tablet_handle_slider(tablet, device);
|
||||
axes.tilt = tablet_handle_tilt(tablet, device);
|
||||
axes.delta = tool_process_delta(tool, device, &delta, time);
|
||||
|
||||
/* We must check ROTATION_Z after TILT_X/Y so that the tilt axes are
|
||||
* already normalized and set if we have the mouse/lens tool */
|
||||
if (tablet->current_tool_type == LIBINPUT_TABLET_TOOL_TYPE_MOUSE ||
|
||||
tablet->current_tool_type == LIBINPUT_TABLET_TOOL_TYPE_LENS) {
|
||||
axes.rotation = tablet_handle_mouse_rotation(tablet, device);
|
||||
clear_bit(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_TILT_X);
|
||||
clear_bit(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_TILT_Y);
|
||||
axes.tilt.x = 0;
|
||||
axes.tilt.y = 0;
|
||||
|
||||
/* tilt is already converted to left-handed, so mouse
|
||||
* rotation is converted to left-handed automatically */
|
||||
} else {
|
||||
axes.rotation = tablet_handle_artpen_rotation(tablet, device);
|
||||
if (device->left_handed.enabled)
|
||||
axes.rotation = fmod(180 + axes.rotation, 360);
|
||||
if (memcmp(tmp, tablet->changed_axes, sizeof(tmp)) == 0) {
|
||||
axes = tablet->axes;
|
||||
goto out;
|
||||
}
|
||||
|
||||
axes.wheel = tablet_handle_wheel(tablet, device, &axes.wheel_discrete);
|
||||
tablet_update_xy(tablet, device);
|
||||
tablet_update_pressure(tablet, device, tool);
|
||||
tablet_update_distance(tablet, device);
|
||||
tablet_update_slider(tablet, device);
|
||||
tablet_update_tilt(tablet, device);
|
||||
tablet_update_wheel(tablet, device);
|
||||
/* We must check ROTATION_Z after TILT_X/Y so that the tilt axes are
|
||||
* already normalized and set if we have the mouse/lens tool */
|
||||
tablet_update_rotation(tablet, device);
|
||||
|
||||
axes.point = tablet->axes.point;
|
||||
axes.pressure = tablet->axes.pressure;
|
||||
axes.distance = tablet->axes.distance;
|
||||
axes.slider = tablet->axes.slider;
|
||||
axes.tilt = tablet->axes.tilt;
|
||||
axes.wheel = tablet->axes.wheel;
|
||||
axes.wheel_discrete = tablet->axes.wheel_discrete;
|
||||
axes.rotation = tablet->axes.rotation;
|
||||
|
||||
rc = true;
|
||||
|
||||
out:
|
||||
tablet_history_push(tablet, &tablet->axes);
|
||||
tablet_smoothen_axes(tablet, &axes);
|
||||
|
||||
/* The delta relies on the last *smooth* point, so we do it last */
|
||||
axes.delta = tablet_tool_process_delta(tablet, tool, device, &axes, time);
|
||||
|
||||
*axes_out = axes;
|
||||
|
||||
return true;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1270,22 +1356,169 @@ tablet_update_proximity_state(struct tablet_dispatch *tablet,
|
|||
tablet_set_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
tablet_send_proximity_in(struct tablet_dispatch *tablet,
|
||||
struct libinput_tablet_tool *tool,
|
||||
struct evdev_device *device,
|
||||
struct tablet_axes *axes,
|
||||
uint64_t time)
|
||||
{
|
||||
if (!tablet_has_status(tablet, TABLET_TOOL_ENTERING_PROXIMITY))
|
||||
return false;
|
||||
|
||||
tablet_notify_proximity(&device->base,
|
||||
time,
|
||||
tool,
|
||||
LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN,
|
||||
tablet->changed_axes,
|
||||
axes);
|
||||
tablet_unset_status(tablet, TABLET_TOOL_ENTERING_PROXIMITY);
|
||||
tablet_unset_status(tablet, TABLET_AXES_UPDATED);
|
||||
|
||||
tablet_reset_changed_axes(tablet);
|
||||
axes->delta.x = 0;
|
||||
axes->delta.y = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
tablet_send_proximity_out(struct tablet_dispatch *tablet,
|
||||
struct libinput_tablet_tool *tool,
|
||||
struct evdev_device *device,
|
||||
struct tablet_axes *axes,
|
||||
uint64_t time)
|
||||
{
|
||||
if (!tablet_has_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY))
|
||||
return false;
|
||||
|
||||
tablet_notify_proximity(&device->base,
|
||||
time,
|
||||
tool,
|
||||
LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT,
|
||||
tablet->changed_axes,
|
||||
axes);
|
||||
|
||||
tablet_set_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY);
|
||||
tablet_unset_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY);
|
||||
|
||||
tablet_reset_changed_axes(tablet);
|
||||
axes->delta.x = 0;
|
||||
axes->delta.y = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
tablet_send_tip(struct tablet_dispatch *tablet,
|
||||
struct libinput_tablet_tool *tool,
|
||||
struct evdev_device *device,
|
||||
struct tablet_axes *axes,
|
||||
uint64_t time)
|
||||
{
|
||||
if (tablet_has_status(tablet, TABLET_TOOL_ENTERING_CONTACT)) {
|
||||
tablet_notify_tip(&device->base,
|
||||
time,
|
||||
tool,
|
||||
LIBINPUT_TABLET_TOOL_TIP_DOWN,
|
||||
tablet->changed_axes,
|
||||
axes);
|
||||
tablet_unset_status(tablet, TABLET_AXES_UPDATED);
|
||||
tablet_unset_status(tablet, TABLET_TOOL_ENTERING_CONTACT);
|
||||
tablet_set_status(tablet, TABLET_TOOL_IN_CONTACT);
|
||||
|
||||
tablet_reset_changed_axes(tablet);
|
||||
axes->delta.x = 0;
|
||||
axes->delta.y = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (tablet_has_status(tablet, TABLET_TOOL_LEAVING_CONTACT)) {
|
||||
tablet_notify_tip(&device->base,
|
||||
time,
|
||||
tool,
|
||||
LIBINPUT_TABLET_TOOL_TIP_UP,
|
||||
tablet->changed_axes,
|
||||
axes);
|
||||
tablet_unset_status(tablet, TABLET_AXES_UPDATED);
|
||||
tablet_unset_status(tablet, TABLET_TOOL_LEAVING_CONTACT);
|
||||
tablet_unset_status(tablet, TABLET_TOOL_IN_CONTACT);
|
||||
|
||||
tablet_reset_changed_axes(tablet);
|
||||
axes->delta.x = 0;
|
||||
axes->delta.y = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void
|
||||
tablet_send_axes(struct tablet_dispatch *tablet,
|
||||
struct libinput_tablet_tool *tool,
|
||||
struct evdev_device *device,
|
||||
struct tablet_axes *axes,
|
||||
uint64_t time)
|
||||
{
|
||||
enum libinput_tablet_tool_tip_state tip_state;
|
||||
|
||||
if (!tablet_has_status(tablet, TABLET_AXES_UPDATED))
|
||||
return;
|
||||
|
||||
if (tablet_has_status(tablet,
|
||||
TABLET_TOOL_IN_CONTACT))
|
||||
tip_state = LIBINPUT_TABLET_TOOL_TIP_DOWN;
|
||||
else
|
||||
tip_state = LIBINPUT_TABLET_TOOL_TIP_UP;
|
||||
|
||||
tablet_notify_axis(&device->base,
|
||||
time,
|
||||
tool,
|
||||
tip_state,
|
||||
tablet->changed_axes,
|
||||
axes);
|
||||
tablet_unset_status(tablet, TABLET_AXES_UPDATED);
|
||||
tablet_reset_changed_axes(tablet);
|
||||
axes->delta.x = 0;
|
||||
axes->delta.y = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
tablet_send_buttons(struct tablet_dispatch *tablet,
|
||||
struct libinput_tablet_tool *tool,
|
||||
struct evdev_device *device,
|
||||
uint64_t time)
|
||||
{
|
||||
if (tablet_has_status(tablet, TABLET_BUTTONS_RELEASED)) {
|
||||
tablet_notify_buttons(tablet,
|
||||
device,
|
||||
time,
|
||||
tool,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
tablet_unset_status(tablet, TABLET_BUTTONS_RELEASED);
|
||||
}
|
||||
|
||||
if (tablet_has_status(tablet, TABLET_BUTTONS_PRESSED)) {
|
||||
tablet_notify_buttons(tablet,
|
||||
device,
|
||||
time,
|
||||
tool,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
tablet_unset_status(tablet, TABLET_BUTTONS_PRESSED);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_send_axis_proximity_tip_down_events(struct tablet_dispatch *tablet,
|
||||
struct evdev_device *device,
|
||||
struct libinput_tablet_tool *tool,
|
||||
uint64_t time)
|
||||
tablet_send_events(struct tablet_dispatch *tablet,
|
||||
struct libinput_tablet_tool *tool,
|
||||
struct evdev_device *device,
|
||||
uint64_t time)
|
||||
{
|
||||
struct tablet_axes axes = {0};
|
||||
|
||||
/* We need to make sure that we check that the tool is not out of
|
||||
* proximity before we send any axis updates. This is because many
|
||||
* tablets will send axis events with incorrect values if the tablet
|
||||
* tool is close enough so that the tablet can partially detect that
|
||||
* it's there, but can't properly receive any data from the tool. */
|
||||
if (tablet_has_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY))
|
||||
goto out;
|
||||
else if (tablet_has_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY)) {
|
||||
if (tablet_has_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY)) {
|
||||
/* Tool is leaving proximity, we can't rely on the last axis
|
||||
* information (it'll be mostly 0), so we just get the
|
||||
* current state and skip over updating the axes.
|
||||
|
|
@ -1295,66 +1528,26 @@ tablet_send_axis_proximity_tip_down_events(struct tablet_dispatch *tablet,
|
|||
/* Dont' send an axis event, but we may have a tip event
|
||||
* update */
|
||||
tablet_unset_status(tablet, TABLET_AXES_UPDATED);
|
||||
} else if (!tablet_check_notify_axes(tablet,
|
||||
device,
|
||||
tool,
|
||||
&axes,
|
||||
time)) {
|
||||
goto out;
|
||||
} else {
|
||||
tablet_check_notify_axes(tablet, device, tool, &axes, time);
|
||||
}
|
||||
|
||||
if (tablet_has_status(tablet, TABLET_TOOL_ENTERING_PROXIMITY)) {
|
||||
tablet_notify_proximity(&device->base,
|
||||
time,
|
||||
tool,
|
||||
LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN,
|
||||
tablet->changed_axes,
|
||||
&axes);
|
||||
tablet_unset_status(tablet, TABLET_TOOL_ENTERING_PROXIMITY);
|
||||
tablet_unset_status(tablet, TABLET_AXES_UPDATED);
|
||||
}
|
||||
assert(tablet->axes.delta.x == 0);
|
||||
assert(tablet->axes.delta.y == 0);
|
||||
|
||||
if (tablet_has_status(tablet, TABLET_TOOL_ENTERING_CONTACT)) {
|
||||
tablet_notify_tip(&device->base,
|
||||
time,
|
||||
tool,
|
||||
LIBINPUT_TABLET_TOOL_TIP_DOWN,
|
||||
tablet->changed_axes,
|
||||
&tablet->axes);
|
||||
tablet_unset_status(tablet, TABLET_AXES_UPDATED);
|
||||
tablet_unset_status(tablet, TABLET_TOOL_ENTERING_CONTACT);
|
||||
tablet_set_status(tablet, TABLET_TOOL_IN_CONTACT);
|
||||
} else if (tablet_has_status(tablet, TABLET_TOOL_LEAVING_CONTACT)) {
|
||||
tablet_notify_tip(&device->base,
|
||||
time,
|
||||
tool,
|
||||
LIBINPUT_TABLET_TOOL_TIP_UP,
|
||||
tablet->changed_axes,
|
||||
&tablet->axes);
|
||||
tablet_unset_status(tablet, TABLET_AXES_UPDATED);
|
||||
tablet_unset_status(tablet, TABLET_TOOL_LEAVING_CONTACT);
|
||||
tablet_unset_status(tablet, TABLET_TOOL_IN_CONTACT);
|
||||
} else if (tablet_has_status(tablet, TABLET_AXES_UPDATED)) {
|
||||
enum libinput_tablet_tool_tip_state tip_state;
|
||||
tablet_send_proximity_in(tablet, tool, device, &axes, time);
|
||||
if (!tablet_send_tip(tablet, tool, device, &axes, time))
|
||||
tablet_send_axes(tablet, tool, device, &axes, time);
|
||||
|
||||
if (tablet_has_status(tablet,
|
||||
TABLET_TOOL_IN_CONTACT))
|
||||
tip_state = LIBINPUT_TABLET_TOOL_TIP_DOWN;
|
||||
else
|
||||
tip_state = LIBINPUT_TABLET_TOOL_TIP_UP;
|
||||
|
||||
tablet_notify_axis(&device->base,
|
||||
time,
|
||||
tool,
|
||||
tip_state,
|
||||
tablet->changed_axes,
|
||||
&axes);
|
||||
tablet_unset_status(tablet, TABLET_AXES_UPDATED);
|
||||
}
|
||||
|
||||
out:
|
||||
memset(tablet->changed_axes, 0, sizeof(tablet->changed_axes));
|
||||
tablet_unset_status(tablet, TABLET_TOOL_ENTERING_CONTACT);
|
||||
tablet_reset_changed_axes(tablet);
|
||||
|
||||
tablet_send_buttons(tablet, tool, device, time);
|
||||
|
||||
if (tablet_send_proximity_out(tablet, tool, device, &axes, time)) {
|
||||
tablet_change_to_left_handed(device);
|
||||
tablet_history_reset(tablet);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1397,43 +1590,7 @@ tablet_flush(struct tablet_dispatch *tablet,
|
|||
sanitize_tablet_axes(tablet, tool);
|
||||
}
|
||||
|
||||
tablet_send_axis_proximity_tip_down_events(tablet,
|
||||
device,
|
||||
tool,
|
||||
time);
|
||||
|
||||
if (tablet_has_status(tablet, TABLET_BUTTONS_RELEASED)) {
|
||||
tablet_notify_buttons(tablet,
|
||||
device,
|
||||
time,
|
||||
tool,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
tablet_unset_status(tablet, TABLET_BUTTONS_RELEASED);
|
||||
}
|
||||
|
||||
if (tablet_has_status(tablet, TABLET_BUTTONS_PRESSED)) {
|
||||
tablet_notify_buttons(tablet,
|
||||
device,
|
||||
time,
|
||||
tool,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
tablet_unset_status(tablet, TABLET_BUTTONS_PRESSED);
|
||||
}
|
||||
|
||||
if (tablet_has_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY)) {
|
||||
memset(tablet->changed_axes, 0, sizeof(tablet->changed_axes));
|
||||
tablet_notify_proximity(&device->base,
|
||||
time,
|
||||
tool,
|
||||
LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT,
|
||||
tablet->changed_axes,
|
||||
&tablet->axes);
|
||||
|
||||
tablet_set_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY);
|
||||
tablet_unset_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY);
|
||||
|
||||
tablet_change_to_left_handed(device);
|
||||
}
|
||||
tablet_send_events(tablet, tool, device, time);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@
|
|||
#define LIBINPUT_TOOL_NONE 0
|
||||
#define LIBINPUT_TABLET_TOOL_TYPE_MAX LIBINPUT_TABLET_TOOL_TYPE_LENS
|
||||
|
||||
#define TABLET_HISTORY_LENGTH 4
|
||||
|
||||
enum tablet_status {
|
||||
TABLET_NONE = 0,
|
||||
TABLET_AXES_UPDATED = 1 << 0,
|
||||
|
|
@ -53,7 +55,14 @@ struct tablet_dispatch {
|
|||
struct evdev_device *device;
|
||||
unsigned int status;
|
||||
unsigned char changed_axes[NCHARS(LIBINPUT_TABLET_TOOL_AXIS_MAX + 1)];
|
||||
struct tablet_axes axes;
|
||||
struct tablet_axes axes; /* for assembling the current state */
|
||||
struct device_coords last_smooth_point;
|
||||
struct {
|
||||
unsigned int index;
|
||||
unsigned int count;
|
||||
struct tablet_axes samples[TABLET_HISTORY_LENGTH];
|
||||
} history;
|
||||
|
||||
unsigned char axis_caps[NCHARS(LIBINPUT_TABLET_TOOL_AXIS_MAX + 1)];
|
||||
int current_value[LIBINPUT_TABLET_TOOL_AXIS_MAX + 1];
|
||||
int prev_value[LIBINPUT_TABLET_TOOL_AXIS_MAX + 1];
|
||||
|
|
|
|||
|
|
@ -99,18 +99,6 @@ struct wheel_tilt_flags {
|
|||
bool vertical, horizontal;
|
||||
};
|
||||
|
||||
struct tablet_axes {
|
||||
struct device_coords point;
|
||||
struct normalized_coords delta;
|
||||
double distance;
|
||||
double pressure;
|
||||
struct tilt_degrees tilt;
|
||||
double rotation;
|
||||
double slider;
|
||||
double wheel;
|
||||
int wheel_discrete;
|
||||
};
|
||||
|
||||
struct libinput_interface_backend {
|
||||
int (*resume)(struct libinput *libinput);
|
||||
void (*suspend)(struct libinput *libinput);
|
||||
|
|
@ -335,6 +323,18 @@ enum libinput_tablet_tool_axis {
|
|||
|
||||
#define LIBINPUT_TABLET_TOOL_AXIS_MAX LIBINPUT_TABLET_TOOL_AXIS_REL_WHEEL
|
||||
|
||||
struct tablet_axes {
|
||||
struct device_coords point;
|
||||
struct normalized_coords delta;
|
||||
double distance;
|
||||
double pressure;
|
||||
struct tilt_degrees tilt;
|
||||
double rotation;
|
||||
double slider;
|
||||
double wheel;
|
||||
int wheel_discrete;
|
||||
};
|
||||
|
||||
struct libinput_tablet_tool {
|
||||
struct list link;
|
||||
uint32_t serial;
|
||||
|
|
|
|||
|
|
@ -1013,6 +1013,13 @@ START_TEST(proximity_has_axes)
|
|||
litest_axis_set_value(axes, ABS_DISTANCE, 20);
|
||||
litest_axis_set_value(axes, ABS_TILT_X, 15);
|
||||
litest_axis_set_value(axes, ABS_TILT_Y, 25);
|
||||
|
||||
/* work around axis smoothing */
|
||||
litest_tablet_motion(dev, 20, 30, axes);
|
||||
litest_tablet_motion(dev, 20, 29, axes);
|
||||
litest_tablet_motion(dev, 20, 31, axes);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_tablet_motion(dev, 20, 30, axes);
|
||||
libinput_dispatch(li);
|
||||
event = libinput_get_event(li);
|
||||
|
|
@ -1044,8 +1051,10 @@ START_TEST(proximity_has_axes)
|
|||
|
||||
x = libinput_event_tablet_tool_get_x(tablet_event);
|
||||
y = libinput_event_tablet_tool_get_y(tablet_event);
|
||||
litest_assert_double_eq(x, last_x);
|
||||
litest_assert_double_eq(y, last_y);
|
||||
litest_assert_double_ge(x, last_x - 1);
|
||||
litest_assert_double_le(x, last_x + 1);
|
||||
litest_assert_double_ge(y, last_y - 1);
|
||||
litest_assert_double_le(y, last_y + 1);
|
||||
|
||||
if (libinput_tablet_tool_has_distance(tool)) {
|
||||
ck_assert(!libinput_event_tablet_tool_distance_has_changed(
|
||||
|
|
@ -1428,6 +1437,16 @@ START_TEST(left_handed)
|
|||
|
||||
libinput_event_destroy(event);
|
||||
|
||||
/* work around smoothing */
|
||||
litest_axis_set_value(axes, ABS_DISTANCE, 9);
|
||||
litest_tablet_motion(dev, 100, 0, axes);
|
||||
litest_axis_set_value(axes, ABS_DISTANCE, 7);
|
||||
litest_tablet_motion(dev, 100, 0, axes);
|
||||
litest_axis_set_value(axes, ABS_DISTANCE, 10);
|
||||
litest_tablet_motion(dev, 100, 0, axes);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_axis_set_value(axes, ABS_DISTANCE, 5);
|
||||
litest_tablet_motion(dev, 100, 0, axes);
|
||||
libinput_dispatch(li);
|
||||
|
||||
|
|
@ -1468,6 +1487,16 @@ START_TEST(left_handed)
|
|||
|
||||
libinput_event_destroy(event);
|
||||
|
||||
/* work around smoothing */
|
||||
litest_axis_set_value(axes, ABS_DISTANCE, 9);
|
||||
litest_tablet_motion(dev, 100, 0, axes);
|
||||
litest_axis_set_value(axes, ABS_DISTANCE, 7);
|
||||
litest_tablet_motion(dev, 100, 0, axes);
|
||||
litest_axis_set_value(axes, ABS_DISTANCE, 10);
|
||||
litest_tablet_motion(dev, 100, 0, axes);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_axis_set_value(axes, ABS_DISTANCE, 5);
|
||||
litest_tablet_motion(dev, 100, 0, axes);
|
||||
libinput_dispatch(li);
|
||||
|
||||
|
|
@ -1768,6 +1797,7 @@ START_TEST(motion_outside_bounds)
|
|||
struct libinput_event *event;
|
||||
struct libinput_event_tablet_tool *tablet_event;
|
||||
double val;
|
||||
int i;
|
||||
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_DISTANCE, 10 },
|
||||
|
|
@ -1778,6 +1808,15 @@ START_TEST(motion_outside_bounds)
|
|||
litest_tablet_proximity_in(dev, 50, 50, axes);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* Work around smoothing */
|
||||
for (i = 5; i > 0; i--) {
|
||||
litest_event(dev, EV_ABS, ABS_X, 0 + 5 * i);
|
||||
litest_event(dev, EV_ABS, ABS_Y, 1000);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
litest_drain_events(li);
|
||||
|
||||
/* On the 24HD x/y of 0 is outside the limit */
|
||||
litest_event(dev, EV_ABS, ABS_X, 0);
|
||||
litest_event(dev, EV_ABS, ABS_Y, 1000);
|
||||
|
|
@ -1797,6 +1836,15 @@ START_TEST(motion_outside_bounds)
|
|||
|
||||
libinput_event_destroy(event);
|
||||
|
||||
/* Work around smoothing */
|
||||
for (i = 5; i > 0; i--) {
|
||||
litest_event(dev, EV_ABS, ABS_X, 1000);
|
||||
litest_event(dev, EV_ABS, ABS_Y, 0 + 5 * i);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
litest_drain_events(li);
|
||||
|
||||
/* On the 24HD x/y of 0 is outside the limit */
|
||||
litest_event(dev, EV_ABS, ABS_X, 1000);
|
||||
litest_event(dev, EV_ABS, ABS_Y, 0);
|
||||
|
|
@ -3341,12 +3389,18 @@ START_TEST(tablet_pressure_min_max)
|
|||
litest_tablet_motion(dev, 5, 100, axes);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* need to fill the motion history */
|
||||
litest_axis_set_value(axes, ABS_PRESSURE, 100);
|
||||
litest_tablet_motion(dev, 5, 100, axes);
|
||||
litest_tablet_motion(dev, 6, 100, axes);
|
||||
litest_tablet_motion(dev, 7, 100, axes);
|
||||
litest_tablet_motion(dev, 8, 100, axes);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_tablet_motion(dev, 5, 100, axes);
|
||||
libinput_dispatch(li);
|
||||
event = libinput_get_event(li);
|
||||
tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
|
||||
ck_assert(libinput_event_tablet_tool_pressure_has_changed(tev));
|
||||
p = libinput_event_tablet_tool_get_pressure(tev);
|
||||
ck_assert_double_ge(p, 1.0);
|
||||
libinput_event_destroy(event);
|
||||
|
|
@ -3630,7 +3684,12 @@ START_TEST(tilt_x)
|
|||
|
||||
for (tilt = 0; tilt <= 100; tilt += 5) {
|
||||
litest_axis_set_value(axes, ABS_TILT_X, tilt);
|
||||
/* work around smoothing */
|
||||
litest_tablet_motion(dev, 10, 10, axes);
|
||||
litest_tablet_motion(dev, 10, 11, axes);
|
||||
litest_tablet_motion(dev, 10, 10, axes);
|
||||
litest_drain_events(li);
|
||||
litest_tablet_motion(dev, 10, 11, axes);
|
||||
libinput_dispatch(li);
|
||||
event = libinput_get_event(li);
|
||||
tev = litest_is_tablet_event(event,
|
||||
|
|
@ -3699,6 +3758,11 @@ START_TEST(tilt_y)
|
|||
|
||||
for (tilt = 0; tilt <= 100; tilt += 5) {
|
||||
litest_axis_set_value(axes, ABS_TILT_Y, tilt);
|
||||
/* work around smoothing */
|
||||
litest_tablet_motion(dev, 10, 11, axes);
|
||||
litest_tablet_motion(dev, 10, 10, axes);
|
||||
litest_tablet_motion(dev, 10, 11, axes);
|
||||
litest_drain_events(li);
|
||||
litest_tablet_motion(dev, 10, 10, axes);
|
||||
libinput_dispatch(li);
|
||||
event = libinput_get_event(li);
|
||||
|
|
@ -3815,7 +3879,7 @@ START_TEST(relative_delta)
|
|||
ck_assert(dy == 0.0);
|
||||
libinput_event_destroy(event);
|
||||
|
||||
litest_tablet_motion(dev, 10, 10, axes);
|
||||
litest_tablet_motion(dev, 5, 10, axes);
|
||||
libinput_dispatch(li);
|
||||
event = libinput_get_event(li);
|
||||
tev = litest_is_tablet_event(event,
|
||||
|
|
@ -3837,7 +3901,7 @@ START_TEST(relative_delta)
|
|||
ck_assert(dy > 0.0);
|
||||
libinput_event_destroy(event);
|
||||
|
||||
litest_tablet_motion(dev, 10, 10, axes);
|
||||
litest_tablet_motion(dev, 10, 5, axes);
|
||||
libinput_dispatch(li);
|
||||
event = libinput_get_event(li);
|
||||
tev = litest_is_tablet_event(event,
|
||||
|
|
@ -3888,7 +3952,7 @@ START_TEST(relative_calibration)
|
|||
ck_assert(dy == 0.0);
|
||||
libinput_event_destroy(event);
|
||||
|
||||
litest_tablet_motion(dev, 10, 10, axes);
|
||||
litest_tablet_motion(dev, 5, 10, axes);
|
||||
libinput_dispatch(li);
|
||||
event = libinput_get_event(li);
|
||||
tev = litest_is_tablet_event(event,
|
||||
|
|
@ -3910,7 +3974,7 @@ START_TEST(relative_calibration)
|
|||
ck_assert(dy < 0.0);
|
||||
libinput_event_destroy(event);
|
||||
|
||||
litest_tablet_motion(dev, 10, 10, axes);
|
||||
litest_tablet_motion(dev, 10, 5, axes);
|
||||
libinput_dispatch(li);
|
||||
event = libinput_get_event(li);
|
||||
tev = litest_is_tablet_event(event,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue