tablet: when configuring a user-defined pressure range, zero the offset

When a user configures a pressure range, the tool would get locked into
the current offset even if that offset was still pending. For example, a
sequence of

- tool in-prox with pressure 50%
- libinput_tablet_tool_config_pressure_range_set(tool, 0.0, 0.9)
- tool out-of-prox, tool-in-prox
- libinput applies the tool config, tool now has a configured range,
  has_offset = true
- tool out-of-prox, tool-in-prox
- update_pressure_range() sees has_offset = true, scales the last offset
  (50%) to the actual offset.

Fix this by resetting the detected offset to zero when we shortcut the
heuristics. A user-defined pressure range should include the tool's
pressure offset anyway, the user knows this much better than our
heuristics.

Closes: 1177
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1340>
This commit is contained in:
Peter Hutterer 2025-10-23 13:31:55 +10:00 committed by Marge Bot
parent 66f2d121ee
commit bda0c7478e
2 changed files with 84 additions and 3 deletions

View file

@ -2192,13 +2192,13 @@ update_pressure_range(struct tablet_dispatch *tablet,
threshold->threshold.upper = hi; threshold->threshold.upper = hi;
threshold->threshold.lower = lo; threshold->threshold.lower = lo;
if (threshold->has_offset)
set_pressure_offset(threshold, threshold->offset);
/* Disable any heuristics */ /* Disable any heuristics */
if (tool->pressure.has_configured_range) { if (tool->pressure.has_configured_range) {
threshold->has_offset = true; threshold->has_offset = true;
threshold->heuristic_state = PRESSURE_HEURISTIC_STATE_DONE; threshold->heuristic_state = PRESSURE_HEURISTIC_STATE_DONE;
threshold->offset = pressure_offset_from_double(0.0);
} else if (threshold->has_offset) {
set_pressure_offset(threshold, threshold->offset);
} }
} }

View file

@ -4970,6 +4970,86 @@ START_TEST(tablet_pressure_config_set_range)
} }
END_TEST END_TEST
START_TEST(tablet_pressure_config_resets_offset)
{
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
struct axis_replacement axes[] = {
{ ABS_DISTANCE, 70 },
{ ABS_PRESSURE, 70 }, /* high pressure offset */
{ -1, -1 },
};
if (!libevdev_has_event_code(dev->evdev, EV_ABS, ABS_PRESSURE))
return LITEST_NOT_APPLICABLE;
litest_tablet_proximity_in(dev, 5, 100, axes);
litest_drain_events(li);
litest_dispatch(li);
litest_tablet_motion(dev, 70, 70, axes);
litest_dispatch(li);
{
_destroy_(libinput_event) *event = libinput_get_event(li);
auto tev =
litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
auto tool = libinput_event_tablet_tool_get_tool(tev);
litest_assert(
libinput_tablet_tool_config_pressure_range_is_available(tool));
litest_assert_enum_eq(
libinput_tablet_tool_config_pressure_range_set(tool,
0.01,
0.99),
LIBINPUT_CONFIG_STATUS_SUCCESS);
}
litest_tablet_proximity_out(dev);
litest_timeout_tablet_proxout(li);
litest_drain_events(li);
/* Config should be applied on prox in */
litest_axis_set_value(axes, ABS_PRESSURE, 71);
litest_tablet_proximity_in(dev, 72, 72, axes);
litest_drain_events(li);
litest_tablet_proximity_out(dev);
litest_timeout_tablet_proxout(li);
litest_drain_events(li);
/* Two prox in/out cycles to get past the heuristics on devices without
* ABS_DISTANCE
*/
litest_axis_set_value(axes, ABS_PRESSURE, 72);
litest_tablet_proximity_in(dev, 75, 75, axes);
litest_drain_events(li);
litest_tablet_proximity_out(dev);
litest_timeout_tablet_proxout(li);
litest_drain_events(li);
for (double pressure = 10.0, i = 71; pressure <= 25; pressure += 5, i += 0.2) {
litest_log_group("Prox in/out with pressure %.f", pressure) {
litest_axis_set_value(axes, ABS_PRESSURE, pressure);
litest_tablet_proximity_in(dev, i, i, axes);
litest_dispatch(li);
_destroy_(libinput_event) *event = libinput_get_event(li);
auto tev = litest_is_tablet_event(
event,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
double p = libinput_event_tablet_tool_get_pressure(tev);
/* checking if >5% is good enough here, it'd be zero if the
* 70% threshold were locked in */
litest_assert_double_gt(p, 0.05);
litest_tablet_proximity_out(dev);
litest_timeout_tablet_proxout(li);
litest_drain_events(li);
}
}
}
END_TEST
static void static void
pressure_threshold_warning(struct libinput *libinput, pressure_threshold_warning(struct libinput *libinput,
enum libinput_log_priority priority, enum libinput_log_priority priority,
@ -7629,6 +7709,7 @@ TEST_COLLECTION(tablet)
litest_add(tablet_pressure_config_set_minimum, LITEST_TABLET, LITEST_TOTEM); litest_add(tablet_pressure_config_set_minimum, LITEST_TABLET, LITEST_TOTEM);
litest_add(tablet_pressure_config_set_maximum, LITEST_TABLET, LITEST_TOTEM); litest_add(tablet_pressure_config_set_maximum, LITEST_TABLET, LITEST_TOTEM);
litest_add(tablet_pressure_config_set_range, LITEST_TABLET, LITEST_TOTEM); litest_add(tablet_pressure_config_set_range, LITEST_TABLET, LITEST_TOTEM);
litest_add(tablet_pressure_config_resets_offset, LITEST_TABLET, LITEST_TOTEM);
litest_add_for_device(tablet_distance_range, LITEST_WACOM_INTUOS5_PEN); litest_add_for_device(tablet_distance_range, LITEST_WACOM_INTUOS5_PEN);