From: Peter Hutterer <peter.hutte...@who-t.net> On clickpads, clicking the pad usually causes some motion events. To avoid erroneous movements, lock the finger into position on the click and don't allow for motion events until we move past a given threshold (currently 2% of the touchpad diagonal).
HdG: Instead of pinning the lowest touch assuming that that is the one holding the physical button, simply pin all touches, and unpin as soon as a touch is moved more then the threshold. Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net> Signed-off-by: Hans de Goede <hdego...@redhat.com> --- src/evdev-mt-touchpad.c | 79 ++++++++++++++++++++++++------------------------- src/evdev-mt-touchpad.h | 12 +++++++- 2 files changed, 49 insertions(+), 42 deletions(-) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 8021db2..fbe0a7b 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -32,6 +32,7 @@ #define DEFAULT_MIN_ACCEL_FACTOR 0.16 #define DEFAULT_MAX_ACCEL_FACTOR 1.0 #define DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR 700.0 +#define DEFAULT_BUTTON_MOTION_THRESHOLD 0.02 /* in percent of size */ static inline int tp_hysteresis(int in, int center, int margin) @@ -182,6 +183,7 @@ tp_end_touch(struct tp_dispatch *tp, struct tp_touch *t) t->dirty = true; t->is_pointer = false; t->state = TOUCH_END; + t->pinned.is_pinned = false; assert(tp->nfingers_down >= 1); tp->nfingers_down--; tp->queued |= TOUCHPAD_EVENT_MOTION; @@ -346,50 +348,43 @@ tp_process_key(struct tp_dispatch *tp, } static void -tp_unpin_finger(struct tp_dispatch *tp) +tp_unpin_finger(struct tp_dispatch *tp, struct tp_touch *t) { - struct tp_touch *t; - tp_for_each_touch(tp, t) { - if (t->is_pinned) { - t->is_pinned = false; + unsigned int xdist, ydist; + struct tp_touch *tmp; + + if (!t->pinned.is_pinned) + return; + + xdist = abs(t->x - t->pinned.center_x); + ydist = abs(t->y - t->pinned.center_y); - if (t->state != TOUCH_END && - tp->nfingers_down == 1) - t->is_pointer = true; + if (xdist * xdist + ydist * ydist < + tp->buttons.motion_dist * tp->buttons.motion_dist) + return; + + t->pinned.is_pinned = false; + + tp_for_each_touch(tp, tmp) { + if (tmp->is_pointer) break; - } } + + if (t->state != TOUCH_END && !tmp->is_pointer) + t->is_pointer = true; } static void -tp_pin_finger(struct tp_dispatch *tp) +tp_pin_fingers(struct tp_dispatch *tp) { - struct tp_touch *t, - *pinned = NULL; + struct tp_touch *t; tp_for_each_touch(tp, t) { - if (t->is_pinned) { - pinned = t; - break; - } - } - - assert(!pinned); - - pinned = tp_current_touch(tp); - - if (tp->nfingers_down != 1) { - tp_for_each_touch(tp, t) { - if (t == pinned) - continue; - - if (t->y > pinned->y) - pinned = t; - } + t->is_pointer = false; + t->pinned.is_pinned = true; + t->pinned.center_x = t->x; + t->pinned.center_y = t->y; } - - pinned->is_pinned = true; - pinned->is_pointer = false; } static void @@ -409,16 +404,19 @@ tp_process_state(struct tp_dispatch *tp, uint32_t time) tp_motion_hysteresis(tp, t); tp_motion_history_push(t); + + tp_unpin_finger(tp, t); } - /* We have a physical button down event on a clickpad. For drag and - drop, this means we try to identify which finger pressed the - physical button and "pin" it, i.e. remove pointer-moving - capabilities from it. + /* + * We have a physical button down event on a clickpad. To avoid + * spurious pointer moves by the clicking finger we pin all fingers. + * We unpin fingers when they move more then a certain threshold to + * to allow drag and drop. */ if ((tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS) && !tp->buttons.has_buttons) - tp_pin_finger(tp); + tp_pin_fingers(tp); } static void @@ -441,9 +439,6 @@ tp_post_process_state(struct tp_dispatch *tp, uint32_t time) tp->buttons.old_state = tp->buttons.state; - if (tp->queued & TOUCHPAD_EVENT_BUTTON_RELEASE) - tp_unpin_finger(tp); - tp->queued = TOUCHPAD_EVENT_NONE; } @@ -796,6 +791,8 @@ tp_init(struct tp_dispatch *tp, tp->hysteresis.margin_y = diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR; + tp->buttons.motion_dist = diagonal * DEFAULT_BUTTON_MOTION_THRESHOLD; + if (libevdev_has_event_code(device->evdev, EV_KEY, BTN_MIDDLE) || libevdev_has_event_code(device->evdev, EV_KEY, BTN_RIGHT)) tp->buttons.has_buttons = true; diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index 2bdb329..e5fbd7a 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -77,7 +77,6 @@ struct tp_touch { bool dirty; bool fake; /* a fake touch */ bool is_pointer; /* the pointer-controlling touch */ - bool is_pinned; /* holds the phys. button */ int32_t x; int32_t y; uint32_t millis; @@ -92,6 +91,16 @@ struct tp_touch { int32_t center_x; int32_t center_y; } hysteresis; + + /* A pinned touchpoint is the one that pressed the physical button + * on a clickpad. After the release, it won't move until the center + * moves more than a threshold away from the original coordinates + */ + struct { + bool is_pinned; + int32_t center_x; + int32_t center_y; + } pinned; }; struct tp_dispatch { @@ -122,6 +131,7 @@ struct tp_dispatch { bool has_buttons; /* true for physical LMR buttons */ uint32_t state; uint32_t old_state; + uint32_t motion_dist; /* for pinned touches */ } buttons; /* physical buttons */ struct { -- 1.9.0 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel