touchpad: accumulate the initial scroll edge delta

The previous setting of 10 wasn't 10 mm, it was used against the deltas
normalized to a 1000DPI mouse, i.e. closer to 4mm. It was also also per-event,
so a slow movement or a high-frequency touchpad can struggle to meet the
threshold.

Change the trigger to be ~5 mm from the initial touch down, accumulated until
we either meet the threshold or the timeout expires. The first scroll event
includes the delta since the touch down rather than the most recent delta.
This removes the delay otherwise seen in scrolling and makes the scroll motion
match the finger motion. This accumulated delta only applies when exceeding
the motion threshold, when the timeout triggers the switch to scrolling the
first delta posted is the current delta.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
This commit is contained in:
Peter Hutterer 2015-03-06 14:36:31 +10:00
parent 82be678e79
commit 1cebdc7a2b
5 changed files with 54 additions and 8 deletions

View file

@ -34,8 +34,7 @@
avoid accidentally locking in scrolling mode when trying to use the entire
touchpad to move the pointer. The user can wait for the timeout to trigger
to do a small scroll. */
/* In mm for touchpads with valid resolution, see tp_init_accel() */
#define DEFAULT_SCROLL_THRESHOLD 10.0
#define DEFAULT_SCROLL_THRESHOLD TP_MM_TO_DPI_NORMALIZED(5)
enum scroll_event {
SCROLL_EVENT_TOUCH,
@ -78,6 +77,8 @@ tp_edge_scroll_set_state(struct tp_dispatch *tp,
break;
case EDGE_SCROLL_TOUCH_STATE_EDGE_NEW:
t->scroll.edge = tp_touch_get_edge(tp, t);
t->scroll.initial_x = t->x;
t->scroll.initial_y = t->y;
libinput_timer_set(&t->scroll.timer,
t->millis + DEFAULT_SCROLL_LOCK_TIMEOUT);
break;
@ -315,6 +316,7 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
struct tp_touch *t;
enum libinput_pointer_axis axis;
double dx, dy, *delta;
double initial_dx, initial_dy, *initial_delta;
if (tp->scroll.method != LIBINPUT_CONFIG_SCROLL_EDGE)
return 0;
@ -338,10 +340,12 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
case EDGE_RIGHT:
axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL;
delta = &dy;
initial_delta = &initial_dy;
break;
case EDGE_BOTTOM:
axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL;
delta = &dx;
initial_delta = &initial_dx;
break;
default: /* EDGE_RIGHT | EDGE_BOTTOM */
continue; /* Don't know direction yet, skip */
@ -350,7 +354,34 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
tp_get_delta(t, &dx, &dy);
tp_filter_motion(tp, &dx, &dy, NULL, NULL, time);
if (fabs(*delta) < t->scroll.threshold)
switch (t->scroll.edge_state) {
case EDGE_SCROLL_TOUCH_STATE_NONE:
case EDGE_SCROLL_TOUCH_STATE_AREA:
log_bug_libinput(device->seat->libinput,
"unexpected scroll state %d\n",
t->scroll.edge_state);
break;
case EDGE_SCROLL_TOUCH_STATE_EDGE_NEW:
initial_dx = t->x - t->scroll.initial_x;
initial_dy = t->y - t->scroll.initial_y;
tp_normalize_delta(tp,
&initial_dx,
&initial_dy);
if (fabs(*initial_delta) < t->scroll.threshold) {
dx = 0.0;
dy = 0.0;
} else {
dx = initial_dx;
dy = initial_dy;
}
break;
case EDGE_SCROLL_TOUCH_STATE_EDGE:
if (fabs(*delta) < t->scroll.threshold)
*delta = 0.0;
break;
}
if (*delta == 0.0)
continue;
pointer_notify_axis(device, time,

View file

@ -176,6 +176,8 @@ struct tp_touch {
int direction;
double threshold;
struct libinput_timer timer;
int32_t initial_x; /* in device coordinates */
int32_t initial_y; /* in device coordinates */
} scroll;
struct {

View file

@ -1390,6 +1390,12 @@ litest_timeout_finger_switch(void)
msleep(120);
}
void
litest_timeout_edgescroll(void)
{
msleep(300);
}
void
litest_push_event_frame(struct litest_device *dev)
{

View file

@ -183,6 +183,7 @@ struct libevdev_uinput * litest_create_uinput_abs_device(const char *name,
void litest_timeout_tap(void);
void litest_timeout_softbuttons(void);
void litest_timeout_buttonscroll(void);
void litest_timeout_edgescroll(void);
void litest_timeout_finger_switch(void);
void litest_push_event_frame(struct litest_device *dev);

View file

@ -2057,7 +2057,7 @@ START_TEST(touchpad_edge_scroll)
}
END_TEST
START_TEST(touchpad_edge_scroll_slow_distance)
START_TEST(touchpad_edge_scroll_timeout)
{
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
@ -2067,6 +2067,10 @@ START_TEST(touchpad_edge_scroll_slow_distance)
litest_drain_events(li);
litest_touch_down(dev, 0, 99, 20);
libinput_dispatch(li);
litest_timeout_edgescroll();
libinput_dispatch(li);
litest_touch_move_to(dev, 0, 99, 20, 99, 80, 60, 10);
litest_touch_up(dev, 0);
libinput_dispatch(li);
@ -2074,6 +2078,8 @@ START_TEST(touchpad_edge_scroll_slow_distance)
event = libinput_get_event(li);
ck_assert_notnull(event);
litest_wait_for_event_of_type(li, LIBINPUT_EVENT_POINTER_AXIS, -1);
while (libinput_next_event_type(li) != LIBINPUT_EVENT_NONE) {
double axisval;
ck_assert_int_eq(libinput_event_get_type(event),
@ -2105,10 +2111,10 @@ START_TEST(touchpad_edge_scroll_no_motion)
litest_drain_events(li);
litest_touch_down(dev, 0, 99, 20);
litest_touch_move_to(dev, 0, 99, 20, 99, 60, 10, 0);
litest_touch_down(dev, 0, 99, 10);
litest_touch_move_to(dev, 0, 99, 10, 99, 70, 10, 0);
/* moving outside -> no motion event */
litest_touch_move_to(dev, 0, 99, 60, 20, 80, 10, 0);
litest_touch_move_to(dev, 0, 99, 70, 20, 80, 10, 0);
/* moving down outside edge once scrolling had started -> scroll */
litest_touch_move_to(dev, 0, 20, 80, 40, 99, 10, 0);
litest_touch_up(dev, 0);
@ -3427,7 +3433,7 @@ int main(int argc, char **argv) {
litest_add("touchpad:scroll", touchpad_edge_scroll, LITEST_TOUCHPAD|LITEST_SINGLE_TOUCH, LITEST_ANY);
litest_add("touchpad:scroll", touchpad_edge_scroll_no_motion, LITEST_TOUCHPAD|LITEST_SINGLE_TOUCH, LITEST_ANY);
litest_add("touchpad:scroll", touchpad_edge_scroll_no_edge_after_motion, LITEST_TOUCHPAD|LITEST_SINGLE_TOUCH, LITEST_ANY);
litest_add("touchpad:scroll", touchpad_edge_scroll_slow_distance, LITEST_TOUCHPAD|LITEST_SINGLE_TOUCH, LITEST_ANY);
litest_add("touchpad:scroll", touchpad_edge_scroll_timeout, LITEST_TOUCHPAD|LITEST_SINGLE_TOUCH, LITEST_ANY);
litest_add("touchpad:scroll", touchpad_edge_scroll_source, LITEST_TOUCHPAD|LITEST_SINGLE_TOUCH, LITEST_ANY);
litest_add("touchpad:palm", touchpad_palm_detect_at_edge, LITEST_TOUCHPAD, LITEST_ANY);