touchpad: replace the hardcoded thumb threshold with a udev prop
authorPeter Hutterer <peter.hutterer@who-t.net>
Wed, 23 May 2018 23:52:17 +0000 (09:52 +1000)
committerPeter Hutterer <peter.hutterer@who-t.net>
Tue, 29 May 2018 23:42:06 +0000 (09:42 +1000)
LIBINPUT_ATTR_THUMB_PRESSURE_THRESHOLD now determines whether we do thumb
pressure detection or not. Much better than having a hardcoded default that
may or may not be correct on any given device.

This patch is likely to break thumb detection on some touchpads, the only
property so far is to restore the default of 100 for all Lenovo Thinkpad
touchpads. More rules are needed, we'll just wait until someone shouts.

https://bugs.freedesktop.org/show_bug.cgi?id=106458

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
src/evdev-mt-touchpad.c
src/libinput-util.c
src/libinput-util.h
udev/90-libinput-model-quirks.hwdb
udev/parse_hwdb.py

index b1543dae6f0359e5afb1d820d2dd518bf8c12117..dd575510e140d82fce951152cd85b48a8fbdd3ab 100644 (file)
@@ -3039,6 +3039,25 @@ tp_init_sendevents(struct tp_dispatch *tp,
                            tp_keyboard_timeout, tp);
 }
 
+static int
+tp_read_thumb_pressure_prop(struct tp_dispatch *tp,
+                           const struct evdev_device *device)
+{
+       struct udev_device *udev_device = device->udev_device;
+       const char *prop;
+       int threshold;
+       const int default_thumb_threshold = 0;
+
+       prop = udev_device_get_property_value(udev_device,
+                             "LIBINPUT_ATTR_THUMB_PRESSURE_THRESHOLD");
+       if (!prop)
+               return default_thumb_threshold;
+
+       threshold = parse_thumb_pressure_property(prop);
+
+       return threshold > 0 ? threshold : default_thumb_threshold;
+}
+
 static void
 tp_init_thumb(struct tp_dispatch *tp)
 {
@@ -3047,8 +3066,7 @@ tp_init_thumb(struct tp_dispatch *tp)
        double w = 0.0, h = 0.0;
        struct device_coords edges;
        struct phys_coords mm = { 0.0, 0.0 };
-       int xres, yres;
-       double threshold;
+       int threshold;
 
        if (!tp->buttons.is_clickpad)
                return;
@@ -3077,20 +3095,11 @@ tp_init_thumb(struct tp_dispatch *tp)
        if (!abs)
                goto out;
 
-       if (abs->maximum - abs->minimum < 255)
+       threshold = tp_read_thumb_pressure_prop(tp, device);
+       if (threshold == 0)
                goto out;
 
-       /* Our reference touchpad is the T440s with 42x42 resolution.
-        * Higher-res touchpads exhibit higher pressure for the same
-        * interaction. On the T440s, the threshold value is 100, you don't
-        * reach that with a normal finger interaction.
-        * Note: "thumb" means massive touch that should not interact, not
-        * "using the tip of my thumb for a pinch gestures".
-        */
-       xres = tp->device->abs.absinfo_x->resolution;
-       yres = tp->device->abs.absinfo_y->resolution;
-       threshold = 100.0 * hypot(xres, yres)/hypot(42, 42);
-       tp->thumb.threshold = max(100, threshold);
+       tp->thumb.threshold = threshold;
 
 out:
        evdev_log_debug(device,
index 80ed489acd0d0ab4117124e5db05afb81904446f..eb6e3ecf903de775fffbfddac59800fb369927b9 100644 (file)
@@ -456,6 +456,31 @@ parse_palm_size_property(const char *prop)
         return thr;
 }
 
+/**
+ * Helper function to parse the LIBINPUT_ATTR_THUMB_PRESSURE_THRESHOLD
+ * property from udev. Property is of the form:
+ * LIBINPUT_ATTR_THUMB_PRESSURE_THRESHOLD=<integer>
+ * Where the number indicates the minimum threshold to consider a touch to
+ * be a thumb.
+ *
+ * @param prop The value of the udev property (without the
+ * LIBINPUT_ATTR_THUMB_PRESSURE_THRESHOLD=)
+ * @return The pressure threshold or 0 on error
+ */
+int
+parse_thumb_pressure_property(const char *prop)
+{
+       int threshold = 0;
+
+       if (!prop)
+               return 0;
+
+       if (!safe_atoi(prop, &threshold) || threshold < 0)
+               return 0;
+
+        return threshold;
+}
+
 /**
  * Return the next word in a string pointed to by state before the first
  * separator character. Call repeatedly to tokenize a whole string.
index c6759718a0cd3c39fd0344df8f7c8ee2763f5d24..92e7cf732bac82cf3864ef079e03beda6ef9dc7c 100644 (file)
@@ -419,6 +419,7 @@ 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);
+int parse_thumb_pressure_property(const char *prop);
 
 enum tpkbcombo_layout {
        TPKBCOMBO_LAYOUT_UNKNOWN,
index 06e489508f196096421a00dd9613b1d50fc16a15..6b3ca1968f9760c2282a9c7772f37c2668fa9b05 100644 (file)
@@ -254,6 +254,10 @@ libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*:pvrThinkPadX1Carbon3rd
  LIBINPUT_MODEL_LENOVO_T450_TOUCHPAD=1
  LIBINPUT_ATTR_PALM_PRESSURE_THRESHOLD=150
 
+# Lenovo ThinkPad series
+libinput:name:*Synaptics*:dmi:*svnLENOVO:*:pvrThinkPad*:*
+ LIBINPUT_ATTR_THUMB_PRESSURE_THRESHOLD=100
+
 # Lenovo ThinkPad Compact USB Keyboard with TrackPoint
 libinput:keyboard:input:b0003v17EFp6047*
  LIBINPUT_ATTR_KEYBOARD_INTEGRATION=external
index 3f47f33872213a06cfb49e49d98f6851b3c0c756..d00bce4c61e006b43d36371c268052c193757a15 100755 (executable)
@@ -114,6 +114,7 @@ def property_grammar():
          Or(('reliable', 'write_open'))),
         ('LIBINPUT_ATTR_KEYBOARD_INTEGRATION', Or(('internal', 'external'))),
         ('LIBINPUT_ATTR_TRACKPOINT_RANGE', INTEGER('Y')),
+        ('LIBINPUT_ATTR_THUMB_PRESSURE_THRESHOLD', INTEGER('Y')),
     )
     value_props = [Literal(name)('NAME') - Suppress('=') - val('VALUE') for
                    name, val in vprops]