evdev: simplify hysteresis code and document it
authorPeter Hutterer <peter.hutterer@who-t.net>
Mon, 21 Nov 2016 02:24:45 +0000 (12:24 +1000)
committerPeter Hutterer <peter.hutterer@who-t.net>
Tue, 22 Nov 2016 01:23:39 +0000 (11:23 +1000)
center + diff is the input coordinate. Simplify the code so it's clear what
we're returning. And document the function to explain what it does.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
src/evdev.h

index 888cc283513a5444a96ab381ac23f96599ea9147..088860083fe6cca3c1abfcf13ec2128fe9dd7fe3 100644 (file)
@@ -530,6 +530,38 @@ evdev_to_left_handed(struct evdev_device *device,
        return button;
 }
 
+/**
+ * Apply a hysteresis filtering to the coordinate in, based on the current
+ * hystersis center and the margin. If 'in' is within 'margin' of center,
+ * return the center (and thus filter the motion). If 'in' is outside,
+ * return a point on the edge of the new margin. So for a point x in the
+ * space outside c + margin we return r:
+ * +---+       +---+
+ * | c |  x →  | r x
+ * +---+       +---+
+ *
+ * The effect of this is that initial small motions are filtered. Once we
+ * move into one direction we lag the real coordinates by 'margin' but any
+ * movement that continues into that direction will always be just outside
+ * margin - we get responsive movement. Once we move back into the other
+ * direction, the first movements are filtered again.
+ *
+ * Returning the edge rather than the point avoids cursor jumps, as the
+ * first reachable coordinate is the point next to the center (center + 1).
+ * Otherwise, the center has a dead zone of size margin around it and the
+ * first reachable point is the margin edge.
+ *
+ * Hysteresis is handled separately per axis (and the window is thus
+ * rectangular, not circular). It is unkown if that's an issue, but the
+ * calculation to do circular hysteresis are nontrivial, especially since
+ * many touchpads have uneven x/y resolutions.
+ *
+ * @param in The input coordinate
+ * @param center Current center of the hysteresis
+ * @param margin Hysteresis width (on each side)
+ *
+ * @return The new center of the hysteresis
+ */
 static inline int
 evdev_hysteresis(int in, int center, int margin)
 {
@@ -537,10 +569,10 @@ evdev_hysteresis(int in, int center, int margin)
        if (abs(diff) <= margin)
                return center;
 
-       if (diff > margin)
-               return center + diff - margin;
+       if (diff > 0)
+               return in - margin;
        else
-               return center + diff + margin;
+               return in + margin;
 }
 
 static inline struct libinput *