From 8a91c2aa849c73f27ad1cd23738a70b9ad38639f Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Jun 02 2015 01:11:00 +0000 Subject: Handle slow motions better (#1227039) --- diff --git a/0001-filter-pass-last_velocity-as-argument.patch b/0001-filter-pass-last_velocity-as-argument.patch new file mode 100644 index 0000000..852108c --- /dev/null +++ b/0001-filter-pass-last_velocity-as-argument.patch @@ -0,0 +1,58 @@ +From 578c4e81c2606abb969972186b013f67fb152040 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Thu, 30 Apr 2015 15:23:34 +1000 +Subject: [PATCH libinput 1/3] filter: pass last_velocity as argument + +Let the caller set the various fields, here we just calculate stuff. +No functional changes. + +Signed-off-by: Peter Hutterer +Reviewed-by: Hans de Goede +--- + src/filter.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +diff --git a/src/filter.c b/src/filter.c +index 0cdcb63..fe86215 100644 +--- a/src/filter.c ++++ b/src/filter.c +@@ -197,17 +197,20 @@ acceleration_profile(struct pointer_accelerator *accel, + + static double + calculate_acceleration(struct pointer_accelerator *accel, +- void *data, double velocity, uint64_t time) ++ void *data, ++ double velocity, ++ double last_velocity, ++ uint64_t time) + { + double factor; + + /* Use Simpson's rule to calculate the avarage acceleration between + * the previous motion and the most recent. */ + factor = acceleration_profile(accel, data, velocity, time); +- factor += acceleration_profile(accel, data, accel->last_velocity, time); ++ factor += acceleration_profile(accel, data, last_velocity, time); + factor += 4.0 * + acceleration_profile(accel, data, +- (accel->last_velocity + velocity) / 2, ++ (last_velocity + velocity) / 2, + time); + + factor = factor / 6.0; +@@ -228,7 +231,11 @@ accelerator_filter(struct motion_filter *filter, + + feed_trackers(accel, unaccelerated, time); + velocity = calculate_velocity(accel, time); +- accel_value = calculate_acceleration(accel, data, velocity, time); ++ accel_value = calculate_acceleration(accel, ++ data, ++ velocity, ++ accel->last_velocity, ++ time); + + accelerated.x = accel_value * unaccelerated->x; + accelerated.y = accel_value * unaccelerated->y; +-- +2.4.1 + diff --git a/0002-filter-up-the-motion-timeout-to-1-second.patch b/0002-filter-up-the-motion-timeout-to-1-second.patch new file mode 100644 index 0000000..d7e9428 --- /dev/null +++ b/0002-filter-up-the-motion-timeout-to-1-second.patch @@ -0,0 +1,34 @@ +From a81051e5136aeb23ce0ed85e387ae2d9b9447faa Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Wed, 22 Apr 2015 11:46:57 +1000 +Subject: [PATCH libinput 2/3] filter: up the motion timeout to 1 second + +This timeout defines how far back in the events we search for velocity +calculations. For really slow movements, 300ms is not enough. It causes the +velocity to be 0 -> accel factor of 0 -> no movement. +As a result, really slow movement does not move the cursor. + +Up the timeout to 1 second instead. + +Signed-off-by: Peter Hutterer +Reviewed-by: Hans de Goede +--- + src/filter.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/filter.c b/src/filter.c +index fe86215..3845c7f 100644 +--- a/src/filter.c ++++ b/src/filter.c +@@ -78,7 +78,7 @@ filter_get_speed(struct motion_filter *filter) + */ + + #define MAX_VELOCITY_DIFF 1.0 /* units/ms */ +-#define MOTION_TIMEOUT 300 /* (ms) */ ++#define MOTION_TIMEOUT 1000 /* (ms) */ + #define NUM_POINTER_TRACKERS 16 + + struct pointer_tracker { +-- +2.4.1 + diff --git a/0003-filter-enforce-minimum-velocity.patch b/0003-filter-enforce-minimum-velocity.patch new file mode 100644 index 0000000..61b5b16 --- /dev/null +++ b/0003-filter-enforce-minimum-velocity.patch @@ -0,0 +1,130 @@ +From 289e4675c81d2fe32650295ce2b6a66a1ebb9f24 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Wed, 22 Apr 2015 12:25:13 +1000 +Subject: [PATCH libinput 3/3] filter: enforce minimum velocity + +In the current code, a timeout or direction change on the first tracker will +result in a velocity of 0. Really slow movements will thus always be zero, and +the first event after a direction is swallowed. + +Enforce a minimum velocity: +In the case of a timeout, assume the current velocity is that of +distance/timeout. In the case of a direction change, the velocity is simply +that since the last tracker. + +Signed-off-by: Peter Hutterer +Reviewed-by: Hans de Goede +--- + src/filter.c | 34 ++++++++++++++++++++++++++++++---- + test/touchpad.c | 10 +++++----- + 2 files changed, 35 insertions(+), 9 deletions(-) + +diff --git a/src/filter.c b/src/filter.c +index 3845c7f..c54d866 100644 +--- a/src/filter.c ++++ b/src/filter.c +@@ -144,6 +144,24 @@ calculate_tracker_velocity(struct pointer_tracker *tracker, uint64_t time) + return normalized_length(tracker->delta) / tdelta; /* units/ms */ + } + ++static inline double ++calculate_velocity_after_timeout(struct pointer_tracker *tracker) ++{ ++ /* First movement after timeout needs special handling. ++ * ++ * When we trigger the timeout, the last event is too far in the ++ * past to use it for velocity calculation across multiple tracker ++ * values. ++ * ++ * Use the motion timeout itself to calculate the speed rather than ++ * the last tracker time. This errs on the side of being too fast ++ * for really slow movements but provides much more useful initial ++ * movement in normal use-cases (pause, move, pause, move) ++ */ ++ return calculate_tracker_velocity(tracker, ++ tracker->time + MOTION_TIMEOUT); ++} ++ + static double + calculate_velocity(struct pointer_accelerator *accel, uint64_t time) + { +@@ -163,15 +181,23 @@ calculate_velocity(struct pointer_accelerator *accel, uint64_t time) + + /* Stop if too far away in time */ + if (time - tracker->time > MOTION_TIMEOUT || +- tracker->time > time) ++ tracker->time > time) { ++ if (offset == 1) ++ result = calculate_velocity_after_timeout(tracker); + break; ++ } ++ ++ velocity = calculate_tracker_velocity(tracker, time); + + /* Stop if direction changed */ + dir &= tracker->dir; +- if (dir == 0) ++ if (dir == 0) { ++ /* First movement after dirchange - velocity is that ++ * of the last movement */ ++ if (offset == 1) ++ result = velocity; + break; +- +- velocity = calculate_tracker_velocity(tracker, time); ++ } + + if (initial_velocity == 0.0) { + result = initial_velocity = velocity; +diff --git a/test/touchpad.c b/test/touchpad.c +index 5579c04..a747910 100644 +--- a/test/touchpad.c ++++ b/test/touchpad.c +@@ -2959,7 +2959,7 @@ START_TEST(touchpad_edge_scroll) + litest_touch_up(dev, 0); + + libinput_dispatch(li); +- litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 10); ++ litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 4); + litest_assert_empty_queue(li); + + litest_touch_down(dev, 0, 99, 80); +@@ -2967,7 +2967,7 @@ START_TEST(touchpad_edge_scroll) + litest_touch_up(dev, 0); + + libinput_dispatch(li); +- litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, -10); ++ litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, -4); + litest_assert_empty_queue(li); + + litest_touch_down(dev, 0, 20, 99); +@@ -2975,7 +2975,7 @@ START_TEST(touchpad_edge_scroll) + litest_touch_up(dev, 0); + + libinput_dispatch(li); +- litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, 10); ++ litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, 4); + litest_assert_empty_queue(li); + + litest_touch_down(dev, 0, 70, 99); +@@ -2983,7 +2983,7 @@ START_TEST(touchpad_edge_scroll) + litest_touch_up(dev, 0); + + libinput_dispatch(li); +- litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, -10); ++ litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, -4); + litest_assert_empty_queue(li); + } + END_TEST +@@ -3065,7 +3065,7 @@ START_TEST(touchpad_edge_scroll_no_motion) + litest_touch_up(dev, 0); + libinput_dispatch(li); + +- litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 5); ++ litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 4); + litest_assert_empty_queue(li); + } + END_TEST +-- +2.4.1 + diff --git a/libinput.spec b/libinput.spec index 1dd25fe..eb96b0b 100644 --- a/libinput.spec +++ b/libinput.spec @@ -5,7 +5,7 @@ Name: libinput Version: 0.16.0 -Release: 1%{?gitdate:.%{gitdate}git%{gitversion}}%{?dist} +Release: 2%{?gitdate:.%{gitdate}git%{gitversion}}%{?dist} Summary: Input device library License: MIT @@ -18,6 +18,10 @@ Source2: commitid Source0: http://www.freedesktop.org/software/libinput/libinput-%{version}.tar.xz %endif +Patch01: 0001-filter-pass-last_velocity-as-argument.patch +Patch02: 0002-filter-up-the-motion-timeout-to-1-second.patch +Patch03: 0003-filter-enforce-minimum-velocity.patch + BuildRequires: git BuildRequires: autoconf automake libtool pkgconfig BuildRequires: libevdev-devel @@ -93,6 +97,9 @@ find $RPM_BUILD_ROOT -name '*.la' -delete %changelog +* Tue Jun 02 2015 Peter Hutterer 0.16.0-2 +- Handle slow motions better (#1227039) + * Tue Jun 02 2015 Peter Hutterer 0.16.0-1 - libinput 0.16.0