summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/evdev-tablet.c52
-rw-r--r--src/libinput-private.h6
-rw-r--r--test/test-tablet.c49
3 files changed, 63 insertions, 44 deletions
diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c
index 21963ccd..62c23b83 100644
--- a/src/evdev-tablet.c
+++ b/src/evdev-tablet.c
@@ -353,30 +353,20 @@ static inline double
normalize_pressure(const struct input_absinfo *absinfo,
struct libinput_tablet_tool *tool)
{
- 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.
+ * Note: the upper threshold takes the offset into account so that
+ * |- 4% -|
+ * min |------X------X-------------------------| max
+ * | |
+ * | + upper threshold / tip trigger
+ * +- offset and lower threshold
*
- * 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 noticeable.
- *
- * Note that that lower-upper range gives us a negative pressure, so
- * we have to clip to 0 for those.
+ * The axis is scaled into the range [lower, max] so that the lower
+ * threshold is 0 pressure.
*/
-
- if (tool->pressure.has_offset)
- offset = tool->pressure.offset;
- else
- offset = tool->pressure.threshold.upper;
- range = absinfo->maximum - offset;
- value = (absinfo->value - offset) / range;
+ int base = tool->pressure.threshold.lower;
+ double range = absinfo->maximum - base;
+ double value = (absinfo->value - base) / range;
return max(0.0, value);
}
@@ -1255,7 +1245,10 @@ sanitize_pressure_distance(struct tablet_dispatch *tablet,
if (!pressure_changed && !distance_changed)
return;
- tool_in_contact = (pressure->value > tool->pressure.offset);
+ /* Note: this is an arbitrary "in contact" decision rather than "tip
+ * down". We use the lower threshold as minimum pressure value,
+ * anything less than that gets filtered away */
+ tool_in_contact = (pressure->value > tool->pressure.threshold.lower);
/* Keep distance and pressure mutually exclusive */
if (distance &&
@@ -1327,7 +1320,7 @@ detect_pressure_offset(struct tablet_dispatch *tablet,
*/
if (tool->pressure.has_offset) {
if (offset < tool->pressure.offset)
- tool->pressure.offset = offset;
+ goto set_offset;
return;
}
@@ -1359,9 +1352,17 @@ detect_pressure_offset(struct tablet_dispatch *tablet,
tablet_tool_type_to_string(tool->type),
tool->serial,
HTTP_DOC_LINK);
+set_offset:
tool->pressure.offset = offset;
tool->pressure.has_offset = true;
- tool->pressure.threshold.lower = pressure->minimum;
+
+ /* Adjust the tresholds accordingly - we use the same gap (4% in
+ * device coordinates) between upper and lower as before which isn't
+ * technically correct (our range shrunk) but it's easy to calculate.
+ */
+ int gap = tool->pressure.threshold.upper - tool->pressure.threshold.lower;
+ tool->pressure.threshold.lower = offset;
+ tool->pressure.threshold.upper = offset + gap;
}
static void
@@ -1392,9 +1393,6 @@ detect_tool_contact(struct tablet_dispatch *tablet,
}
pressure = p->value;
- if (tool->pressure.has_offset)
- pressure -= (tool->pressure.offset - p->minimum);
-
if (pressure <= tool->pressure.threshold.lower &&
tablet_has_status(tablet, TABLET_TOOL_IN_CONTACT)) {
tablet_set_status(tablet, TABLET_TOOL_LEAVING_CONTACT);
diff --git a/src/libinput-private.h b/src/libinput-private.h
index 7abb384f..aca4d965 100644
--- a/src/libinput-private.h
+++ b/src/libinput-private.h
@@ -407,10 +407,8 @@ struct libinput_tablet_tool {
void *user_data;
struct {
- /* The pressure threshold assumes a pressure_offset of 0 */
- struct threshold threshold;
- /* pressure_offset includes axis->minimum */
- int offset;
+ struct threshold threshold; /* in device coordinates */
+ int offset; /* in device coordinates */
bool has_offset;
} pressure;
};
diff --git a/test/test-tablet.c b/test/test-tablet.c
index 35f835e5..ce1c7b6a 100644
--- a/test/test-tablet.c
+++ b/test/test-tablet.c
@@ -3588,8 +3588,9 @@ START_TEST(tablet_pressure_distance_exclusive)
litest_tablet_proximity_in(dev, 5, 50, axes);
litest_drain_events(li);
- /* We have pressure but we're still below the tip threshold */
- litest_axis_set_value(axes, ABS_PRESSURE, 1);
+ /* We have 0.1% pressure above minimum threshold but we're still below
+ * the tip threshold */
+ litest_axis_set_value(axes, ABS_PRESSURE, 1.1);
litest_tablet_motion(dev, 70, 70, axes);
libinput_dispatch(li);
@@ -3599,11 +3600,11 @@ 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_eq(pressure, 0.0);
+ ck_assert_double_eq(pressure, 0.001);
ck_assert_double_eq(distance, 0.0);
libinput_event_destroy(event);
- /* We have pressure and we're above the threshold now */
+ /* We have pressure and we're above the tip threshold now */
litest_axis_set_value(axes, ABS_PRESSURE, 5.5);
litest_tablet_motion(dev, 70, 70, axes);
libinput_dispatch(li);
@@ -3820,18 +3821,23 @@ START_TEST(tablet_pressure_offset_set)
};
double pressure;
- /* This activates the pressure thresholds */
+ /* This activates the pressure offset */
litest_tablet_proximity_in(dev, 5, 100, axes);
litest_drain_events(li);
/* Put the pen down, with a pressure high enough to meet the
- * threshold */
+ * new offset */
litest_axis_set_value(axes, ABS_DISTANCE, 0);
- litest_axis_set_value(axes, ABS_PRESSURE, 25);
+ litest_axis_set_value(axes, ABS_PRESSURE, 26);
- litest_tablet_tip_down(dev, 70, 70, axes);
+ /* Tablet motion above threshold should trigger axis + tip down. Use
+ * the litest motion helper here to avoid false positives caused by
+ * BTN_TOUCH */
+ litest_tablet_motion(dev, 70, 70, axes);
libinput_dispatch(li);
- litest_drain_events(li);
+ event = libinput_get_event(li);
+ litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
+ libinput_event_destroy(event);
/* Reduce pressure to just a tick over the offset, otherwise we get
* the tip up event again */
@@ -3879,6 +3885,16 @@ START_TEST(tablet_pressure_offset_set)
ck_assert_double_ge(pressure, 1.0);
libinput_event_destroy(event);
+ /* Tablet motion at offset should trigger tip up. Use
+ * the litest motion helper here to avoid false positives caused by
+ * BTN_TOUCH */
+ litest_axis_set_value(axes, ABS_PRESSURE, 20);
+ litest_tablet_motion(dev, 71, 71, axes);
+ libinput_dispatch(li);
+ event = libinput_get_event(li);
+ litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
+ libinput_event_destroy(event);
+
}
END_TEST
@@ -3929,8 +3945,10 @@ START_TEST(tablet_pressure_offset_decrease)
pressure = libinput_event_tablet_tool_get_pressure(tev);
- /* offset is 10, value is 15, so that's a around 5% of the
- * remaining range */
+ /* offset 10 + lower threshold of ~1% of original range,
+ * value 15 is 5% over original range but with the above taken into
+ * account it's closer to 5% into the remaining effective 89% range
+ */
ck_assert_double_eq_tol(pressure, 0.05, 0.01);
libinput_event_destroy(event);
}
@@ -3973,7 +3991,11 @@ START_TEST(tablet_pressure_offset_increase)
tev = litest_is_tablet_event(event,
LIBINPUT_EVENT_TABLET_TOOL_AXIS);
pressure = libinput_event_tablet_tool_get_pressure(tev);
- /* offset 20, value 30 leaves us with 12% of the remaining 90 range */
+
+ /* offset 20 + lower threshold of 1% of original range,
+ * value 30 is 5% over original range but with the above taken into
+ * account it's closer to 12% into the remaining effective 79% range
+ */
ck_assert_double_eq_tol(pressure, 0.12, 0.01);
libinput_event_destroy(event);
@@ -4015,7 +4037,8 @@ START_TEST(tablet_pressure_min_max)
libinput_dispatch(li);
litest_axis_set_value(axes, ABS_DISTANCE, 0);
- litest_axis_set_value(axes, ABS_PRESSURE, 1);
+ /* Default pressure threshold is 1% of range */
+ litest_axis_set_value(axes, ABS_PRESSURE, 1.1);
litest_tablet_motion(dev, 5, 50, axes);
libinput_dispatch(li);
event = libinput_get_event(li);