touchpad: require minimum scroll distance and lock scroll direction

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.hutterer@who-t.net>
This commit is contained in:
Peter Hutterer 2014-02-14 12:31:26 +10:00
parent 0d759edc3f
commit c1a9b24a0a
2 changed files with 79 additions and 13 deletions

View file

@ -310,16 +310,64 @@ tp_post_twofinger_scroll(struct tp_dispatch *tp, uint32_t time)
tp_filter_motion(tp, &dx, &dy, time); tp_filter_motion(tp, &dx, &dy, time);
if (dx != 0.0) if (tp->scroll.state == SCROLL_STATE_NONE) {
pointer_notify_axis(&tp->device->base, /* Require at least one px scrolling to start */
time, if (dx <= -1.0 || dx >= 1.0) {
LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL, tp->scroll.state = SCROLL_STATE_SCROLLING;
li_fixed_from_double(dx)); tp->scroll.direction |= (1 << LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL);
if (dy != 0.0) }
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, pointer_notify_axis(&tp->device->base,
time, time,
LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL, LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL,
li_fixed_from_double(dy)); 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 static void
@ -362,16 +410,12 @@ tp_post_events(struct tp_dispatch *tp, uint32_t time)
struct tp_touch *t = tp_current_touch(tp); struct tp_touch *t = tp_current_touch(tp);
double dx, dy; 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) if (tp_tap_handle_state(tp, time) != 0)
return; return;
if (tp_post_scroll_events(tp, time) != 0)
return;
if (t->history.count >= TOUCHPAD_MIN_SAMPLES) { if (t->history.count >= TOUCHPAD_MIN_SAMPLES) {
tp_get_delta(t, &dx, &dy); tp_get_delta(t, &dx, &dy);
tp_filter_motion(tp, &dx, &dy, time); tp_filter_motion(tp, &dx, &dy, time);
@ -463,6 +507,15 @@ tp_init_accel(struct tp_dispatch *touchpad, double diagonal)
return 0; return 0;
} }
static int
tp_init_scroll(struct tp_dispatch *tp)
{
tp->scroll.direction = 0;
tp->scroll.state = SCROLL_STATE_NONE;
return 0;
}
static int static int
tp_init(struct tp_dispatch *tp, tp_init(struct tp_dispatch *tp,
struct evdev_device *device) struct evdev_device *device)
@ -485,6 +538,9 @@ tp_init(struct tp_dispatch *tp,
tp->hysteresis.margin_y = tp->hysteresis.margin_y =
diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR; diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
if (tp_init_scroll(tp) != 0)
return -1;
if (tp_init_accel(tp, diagonal) != 0) if (tp_init_accel(tp, diagonal) != 0)
return -1; return -1;

View file

@ -46,6 +46,11 @@ enum touch_state {
TOUCH_END TOUCH_END
}; };
enum scroll_state {
SCROLL_STATE_NONE,
SCROLL_STATE_SCROLLING
};
enum tp_tap_state { enum tp_tap_state {
TAP_STATE_IDLE = 4, TAP_STATE_IDLE = 4,
TAP_STATE_TOUCH, TAP_STATE_TOUCH,
@ -113,6 +118,11 @@ struct tp_dispatch {
uint32_t old_state; uint32_t old_state;
} buttons; /* physical buttons */ } buttons; /* physical buttons */
struct {
enum scroll_state state;
enum libinput_pointer_axis direction;
} scroll;
enum touchpad_event queued; enum touchpad_event queued;
struct { struct {