This is a fairly rough approach, but can be handled more fine-grained later.
Require a minimum of 1 unit to start scrolling and lock the scrolling in the
initial direction, so further scroll events are limited to that direction
only.

Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net>
---
 src/evdev-mt-touchpad.c | 82 +++++++++++++++++++++++++++++++++++++++++--------
 src/evdev-mt-touchpad.h | 10 ++++++
 2 files changed, 79 insertions(+), 13 deletions(-)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 873ddf0..14fb7f3 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -310,16 +310,64 @@ tp_post_twofinger_scroll(struct tp_dispatch *tp, uint32_t 
time)
 
        tp_filter_motion(tp, &dx, &dy, time);
 
-       if (dx != 0.0)
-               pointer_notify_axis(&tp->device->base,
-                                   time,
-                                   LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL,
-                                   li_fixed_from_double(dx));
-       if (dy != 0.0)
+       if (tp->scroll.state == SCROLL_STATE_NONE) {
+               /* Require at least one px scrolling to start */
+               if (dx <= -1.0 || dx >= 1.0) {
+                       tp->scroll.state = SCROLL_STATE_SCROLLING;
+                       tp->scroll.direction |= (1 << 
LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL);
+               }
+
+               if (dy <= -1.0 || dy >= 1.0) {
+                       tp->scroll.state = SCROLL_STATE_SCROLLING;
+                       tp->scroll.direction |= (1 << 
LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL);
+               }
+
+               if (tp->scroll.state == SCROLL_STATE_NONE)
+                       return;
+       }
+
+       if (dy != 0.0 &&
+           (tp->scroll.direction & (1 << 
LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL))) {
                pointer_notify_axis(&tp->device->base,
                                    time,
                                    LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL,
                                    li_fixed_from_double(dy));
+       }
+
+       if (dx != 0.0 &&
+           (tp->scroll.direction & (1 << 
LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL))) {
+               pointer_notify_axis(&tp->device->base,
+                                   time,
+                                   LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL,
+                                   li_fixed_from_double(dx));
+       }
+}
+
+static int
+tp_post_scroll_events(struct tp_dispatch *tp, uint32_t time)
+{
+       if (tp->nfingers_down != 2) {
+               /* terminate scrolling with a zero scroll event to notify
+                * caller that it really ended now */
+               if (tp->scroll.state != SCROLL_STATE_NONE) {
+                       tp->scroll.state = SCROLL_STATE_NONE;
+                       tp->scroll.direction = 0;
+                       if (tp->scroll.direction & 
LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL)
+                               pointer_notify_axis(&tp->device->base,
+                                                   time,
+                                                   
LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL,
+                                                   0);
+                       if (tp->scroll.direction & 
LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL)
+                               pointer_notify_axis(&tp->device->base,
+                                                   time,
+                                                   
LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL,
+                                                   0);
+               }
+       } else {
+               tp_post_twofinger_scroll(tp, time);
+               return 1;
+       }
+       return 0;
 }
 
 static void
@@ -362,16 +410,12 @@ tp_post_events(struct tp_dispatch *tp, uint32_t time)
        struct tp_touch *t = tp_current_touch(tp);
        double dx, dy;
 
-       if (tp->nfingers_down > 2) {
-               return;
-       } else if (tp->nfingers_down == 2) {
-               tp_post_twofinger_scroll(tp, time);
-               return;
-       }
-
        if (tp_tap_handle_state(tp, time) != 0)
                return;
 
+       if (tp_post_scroll_events(tp, time) != 0)
+               return;
+
        if (t->history.count >= TOUCHPAD_MIN_SAMPLES) {
                tp_get_delta(t, &dx, &dy);
                tp_filter_motion(tp, &dx, &dy, time);
@@ -464,6 +508,15 @@ tp_init_accel(struct tp_dispatch *touchpad, double 
diagonal)
 }
 
 static int
+tp_init_scroll(struct tp_dispatch *tp)
+{
+       tp->scroll.direction = 0;
+       tp->scroll.state = SCROLL_STATE_NONE;
+
+       return 0;
+}
+
+static int
 tp_init(struct tp_dispatch *tp,
        struct evdev_device *device)
 {
@@ -485,6 +538,9 @@ tp_init(struct tp_dispatch *tp,
        tp->hysteresis.margin_y =
                diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
 
+       if (tp_init_scroll(tp) != 0)
+               return -1;
+
        if (tp_init_accel(tp, diagonal) != 0)
                return -1;
 
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index a5cfaa6..17e9055 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -46,6 +46,11 @@ enum touch_state {
        TOUCH_END
 };
 
+enum scroll_state {
+       SCROLL_STATE_NONE,
+       SCROLL_STATE_SCROLLING
+};
+
 enum tp_tap_state {
        TAP_STATE_IDLE = 4,
        TAP_STATE_TOUCH,
@@ -113,6 +118,11 @@ struct tp_dispatch {
                uint32_t old_state;
        } buttons;                              /* physical buttons */
 
+       struct {
+               enum scroll_state state;
+               enum libinput_pointer_axis direction;
+       } scroll;
+
        enum touchpad_event queued;
 
        struct {
-- 
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