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 <thatslyude@gmail.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
This commit is contained in:
Stephen Chandler Paul 2014-06-12 18:46:26 -04:00
parent 8f572b6fd1
commit 4e4ff21e31
2 changed files with 36 additions and 1 deletions

View file

@ -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);
}

View file

@ -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 {