touchpad: revert to pointer movement when stopping twofinger scrolling

Add a boolean state machine for two-finger scrolling so we know when we're
currently scrolling. If we were scrolling and it stops, pick the active
touch as pointer touch so we can go back to pointer movement without having to
lift the finger off the touchpad.

https://bugs.freedesktop.org/show_bug.cgi?id=86807

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Peter Hutterer 2014-12-18 10:37:38 +10:00
parent 54c972402f
commit 6028e126fe
3 changed files with 79 additions and 6 deletions

View file

@ -436,6 +436,33 @@ tp_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
tp_filter_motion(tp, &dx, &dy, NULL, NULL, time);
evdev_post_scroll(tp->device, time, dx, dy);
tp->scroll.twofinger_state = TWOFINGER_SCROLL_STATE_ACTIVE;
}
static void
tp_twofinger_stop_scroll(struct tp_dispatch *tp, uint64_t time)
{
struct tp_touch *t, *ptr = NULL;
int nfingers_down = 0;
evdev_stop_scroll(tp->device, time);
/* If we were scrolling and now there's exactly 1 active finger,
switch back to pointer movement */
if (tp->scroll.twofinger_state == TWOFINGER_SCROLL_STATE_ACTIVE) {
tp_for_each_touch(tp, t) {
if (tp_touch_active(tp, t)) {
nfingers_down++;
if (ptr == NULL)
ptr = t;
}
}
if (nfingers_down == 1)
tp_set_pointer(tp, ptr);
}
tp->scroll.twofinger_state = TWOFINGER_SCROLL_STATE_NONE;
}
static int
@ -458,13 +485,14 @@ tp_twofinger_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
nfingers_down++;
}
if (nfingers_down != 2) {
evdev_stop_scroll(tp->device, time);
return 0;
if (nfingers_down == 2) {
tp_post_twofinger_scroll(tp, time);
return 1;
}
tp_post_twofinger_scroll(tp, time);
return 1;
tp_twofinger_stop_scroll(tp, time);
return 0;
}
static void
@ -504,7 +532,7 @@ tp_stop_scroll_events(struct tp_dispatch *tp, uint64_t time)
case LIBINPUT_CONFIG_SCROLL_NO_SCROLL:
break;
case LIBINPUT_CONFIG_SCROLL_2FG:
evdev_stop_scroll(tp->device, time);
tp_twofinger_stop_scroll(tp, time);
break;
case LIBINPUT_CONFIG_SCROLL_EDGE:
tp_edge_scroll_stop_events(tp, time);

View file

@ -117,6 +117,11 @@ enum tp_edge_scroll_touch_state {
EDGE_SCROLL_TOUCH_STATE_AREA,
};
enum tp_twofinger_scroll_state {
TWOFINGER_SCROLL_STATE_NONE,
TWOFINGER_SCROLL_STATE_ACTIVE,
};
struct tp_motion {
int32_t x;
int32_t y;
@ -238,6 +243,7 @@ struct tp_dispatch {
enum libinput_config_scroll_method method;
int32_t right_edge;
int32_t bottom_edge;
enum tp_twofinger_scroll_state twofinger_state;
} scroll;
enum touchpad_event queued;

View file

@ -1461,6 +1461,44 @@ START_TEST(touchpad_2fg_scroll_slow_distance)
}
END_TEST
START_TEST(touchpad_2fg_scroll_return_to_motion)
{
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
litest_drain_events(li);
/* start with motion */
litest_touch_down(dev, 0, 70, 70);
litest_touch_move_to(dev, 0, 70, 70, 47, 50, 10, 0);
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
/* 2fg scroll */
litest_touch_down(dev, 1, 53, 50);
litest_touch_move_to(dev, 0, 47, 50, 47, 70, 5, 0);
litest_touch_move_to(dev, 1, 53, 50, 53, 70, 5, 0);
litest_touch_up(dev, 1);
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
litest_touch_move_to(dev, 0, 47, 70, 47, 50, 10, 0);
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
/* back to 2fg scroll, lifting the other finger */
litest_touch_down(dev, 1, 50, 50);
litest_touch_move_to(dev, 0, 47, 50, 47, 70, 5, 0);
litest_touch_move_to(dev, 1, 53, 50, 53, 70, 5, 0);
litest_touch_up(dev, 0);
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
/* move with second finger */
litest_touch_move_to(dev, 1, 53, 70, 53, 50, 10, 0);
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
litest_touch_up(dev, 1);
litest_assert_empty_queue(li);
}
END_TEST
START_TEST(touchpad_scroll_natural_defaults)
{
struct litest_device *dev = litest_current_device();
@ -2059,6 +2097,7 @@ int main(int argc, char **argv) {
litest_add("touchpad:scroll", touchpad_2fg_scroll, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
litest_add("touchpad:scroll", touchpad_2fg_scroll_slow_distance, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
litest_add("touchpad:scroll", touchpad_2fg_scroll_return_to_motion, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
litest_add("touchpad:scroll", touchpad_scroll_natural_defaults, LITEST_TOUCHPAD, LITEST_ANY);
litest_add("touchpad:scroll", touchpad_scroll_natural_enable_config, LITEST_TOUCHPAD, LITEST_ANY);
litest_add("touchpad:scroll", touchpad_scroll_natural, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);