Handle slow motions better (#1227039)

This commit is contained in:
Peter Hutterer 2015-06-02 11:11:00 +10:00
parent 1a6d239ed3
commit 8a91c2aa84
4 changed files with 230 additions and 1 deletions

View File

@ -0,0 +1,58 @@
From 578c4e81c2606abb969972186b013f67fb152040 Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
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 <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
---
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

View File

@ -0,0 +1,34 @@
From a81051e5136aeb23ce0ed85e387ae2d9b9447faa Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
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 <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
---
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

View File

@ -0,0 +1,130 @@
From 289e4675c81d2fe32650295ce2b6a66a1ebb9f24 Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
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 <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
---
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

View File

@ -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 <peter.hutterer@redhat.com> 0.16.0-2
- Handle slow motions better (#1227039)
* Tue Jun 02 2015 Peter Hutterer <peter.hutterer@redhat.com> 0.16.0-1
- libinput 0.16.0