From d93feba134dbabbac37d375c972699f6ae5c1bc2 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 6 Aug 2019 14:04:16 +1000 Subject: [PATCH] tablet: scale the available pressure range into the pressure thresholds Pens that don't have a pressure offset (caused by a worn-out tip) still have basic pressure thresholds to avoid tip events when we're still a bit away from the tablet or barely touching it. That range is currently 5% of the pressure for tip down, 1% for tip up. This leaves us with 95% of the range and that needs to be scaled correctly, otherwise the bottom 5% happen before a tip event and are inaccessible where applications don't look at pressure before tip down. Fixes #332 Signed-off-by: Peter Hutterer --- src/evdev-tablet.c | 30 +++++++++++++++++++++++++----- test/test-tablet.c | 29 +++++++++++++++++++++++------ 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index 18c8fbee3..943b5284b 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -354,12 +354,32 @@ static inline double normalize_pressure(const struct input_absinfo *absinfo, struct libinput_tablet_tool *tool) { - int offset = tool->has_pressure_offset ? - tool->pressure_offset : absinfo->minimum; - double range = absinfo->maximum - offset; - double value = (absinfo->value - offset) / range; + int offset; + double range; + double value; + + /** + * If the tool has a pressure offset, we use that as the lower bound + * for the scaling range. If not, we use the upper threshold as the + * lower bound, so once we get past that minimum physical pressure + * we have logical 0 pressure. + * + * This means that there is a small range (lower-upper) where + * different physical pressure (default: 1-5%) result in the same + * logical pressure. This is, hopefully, not noticable. + * + * Note that that lower-upper range gives us a negative pressure, so + * we have to clip to 0 for those. + */ - return value; + if (tool->has_pressure_offset) + offset = tool->pressure_offset; + else + offset = tool->pressure_threshold.upper; + range = absinfo->maximum - offset; + value = (absinfo->value - offset) / range; + + return max(0.0, value); } static inline double diff --git a/test/test-tablet.c b/test/test-tablet.c index d05e74809..90b81a7fb 100644 --- a/test/test-tablet.c +++ b/test/test-tablet.c @@ -3348,10 +3348,11 @@ START_TEST(tablet_pressure_distance_exclusive) }; double pressure, distance; - litest_tablet_proximity_in(dev, 5, 100, axes); + litest_tablet_proximity_in(dev, 5, 50, axes); litest_drain_events(li); - litest_axis_set_value(axes, ABS_PRESSURE, 2); + /* We have pressure but we're still below the tip threshold */ + litest_axis_set_value(axes, ABS_PRESSURE, 1); litest_tablet_motion(dev, 70, 70, axes); libinput_dispatch(li); @@ -3361,7 +3362,22 @@ START_TEST(tablet_pressure_distance_exclusive) pressure = libinput_event_tablet_tool_get_pressure(tev); distance = libinput_event_tablet_tool_get_distance(tev); - ck_assert_double_ne(pressure, 0.0); + ck_assert_double_eq(pressure, 0.0); + ck_assert_double_eq(distance, 0.0); + libinput_event_destroy(event); + + /* We have pressure and we're above the threshold now */ + litest_axis_set_value(axes, ABS_PRESSURE, 5.5); + litest_tablet_motion(dev, 70, 70, axes); + libinput_dispatch(li); + + event = libinput_get_event(li); + tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP); + + pressure = libinput_event_tablet_tool_get_pressure(tev); + distance = libinput_event_tablet_tool_get_distance(tev); + + ck_assert_double_gt(pressure, 0.0); ck_assert_double_eq(distance, 0.0); libinput_event_destroy(event); @@ -3769,8 +3785,8 @@ START_TEST(tablet_pressure_min_max) struct libinput_event *event; struct libinput_event_tablet_tool *tev; struct axis_replacement axes[] = { - { ABS_DISTANCE, 0 }, - { ABS_PRESSURE, 2 }, + { ABS_DISTANCE, 10 }, + { ABS_PRESSURE, 0 }, { -1, -1 }, }; double p; @@ -3782,7 +3798,8 @@ START_TEST(tablet_pressure_min_max) litest_drain_events(li); libinput_dispatch(li); - litest_axis_set_value(axes, ABS_PRESSURE, 0); + litest_axis_set_value(axes, ABS_DISTANCE, 0); + litest_axis_set_value(axes, ABS_PRESSURE, 1); litest_tablet_motion(dev, 5, 50, axes); libinput_dispatch(li); event = libinput_get_event(li);