From 4e4ff21e319c8eece8a4df8df29de800b58af34f Mon Sep 17 00:00:00 2001 From: Stephen Chandler Paul Date: Thu, 12 Jun 2014 18:46:26 -0400 Subject: [PATCH] Sanitize distance and pressure axes before reporting their values This commit changes two things with the way distance and pressure axes are reported: 1. Distance and pressure are made mutually exclusive. When there is a distance event and a pressure event and the tool is in contact with the tablet, only the pressure change will be reported. When the tool is not in contact and both a distance and pressure change are received, only the distance update will be received. 2. Bad distance events are not reported to the caller. There is a certain distance a tool can be from the tablet where the tablet recongnizes that a tool appeared, but the tool doesn't send any useful information to the tablet. When this happens, the distance will update to it's minimum or maximum value, and no other axis updates will be sent. Since this can give a caller the impression that the tool is within a useful proximity of the tablet, we filter out any distance events with a value of maximum or minimum when the tool is not within useful proximity of the tablet. Signed-off-by: Stephen Chandler Paul Reviewed-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-tablet.c | 34 ++++++++++++++++++++++++++++++++++ src/evdev-tablet.h | 3 ++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index aa9d2cbd..1bd94441 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -50,6 +50,9 @@ tablet_process_absolute(struct tablet_dispatch *tablet, case ABS_PRESSURE: case ABS_TILT_X: case ABS_TILT_Y: + tablet_unset_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY); + + /* Fall through */ case ABS_DISTANCE: axis = evcode_to_axis(e->code); if (axis == LIBINPUT_TABLET_AXIS_NONE) { @@ -313,6 +316,35 @@ tablet_notify_buttons(struct tablet_dispatch *tablet, stylus_buttons, BTN_TOUCH, state); } +static void +sanitize_tablet_axes(struct tablet_dispatch *tablet) +{ + const struct input_absinfo *distance, + *pressure; + + distance = libevdev_get_abs_info(tablet->device->evdev, ABS_DISTANCE); + pressure = libevdev_get_abs_info(tablet->device->evdev, ABS_PRESSURE); + + /* Keep distance and pressure mutually exclusive. In addition, filter + * out invalid distance events that can occur when the tablet tool is + * close enough for the tablet to detect that's something's there, but + * not close enough for it to actually receive data from the tool + * properly + */ + if (bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_AXIS_DISTANCE) && + ((distance->value > distance->minimum && + pressure->value > pressure->minimum) || + (tablet_has_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY) && + (distance->value <= distance->minimum || + distance->value >= distance->maximum)))) { + clear_bit(tablet->changed_axes, LIBINPUT_TABLET_AXIS_DISTANCE); + tablet->axes[LIBINPUT_TABLET_AXIS_DISTANCE] = 0; + } else if (bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_AXIS_PRESSURE) && + !tablet_has_status(tablet, TABLET_STYLUS_IN_CONTACT)) { + clear_bit(tablet->changed_axes, LIBINPUT_TABLET_AXIS_PRESSURE); + } +} + static void tablet_flush(struct tablet_dispatch *tablet, struct evdev_device *device, @@ -336,6 +368,7 @@ tablet_flush(struct tablet_dispatch *tablet, } if (tablet_has_status(tablet, TABLET_AXES_UPDATED)) { + sanitize_tablet_axes(tablet); tablet_check_notify_axes(tablet, device, time); tablet_unset_status(tablet, TABLET_AXES_UPDATED); } @@ -355,6 +388,7 @@ tablet_flush(struct tablet_dispatch *tablet, if (tablet_has_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY)) { tablet_notify_proximity_out(&device->base, time); + tablet_set_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY); tablet_unset_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY); } diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h index 679050b0..bc2939d7 100644 --- a/src/evdev-tablet.h +++ b/src/evdev-tablet.h @@ -34,7 +34,8 @@ enum tablet_status { TABLET_TOOL_LEAVING_PROXIMITY = 1 << 2, TABLET_BUTTONS_PRESSED = 1 << 3, TABLET_BUTTONS_RELEASED = 1 << 4, - TABLET_STYLUS_IN_CONTACT = 1 << 5 + TABLET_STYLUS_IN_CONTACT = 1 << 5, + TABLET_TOOL_OUT_OF_PROXIMITY = 1 << 6 }; struct button_state {