diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2017-03-23 14:54:00 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2017-07-11 12:28:28 +1000 |
commit | ca4285de66641ab4b5e85a39a3dcb0eb55525fad (patch) | |
tree | 495c070680eef26674f7a664f52b8d6affe8db14 | |
parent | 432fbc33cd6a2181ac213eeb66239df8312836a6 (diff) |
touchpad: add touch-size-based palm detection
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
-rw-r--r-- | src/evdev-mt-touchpad.c | 66 | ||||
-rw-r--r-- | src/evdev-mt-touchpad.h | 4 | ||||
-rw-r--r-- | src/libinput-util.c | 25 | ||||
-rw-r--r-- | src/libinput-util.h | 1 | ||||
-rw-r--r-- | test/litest.h | 18 | ||||
-rw-r--r-- | test/test-device.c | 20 | ||||
-rw-r--r-- | test/test-touchpad.c | 36 | ||||
-rw-r--r-- | udev/90-libinput-model-quirks.hwdb | 1 | ||||
-rwxr-xr-x | udev/parse_hwdb.py | 1 |
9 files changed, 152 insertions, 20 deletions
diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 0f009ef6..a3751289 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -746,6 +746,30 @@ tp_palm_detect_multifinger(struct tp_dispatch *tp, struct tp_touch *t, uint64_t } static inline bool +tp_palm_detect_touch_size_triggered(struct tp_dispatch *tp, + struct tp_touch *t, + uint64_t time) +{ + if (!tp->palm.use_size) + return false; + + /* If a finger size is large enough for palm, we stick with that and + * force the user to release and reset the finger */ + if (t->palm.state != PALM_NONE && t->palm.state != PALM_TOUCH_SIZE) + return false; + + if (t->major > tp->palm.size_threshold || + t->minor > tp->palm.size_threshold) { + evdev_log_debug(tp->device, + "palm: touch size exceeded\n"); + t->palm.state = PALM_TOUCH_SIZE; + return true; + } + + return false; +} + +static inline bool tp_palm_detect_edge(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time) @@ -828,6 +852,9 @@ tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time) if (tp_palm_detect_tool_triggered(tp, t, time)) goto out; + if (tp_palm_detect_touch_size_triggered(tp, t, time)) + goto out; + if (tp_palm_detect_edge(tp, t, time)) goto out; @@ -862,6 +889,9 @@ out: case PALM_PRESSURE: palm_state = "pressure"; break; + case PALM_TOUCH_SIZE: + palm_state = "touch size"; + break; case PALM_NONE: default: abort(); @@ -2415,10 +2445,14 @@ tp_init_palmdetect_edge(struct tp_dispatch *tp, struct phys_coords mm = { 0.0, 0.0 }; struct device_coords edges; + if (device->tags & EVDEV_TAG_EXTERNAL_TOUCHPAD && + !tp_is_tpkb_combo_below(device)) + return; + evdev_device_get_size(device, &width, &height); - /* Enable palm detection on touchpads >= 70 mm. Anything smaller - probably won't need it, until we find out it does */ + /* Enable edge palm detection on touchpads >= 70 mm. Anything + smaller probably won't need it, until we find out it does */ if (width < 70.0) return; @@ -2475,6 +2509,33 @@ tp_init_palmdetect_pressure(struct tp_dispatch *tp, tp->palm.pressure_threshold); } +static inline void +tp_init_palmdetect_size(struct tp_dispatch *tp, + struct evdev_device *device) +{ + const char *prop; + int threshold; + + if (!tp->touch_size.use_touch_size) + return; + + prop = udev_device_get_property_value(device->udev_device, + "LIBINPUT_ATTR_PALM_SIZE_THRESHOLD"); + if (!prop) + return; + + threshold = parse_palm_size_property(prop); + if (threshold == 0) { + evdev_log_bug_client(device, + "palm: ignoring invalid threshold %s\n", + prop); + return; + } + + tp->palm.use_size = true; + tp->palm.size_threshold = threshold; +} + static void tp_init_palmdetect(struct tp_dispatch *tp, struct evdev_device *device) @@ -2497,6 +2558,7 @@ tp_init_palmdetect(struct tp_dispatch *tp, tp_init_palmdetect_edge(tp, device); tp_init_palmdetect_pressure(tp, device); + tp_init_palmdetect_size(tp, device); } static void diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index 7391e6ce..664514de 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -59,6 +59,7 @@ enum touch_palm_state { PALM_TRACKPOINT, PALM_TOOL_PALM, PALM_PRESSURE, + PALM_TOUCH_SIZE, }; enum button_event { @@ -360,6 +361,9 @@ struct tp_dispatch { bool use_pressure; int pressure_threshold; + + bool use_size; + int size_threshold; } palm; struct { diff --git a/src/libinput-util.c b/src/libinput-util.c index df7a1f3b..7eb88e3c 100644 --- a/src/libinput-util.c +++ b/src/libinput-util.c @@ -432,6 +432,31 @@ parse_palm_pressure_property(const char *prop) } /** + * Helper function to parse the LIBINPUT_ATTR_PALM_SIZE_THRESHOLD property + * from udev. Property is of the form: + * LIBINPUT_ATTR_PALM_SIZE_THRESHOLD=<integer> + * Where the number indicates the minimum threshold to consider a touch to + * be a palm. + * + * @param prop The value of the udev property (without the + * LIBINPUT_ATTR_PALM_SIZE_THRESHOLD=) + * @return The pressure threshold or 0 on error + */ +int +parse_palm_size_property(const char *prop) +{ + int thr = 0; + + if (!prop) + return 0; + + if (!safe_atoi(prop, &thr) || thr < 0 || thr > 1024) + return 0; + + return thr; +} + +/** * Return the next word in a string pointed to by state before the first * separator character. Call repeatedly to tokenize a whole string. * diff --git a/src/libinput-util.h b/src/libinput-util.h index 30ab48cd..6886c6dd 100644 --- a/src/libinput-util.h +++ b/src/libinput-util.h @@ -390,6 +390,7 @@ bool parse_dimension_property(const char *prop, size_t *width, size_t *height); bool parse_calibration_property(const char *prop, float calibration[6]); bool parse_range_property(const char *prop, int *hi, int *lo); int parse_palm_pressure_property(const char *prop); +int parse_palm_size_property(const char *prop); enum tpkbcombo_layout { TPKBCOMBO_LAYOUT_UNKNOWN, diff --git a/test/litest.h b/test/litest.h index 73f9ac2e..7086804e 100644 --- a/test/litest.h +++ b/test/litest.h @@ -33,6 +33,8 @@ #include <libinput.h> #include <math.h> +#include "libinput-util.h" + extern void litest_setup_tests_udev(void); extern void litest_setup_tests_path(void); extern void litest_setup_tests_pointer(void); @@ -915,6 +917,22 @@ litest_disable_middleemu(struct litest_device *dev) litest_assert_int_eq(status, expected); } +static inline bool +litest_touchpad_is_external(struct litest_device *dev) +{ + struct udev_device *udev_device; + const char *prop; + bool is_external; + + udev_device = libinput_device_get_udev_device(dev->libinput_device); + prop = udev_device_get_property_value(udev_device, + "ID_INPUT_TOUCHPAD_INTEGRATION"); + is_external = prop && streq(prop, "external"); + udev_device_unref(udev_device); + + return is_external; +} + #undef ck_assert_double_eq #undef ck_assert_double_ne #undef ck_assert_double_lt diff --git a/test/test-device.c b/test/test-device.c index 018b194f..c4dfdd47 100644 --- a/test/test-device.c +++ b/test/test-device.c @@ -61,22 +61,6 @@ START_TEST(device_sendevents_config_invalid) } END_TEST -static inline bool -touchpad_is_external(struct litest_device *dev) -{ - struct udev_device *udev_device; - const char *prop; - bool is_external; - - udev_device = libinput_device_get_udev_device(dev->libinput_device); - prop = udev_device_get_property_value(udev_device, - "ID_INPUT_TOUCHPAD_INTEGRATION"); - is_external = prop && streq(prop, "external"); - udev_device_unref(udev_device); - - return is_external; -} - START_TEST(device_sendevents_config_touchpad) { struct litest_device *dev = litest_current_device(); @@ -87,7 +71,7 @@ START_TEST(device_sendevents_config_touchpad) /* The wacom devices in the test suite are external */ if (libevdev_get_id_vendor(dev->evdev) != VENDOR_ID_WACOM && - !touchpad_is_external(dev)) + !litest_touchpad_is_external(dev)) expected |= LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE; @@ -107,7 +91,7 @@ START_TEST(device_sendevents_config_touchpad_superset) /* The wacom devices in the test suite are external */ if (libevdev_get_id_vendor(dev->evdev) == VENDOR_ID_WACOM || - touchpad_is_external(dev)) + litest_touchpad_is_external(dev)) return; device = dev->libinput_device; diff --git a/test/test-touchpad.c b/test/test-touchpad.c index 77618155..5e029a45 100644 --- a/test/test-touchpad.c +++ b/test/test-touchpad.c @@ -5376,6 +5376,41 @@ START_TEST(touchpad_touch_size_2fg) } END_TEST +START_TEST(touchpad_palm_detect_touch_size) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct axis_replacement axes[] = { + { ABS_MT_TOUCH_MAJOR, 0 }, + { ABS_MT_TOUCH_MINOR, 0 }, + { -1, 0 } + }; + + if (!touchpad_has_touch_size(dev) || + litest_touchpad_is_external(dev)) + return; + + litest_drain_events(li); + litest_axis_set_value(axes, ABS_MT_TOUCH_MAJOR, 30); + litest_axis_set_value(axes, ABS_MT_TOUCH_MINOR, 30); + litest_touch_down_extended(dev, 0, 50, 50, axes); + litest_touch_move_to_extended(dev, 0, + 50, 50, + 80, 80, + axes, 10, 1); + litest_assert_only_typed_events(li, + LIBINPUT_EVENT_POINTER_MOTION); + + litest_axis_set_value_unchecked(axes, ABS_MT_TOUCH_MAJOR, 90); + litest_axis_set_value(axes, ABS_MT_TOUCH_MINOR, 90); + litest_touch_move_to_extended(dev, 0, + 80, 80, + 50, 50, + axes, 10, 1); + litest_assert_empty_queue(li); +} +END_TEST + void litest_setup_tests_touchpad(void) { @@ -5430,6 +5465,7 @@ litest_setup_tests_touchpad(void) litest_add("touchpad:palm", touchpad_palm_detect_tool_palm, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); litest_add("touchpad:palm", touchpad_palm_detect_tool_palm_on_off, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); litest_add("touchpad:palm", touchpad_palm_detect_tool_palm_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add("touchpad:palm", touchpad_palm_detect_touch_size, LITEST_APPLE_CLICKPAD, LITEST_ANY); litest_add("touchpad:palm", touchpad_palm_detect_pressure, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); litest_add("touchpad:palm", touchpad_palm_detect_pressure_late, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); diff --git a/udev/90-libinput-model-quirks.hwdb b/udev/90-libinput-model-quirks.hwdb index 5d9b2cbc..2754c5d5 100644 --- a/udev/90-libinput-model-quirks.hwdb +++ b/udev/90-libinput-model-quirks.hwdb @@ -51,6 +51,7 @@ libinput:touchpad:input:b0005v05ACp* LIBINPUT_MODEL_APPLE_TOUCHPAD=1 LIBINPUT_ATTR_SIZE_HINT=104x75 LIBINPUT_ATTR_TOUCH_SIZE_RANGE=150:130 + LIBINPUT_ATTR_PALM_SIZE_THRESHOLD=800 libinput:name:*Apple Inc. Apple Internal Keyboard*:dmi:* LIBINPUT_ATTR_KEYBOARD_INTEGRATION=internal diff --git a/udev/parse_hwdb.py b/udev/parse_hwdb.py index 102fb3e7..f6b9ec0a 100755 --- a/udev/parse_hwdb.py +++ b/udev/parse_hwdb.py @@ -119,6 +119,7 @@ def property_grammar(): tprops = ( ('LIBINPUT_ATTR_PALM_PRESSURE_THRESHOLD', INTEGER('X')), + ('LIBINPUT_ATTR_PALM_SIZE_THRESHOLD', INTEGER('X')), ) typed_props = [Literal(name)('NAME') - Suppress('=') - val for name, val in tprops] |