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);
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);
@ -463,6 +507,15 @@ tp_init_accel(struct tp_dispatch *touchpad, double diagonal)
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
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;

View file

@ -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 {