Same algorithm as in evdev-touchpad.

Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net>
---
 src/evdev-mt-touchpad.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 856d54f..f625814 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -23,10 +23,12 @@
 #include "config.h"
 
 #include <assert.h>
+#include <math.h>
 #include <stdbool.h>
 
 #include "evdev.h"
 
+#define DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR 700.0
 #define TOUCHPAD_HISTORY_LENGTH 4
 
 #define tp_for_each_touch(_tp, _t) \
@@ -56,6 +58,11 @@ struct tp_touch {
                unsigned int index;
                unsigned int count;
        } history;
+
+       struct {
+               int32_t center_x;
+               int32_t center_y;
+       } hysteresis;
 };
 
 struct tp_dispatch {
@@ -66,8 +73,27 @@ struct tp_dispatch {
 
        unsigned int ntouches;                  /* number of slots */
        struct tp_touch *touches;               /* len == ntouches */
+
+       struct {
+               int32_t margin_x;
+               int32_t margin_y;
+       } hysteresis;
 };
 
+static inline int
+tp_hysteresis(int in, int center, int margin)
+{
+       int diff = in - center;
+       if (abs(diff) <= margin)
+               return center;
+
+       if (diff > margin)
+               return center + diff - margin;
+       else if (diff < -margin)
+               return center + diff + margin;
+       return center + diff;
+}
+
 static inline struct tp_motion *
 tp_motion_history_offset(struct tp_touch *t, int offset)
 {
@@ -92,6 +118,30 @@ tp_motion_history_push(struct tp_touch *t)
 }
 
 static inline void
+tp_motion_hysteresis(struct tp_dispatch *tp,
+                    struct tp_touch *t)
+{
+       int x = t->x,
+           y = t->y;
+
+       if (t->history.count == 0) {
+               t->hysteresis.center_x = t->x;
+               t->hysteresis.center_y = t->y;
+       } else {
+               x = tp_hysteresis(x,
+                                 t->hysteresis.center_x,
+                                 tp->hysteresis.margin_x);
+               y = tp_hysteresis(y,
+                                 t->hysteresis.center_y,
+                                 tp->hysteresis.margin_y);
+               t->hysteresis.center_x = x;
+               t->hysteresis.center_y = y;
+               t->x = x;
+               t->y = y;
+       }
+}
+
+static inline void
 tp_motion_history_reset(struct tp_touch *t)
 {
        t->history.count = 0;
@@ -210,6 +260,7 @@ tp_process_state(struct tp_dispatch *tp, uint32_t time)
                if (!t->dirty)
                        continue;
 
+               tp_motion_hysteresis(tp, t);
                tp_motion_history_push(t);
        }
 }
@@ -311,12 +362,24 @@ static int
 tp_init(struct tp_dispatch *tp,
        struct evdev_device *device)
 {
+       int width, height;
+       double diagonal;
+
        tp->base.interface = &tp_interface;
        tp->device = device;
 
        if (tp_init_slots(tp, device) != 0)
                return -1;
 
+       width = abs(device->abs.max_x - device->abs.min_x);
+       height = abs(device->abs.max_y - device->abs.min_y);
+       diagonal = sqrt(width*width + height*height);
+
+       tp->hysteresis.margin_x =
+               diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
+       tp->hysteresis.margin_y =
+               diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
+
        return 0;
 }
 
-- 
1.8.4.2

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to