From 317cd252beac6a3094d82b5758681ed00d0e9cb1 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 3 Aug 2015 14:38:38 +1000 Subject: [PATCH 01/43] middle-button: don't call libinput_now() in the timeout handler The argument has "now" already Signed-off-by: Peter Hutterer --- src/evdev-middle-button.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/evdev-middle-button.c b/src/evdev-middle-button.c index 397b699c..b8337153 100644 --- a/src/evdev-middle-button.c +++ b/src/evdev-middle-button.c @@ -640,9 +640,7 @@ evdev_middlebutton_handle_timeout(uint64_t now, void *data) { struct evdev_device *device = (struct evdev_device*)data; - evdev_middlebutton_handle_event(device, - libinput_now(device->base.seat->libinput), - MIDDLEBUTTON_EVENT_TIMEOUT); + evdev_middlebutton_handle_event(device, now, MIDDLEBUTTON_EVENT_TIMEOUT); } static int From 254f87564f485ff44b8426cac3ac7f8efc47e681 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 4 Aug 2015 15:08:25 +1000 Subject: [PATCH 02/43] filter: fix acceleration threshold assignment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new values were in units/us and didn't make the switch back to ms in 8a6825f1602. Signed-off-by: Peter Hutterer Reviewed-by: Jonas Ådahl --- src/filter.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/filter.c b/src/filter.c index 2506ee27..e11d58a9 100644 --- a/src/filter.c +++ b/src/filter.c @@ -78,6 +78,7 @@ filter_get_speed(struct motion_filter *filter) */ #define DEFAULT_THRESHOLD 0.4 /* in units/ms */ +#define MINIMUM_THRESHOLD 0.2 /* in units/ms */ #define DEFAULT_ACCELERATION 2.0 /* unitless factor */ #define DEFAULT_INCLINE 1.1 /* unitless factor */ @@ -333,9 +334,9 @@ accelerator_set_speed(struct motion_filter *filter, assert(speed >= -1.0 && speed <= 1.0); /* delay when accel kicks in */ - accel_filter->threshold = DEFAULT_THRESHOLD - speed / 4000.0; - if (accel_filter->threshold < 0.0002) - accel_filter->threshold = 0.0002; + accel_filter->threshold = DEFAULT_THRESHOLD - speed / 4.0; + if (accel_filter->threshold < MINIMUM_THRESHOLD) + accel_filter->threshold = MINIMUM_THRESHOLD; /* adjust max accel factor */ accel_filter->accel = DEFAULT_ACCELERATION + speed * 1.5; From 2ee2bebb3423d2beb93607ea3f96fe726d95374c Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 5 Aug 2015 09:45:45 +1000 Subject: [PATCH 03/43] test: don't try to print axis values that aren't set Signed-off-by: Peter Hutterer --- test/litest.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/test/litest.c b/test/litest.c index 51085f19..3a16cd7c 100644 --- a/test/litest.c +++ b/test/litest.c @@ -1834,12 +1834,17 @@ litest_print_event(struct libinput_event *event) break; case LIBINPUT_EVENT_POINTER_AXIS: p = libinput_event_get_pointer_event(event); - fprintf(stderr, - "vert %.f horiz %.2f", - libinput_event_pointer_get_axis_value(p, - LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL), - libinput_event_pointer_get_axis_value(p, - LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)); + x = 0.0; + y = 0.0; + if (libinput_event_pointer_has_axis(p, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) + y = libinput_event_pointer_get_axis_value(p, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); + if (libinput_event_pointer_has_axis(p, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) + x = libinput_event_pointer_get_axis_value(p, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); + fprintf(stderr, "vert %.f horiz %.2f", y, x); break; default: break; From 74236f1047cd0829ad6c96944045e67df3f1fcdb Mon Sep 17 00:00:00 2001 From: Jackie Huang Date: Wed, 5 Aug 2015 11:28:43 +0800 Subject: [PATCH 04/43] configure.ac: add arg --with-libunwind Add arg --with-libunwind for configure so it's optional to check libunwind, which is helpfull to make deterministic builds. Signed-off-by: Jackie Huang Signed-off-by: Peter Hutterer --- configure.ac | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index 0d5d486c..885cb394 100644 --- a/configure.ac +++ b/configure.ac @@ -60,13 +60,22 @@ PKG_PROG_PKG_CONFIG() PKG_CHECK_MODULES(MTDEV, [mtdev >= 1.1.0]) PKG_CHECK_MODULES(LIBUDEV, [libudev]) PKG_CHECK_MODULES(LIBEVDEV, [libevdev >= 0.4]) -PKG_CHECK_MODULES(LIBUNWIND, + +AC_ARG_WITH(libunwind, + AS_HELP_STRING([--without-libunwind],[Do not use libunwind])) + +AS_IF([test "x$with_libunwind" != "xno"], + [PKG_CHECK_MODULES(LIBUNWIND, [libunwind], [HAVE_LIBUNWIND=yes], - [HAVE_LIBUNWIND=no]) -if test "x$HAVE_LIBUNWIND" = "xyes"; then - AC_DEFINE(HAVE_LIBUNWIND, 1, [Have libunwind support]) -fi + [HAVE_LIBUNWIND=no])], + [HAVE_LIBUNWIND=no]) + +AS_IF([test "x$HAVE_LIBUNWIND" = "xyes"], + [AC_DEFINE(HAVE_LIBUNWIND, 1, [Have libunwind support])], + [AS_IF([test "x$with_libunwind" = "xyes"], + [AC_MSG_ERROR([libunwind requested but not found])])]) + AM_CONDITIONAL(HAVE_LIBUNWIND, [test "x$HAVE_LIBUNWIND" = xyes]) AC_PATH_PROG(ADDR2LINE, [addr2line]) if test "x$ADDR2LINE" != "x"; then From 05ce472a0535cd76a9e4aa82b0a8d127a73cd9e9 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 5 Aug 2015 07:37:03 +1000 Subject: [PATCH 05/43] udev: use prop_value() to fetch the ID_INPUT_PROP property This will thus work if the property is only set on a parent device, not on the device directly. https://github.com/systemd/systemd/issues/763 Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- udev/libinput-model-quirks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/udev/libinput-model-quirks.c b/udev/libinput-model-quirks.c index 0e737a4b..67115fae 100644 --- a/udev/libinput-model-quirks.c +++ b/udev/libinput-model-quirks.c @@ -127,7 +127,7 @@ int main(int argc, char **argv) if (!device) goto out; - if (udev_device_get_property_value(device, "ID_INPUT_TOUCHPAD")) + if (prop_value(device, "ID_INPUT_TOUCHPAD")) handle_touchpad(device); rc = 0; From 3dd0ece9c0f4167a98f5f9c96caaa9650da74de9 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 5 Aug 2015 10:55:39 +1000 Subject: [PATCH 06/43] evdev: split scroll threshold and direction lock threshold into two The previous code used a 5mm threshold before axis events were posted. This threshold was on top of the 2mm 2fg threshold (and timeout handling) in the gesture code and effectively prevented events from being sent after a timeout, or in the 2mm-5mm range. We still want a directional lock though, so split the two out. The default 5mm threshold is set to 0 for touchpads since we have our own handling of the threshold there. The directional lock only applies once scrollin has started and remains on 5mm. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad.c | 5 +++-- src/evdev.c | 5 +++-- src/evdev.h | 1 + 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index a683d9a4..872da989 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1628,8 +1628,9 @@ tp_init_scroll(struct tp_dispatch *tp, struct evdev_device *device) tp->scroll.method = tp_scroll_get_default_method(tp); tp->device->base.config.scroll_method = &tp->scroll.config_method; - /* In mm for touchpads with valid resolution, see tp_init_accel() */ - tp->device->scroll.threshold = 5.0; + /* In mm for touchpads with valid resolution, see tp_init_accel() */ + tp->device->scroll.threshold = 0.0; + tp->device->scroll.direction_lock_threshold = 5.0; return 0; } diff --git a/src/evdev.c b/src/evdev.c index 17c26043..53ebf9dc 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -2146,6 +2146,7 @@ evdev_device_create(struct libinput_seat *seat, device->pending_event = EVDEV_NONE; device->devname = libevdev_get_name(device->evdev); device->scroll.threshold = 5.0; /* Default may be overridden */ + device->scroll.direction_lock_threshold = 5.0; /* Default may be overridden */ device->scroll.direction = 0; device->scroll.wheel_click_angle = evdev_read_wheel_click_prop(device); @@ -2414,12 +2415,12 @@ evdev_post_scroll(struct evdev_device *device, trigger speed to start scrolling in the other direction */ } else if (!evdev_is_scrolling(device, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) { - if (fabs(delta->y) >= device->scroll.threshold) + if (fabs(delta->y) >= device->scroll.direction_lock_threshold) evdev_start_scrolling(device, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); } else if (!evdev_is_scrolling(device, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) { - if (fabs(delta->x) >= device->scroll.threshold) + if (fabs(delta->x) >= device->scroll.direction_lock_threshold) evdev_start_scrolling(device, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); } diff --git a/src/evdev.h b/src/evdev.h index be5df0d0..65c5a41a 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -166,6 +166,7 @@ struct evdev_device { void (*change_scroll_method)(struct evdev_device *device); bool button_scroll_active; double threshold; + double direction_lock_threshold; uint32_t direction; struct normalized_coords buildup; From cbff01daf1c128b6fce395210737d667d0d8f631 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 4 Aug 2015 15:45:53 +1000 Subject: [PATCH 07/43] Revert "filter: move the pointer acceleration profiles back to units/ms" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 8a6825f1602aa9d9c4b29a83d296f55f68b316e0. Aside from introducing bugs, this doesn't really help with anything, it adds a requirement to rename everything to make clear where we're using µs and where we're using ms and that just clutters up the code. Signed-off-by: Peter Hutterer Acked-by: Jonas Ådahl --- src/filter.c | 54 +++++++++++++++++++++--------------------- tools/ptraccel-debug.c | 4 ++-- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/filter.c b/src/filter.c index e11d58a9..b01b68ab 100644 --- a/src/filter.c +++ b/src/filter.c @@ -77,8 +77,8 @@ filter_get_speed(struct motion_filter *filter) * Default parameters for pointer acceleration profiles. */ -#define DEFAULT_THRESHOLD 0.4 /* in units/ms */ -#define MINIMUM_THRESHOLD 0.2 /* in units/ms */ +#define DEFAULT_THRESHOLD 0.0004 /* in units/us */ +#define MINIMUM_THRESHOLD 0.0002 /* in units/us */ #define DEFAULT_ACCELERATION 2.0 /* unitless factor */ #define DEFAULT_INCLINE 1.1 /* unitless factor */ @@ -86,7 +86,7 @@ filter_get_speed(struct motion_filter *filter) * Pointer acceleration filter constants */ -#define MAX_VELOCITY_DIFF 1 /* units/ms */ +#define MAX_VELOCITY_DIFF 0.001 /* units/us */ #define MOTION_TIMEOUT ms2us(1000) #define NUM_POINTER_TRACKERS 16 @@ -102,14 +102,14 @@ struct pointer_accelerator { accel_profile_func_t profile; - double velocity; /* units/ms */ - double last_velocity; /* units/ms */ + double velocity; /* units/us */ + double last_velocity; /* units/us */ struct normalized_coords last; struct pointer_tracker *trackers; int cur_tracker; - double threshold; /* units/ms */ + double threshold; /* units/us */ double accel; /* unitless factor */ double incline; /* incline of the function */ @@ -151,7 +151,7 @@ static double calculate_tracker_velocity(struct pointer_tracker *tracker, uint64_t time) { double tdelta = time - tracker->time + 1; - return normalized_length(tracker->delta) / tdelta * 1000.0; /* units/ms */ + return normalized_length(tracker->delta) / tdelta; /* units/us */ } static inline double @@ -221,7 +221,7 @@ calculate_velocity(struct pointer_accelerator *accel, uint64_t time) } } - return result; /* units/ms */ + return result; /* units/us */ } static double @@ -257,11 +257,11 @@ calculate_acceleration(struct pointer_accelerator *accel, static struct normalized_coords accelerator_filter(struct motion_filter *filter, const struct normalized_coords *unaccelerated, - void *data, uint64_t time /* in us */) + void *data, uint64_t time) { struct pointer_accelerator *accel = (struct pointer_accelerator *) filter; - double velocity; /* units/ms */ + double velocity; /* units/us */ double accel_value; /* unitless factor */ struct normalized_coords accelerated; struct normalized_coords unnormalized; @@ -334,7 +334,7 @@ accelerator_set_speed(struct motion_filter *filter, assert(speed >= -1.0 && speed <= 1.0); /* delay when accel kicks in */ - accel_filter->threshold = DEFAULT_THRESHOLD - speed / 4.0; + accel_filter->threshold = DEFAULT_THRESHOLD - speed / 4000.0; if (accel_filter->threshold < MINIMUM_THRESHOLD) accel_filter->threshold = MINIMUM_THRESHOLD; @@ -398,23 +398,23 @@ create_pointer_accelerator_filter(accel_profile_func_t profile, double pointer_accel_profile_linear_low_dpi(struct motion_filter *filter, void *data, - double speed_in, /* in device units (units/ms) */ - uint64_t time /* in us */) + double speed_in, /* in device units (units/us) */ + uint64_t time) { struct pointer_accelerator *accel_filter = (struct pointer_accelerator *)filter; double s1, s2; double max_accel = accel_filter->accel; /* unitless factor */ - const double threshold = accel_filter->threshold; /* units/ms */ + const double threshold = accel_filter->threshold; /* units/us */ const double incline = accel_filter->incline; double factor; double dpi_factor = accel_filter->dpi_factor; max_accel /= dpi_factor; - s1 = min(1, 0.3 + speed_in * 10.0); - s2 = 1 + (speed_in - threshold * dpi_factor) * incline; + s1 = min(1, 0.3 + speed_in * 10000.0); + s2 = 1 + (speed_in * 1000.0 - threshold * dpi_factor * 1000.0) * incline; factor = min(max_accel, s2 > 1 ? s2 : s1); @@ -425,19 +425,19 @@ double pointer_accel_profile_linear(struct motion_filter *filter, void *data, double speed_in, /* 1000-dpi normalized */ - uint64_t time /* in us */) + uint64_t time) { struct pointer_accelerator *accel_filter = (struct pointer_accelerator *)filter; double s1, s2; const double max_accel = accel_filter->accel; /* unitless factor */ - const double threshold = accel_filter->threshold; /* units/ms */ + const double threshold = accel_filter->threshold; /* units/us */ const double incline = accel_filter->incline; double factor; - s1 = min(1, 0.3 + speed_in * 10); - s2 = 1 + (speed_in - threshold) * incline; + s1 = min(1, 0.3 + speed_in * 10 * 1000.0); + s2 = 1 + (speed_in * 1000.0 - threshold * 1000.0) * incline; factor = min(max_accel, s2 > 1 ? s2 : s1); @@ -446,9 +446,9 @@ pointer_accel_profile_linear(struct motion_filter *filter, double touchpad_accel_profile_linear(struct motion_filter *filter, - void *data, - double speed_in, - uint64_t time /* in us */) + void *data, + double speed_in, + uint64_t time) { /* Once normalized, touchpads see the same acceleration as mice. that is technically correct but @@ -469,7 +469,7 @@ double touchpad_lenovo_x230_accel_profile(struct motion_filter *filter, void *data, double speed_in, - uint64_t time /* in us */) + uint64_t time) { /* Keep the magic factor from touchpad_accel_profile_linear. */ const double TP_MAGIC_SLOWDOWN = 0.4; @@ -489,13 +489,13 @@ touchpad_lenovo_x230_accel_profile(struct motion_filter *filter, const double max_accel = accel_filter->accel * TP_MAGIC_LOW_RES_FACTOR; /* unitless factor */ const double threshold = accel_filter->threshold / - TP_MAGIC_LOW_RES_FACTOR; /* units/ms */ + TP_MAGIC_LOW_RES_FACTOR; /* units/us */ const double incline = accel_filter->incline * TP_MAGIC_LOW_RES_FACTOR; speed_in *= TP_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR; - s1 = min(1, speed_in * 5); - s2 = 1 + (speed_in - threshold) * incline; + s1 = min(1, speed_in * 5 * 1000.0); + s2 = 1 + (speed_in * 1000.0 - threshold * 1000.0) * incline; speed_out = min(max_accel, s2 > 1 ? s2 : s1); diff --git a/tools/ptraccel-debug.c b/tools/ptraccel-debug.c index 1496763b..b0867db3 100644 --- a/tools/ptraccel-debug.c +++ b/tools/ptraccel-debug.c @@ -147,12 +147,12 @@ print_accel_func(struct motion_filter *filter) printf("# set ylabel \"raw accel factor\"\n"); printf("# set style data lines\n"); printf("# plot \"gnuplot.data\" using 1:2\n"); - for (vel = 0.0; vel < 3.0; vel += .0001) { + for (vel = 0.0; vel < 0.003; vel += 0.0000001) { double result = pointer_accel_profile_linear(filter, NULL, vel, 0 /* time */); - printf("%.4f\t%.4f\n", vel, result); + printf("%.8f\t%.4f\n", vel, result); } } From c0a1d22fead992a2fa7fe7b6f9bf35de118052e9 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 4 Aug 2015 15:47:39 +1000 Subject: [PATCH 08/43] filter: drop superfluous struct declaration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Peter Hutterer Reviewed-by: Jonas Ådahl --- src/filter.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/filter.c b/src/filter.c index b01b68ab..e615deb1 100644 --- a/src/filter.c +++ b/src/filter.c @@ -96,7 +96,6 @@ struct pointer_tracker { int dir; }; -struct pointer_accelerator; struct pointer_accelerator { struct motion_filter base; From b750c7d69fb45f755390e46c5e82637cdb34ff37 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 4 Aug 2015 15:48:40 +1000 Subject: [PATCH 09/43] filter: rename speed to speed_adjustment where it's in the [-1,1] range To avoid confusion with the other speed in units/time Signed-off-by: Peter Hutterer --- src/filter-private.h | 4 ++-- src/filter.c | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/filter-private.h b/src/filter-private.h index 0e7afa1f..f5e8b7f7 100644 --- a/src/filter-private.h +++ b/src/filter-private.h @@ -38,11 +38,11 @@ struct motion_filter_interface { uint64_t time); void (*destroy)(struct motion_filter *filter); bool (*set_speed)(struct motion_filter *filter, - double speed); + double speed_adjustment); }; struct motion_filter { - double speed; /* normalized [-1, 1] */ + double speed_adjustment; /* normalized [-1, 1] */ struct motion_filter_interface *interface; }; diff --git a/src/filter.c b/src/filter.c index e615deb1..400c52a8 100644 --- a/src/filter.c +++ b/src/filter.c @@ -62,15 +62,15 @@ filter_destroy(struct motion_filter *filter) bool filter_set_speed(struct motion_filter *filter, - double speed) + double speed_adjustment) { - return filter->interface->set_speed(filter, speed); + return filter->interface->set_speed(filter, speed_adjustment); } double filter_get_speed(struct motion_filter *filter) { - return filter->speed; + return filter->speed_adjustment; } /* @@ -325,25 +325,25 @@ accelerator_destroy(struct motion_filter *filter) static bool accelerator_set_speed(struct motion_filter *filter, - double speed) + double speed_adjustment) { struct pointer_accelerator *accel_filter = (struct pointer_accelerator *)filter; - assert(speed >= -1.0 && speed <= 1.0); + assert(speed_adjustment >= -1.0 && speed_adjustment <= 1.0); /* delay when accel kicks in */ - accel_filter->threshold = DEFAULT_THRESHOLD - speed / 4000.0; + accel_filter->threshold = DEFAULT_THRESHOLD - speed_adjustment / 4000.0; if (accel_filter->threshold < MINIMUM_THRESHOLD) accel_filter->threshold = MINIMUM_THRESHOLD; /* adjust max accel factor */ - accel_filter->accel = DEFAULT_ACCELERATION + speed * 1.5; + accel_filter->accel = DEFAULT_ACCELERATION + speed_adjustment * 1.5; /* higher speed -> faster to reach max */ - accel_filter->incline = DEFAULT_INCLINE + speed * 0.75; + accel_filter->incline = DEFAULT_INCLINE + speed_adjustment * 0.75; - filter->speed = speed; + filter->speed_adjustment = speed_adjustment; return true; } From 7db8884ff5e5d41d06cd374c218ef18223587b24 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 4 Aug 2015 16:01:20 +1000 Subject: [PATCH 10/43] filter: rename speed_out to "factor" for the touchpad profiles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The return value of a profile is a unitless factor, not a speed. Same applies for s1/s2, these are factors, not speeds. Signed-off-by: Peter Hutterer Reviewed-by: Jonas Ådahl --- src/filter.c | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/filter.c b/src/filter.c index 400c52a8..9aaf1f42 100644 --- a/src/filter.c +++ b/src/filter.c @@ -403,19 +403,19 @@ pointer_accel_profile_linear_low_dpi(struct motion_filter *filter, struct pointer_accelerator *accel_filter = (struct pointer_accelerator *)filter; - double s1, s2; + double f1, f2; /* unitless */ double max_accel = accel_filter->accel; /* unitless factor */ const double threshold = accel_filter->threshold; /* units/us */ const double incline = accel_filter->incline; - double factor; + double factor; /* unitless */ double dpi_factor = accel_filter->dpi_factor; max_accel /= dpi_factor; - s1 = min(1, 0.3 + speed_in * 10000.0); - s2 = 1 + (speed_in * 1000.0 - threshold * dpi_factor * 1000.0) * incline; + f1 = min(1, 0.3 + speed_in * 10000.0); + f2 = 1 + (speed_in * 1000.0 - threshold * dpi_factor * 1000.0) * incline; - factor = min(max_accel, s2 > 1 ? s2 : s1); + factor = min(max_accel, f2 > 1 ? f2 : f1); return factor; } @@ -429,16 +429,16 @@ pointer_accel_profile_linear(struct motion_filter *filter, struct pointer_accelerator *accel_filter = (struct pointer_accelerator *)filter; - double s1, s2; + double f1, f2; /* unitless */ const double max_accel = accel_filter->accel; /* unitless factor */ const double threshold = accel_filter->threshold; /* units/us */ const double incline = accel_filter->incline; - double factor; + double factor; /* unitless */ - s1 = min(1, 0.3 + speed_in * 10 * 1000.0); - s2 = 1 + (speed_in * 1000.0 - threshold * 1000.0) * incline; + f1 = min(1, 0.3 + speed_in * 10 * 1000.0); + f2 = 1 + (speed_in * 1000.0 - threshold * 1000.0) * incline; - factor = min(max_accel, s2 > 1 ? s2 : s1); + factor = min(max_accel, f2 > 1 ? f2 : f1); return factor; } @@ -446,7 +446,7 @@ pointer_accel_profile_linear(struct motion_filter *filter, double touchpad_accel_profile_linear(struct motion_filter *filter, void *data, - double speed_in, + double speed_in, /* units/us */ uint64_t time) { /* Once normalized, touchpads see the same @@ -454,14 +454,14 @@ touchpad_accel_profile_linear(struct motion_filter *filter, subjectively wrong, we expect a touchpad to be a lot slower than a mouse. Apply a magic factor here and proceed as normal. */ - const double TP_MAGIC_SLOWDOWN = 0.4; - double speed_out; + const double TP_MAGIC_SLOWDOWN = 0.4; /* unitless */ + double factor; /* unitless */ speed_in *= TP_MAGIC_SLOWDOWN; - speed_out = pointer_accel_profile_linear(filter, data, speed_in, time); + factor = pointer_accel_profile_linear(filter, data, speed_in, time); - return speed_out * TP_MAGIC_SLOWDOWN; + return factor * TP_MAGIC_SLOWDOWN; } double @@ -471,7 +471,7 @@ touchpad_lenovo_x230_accel_profile(struct motion_filter *filter, uint64_t time) { /* Keep the magic factor from touchpad_accel_profile_linear. */ - const double TP_MAGIC_SLOWDOWN = 0.4; + const double TP_MAGIC_SLOWDOWN = 0.4; /* unitless */ /* Those touchpads presents an actual lower resolution that what is * advertised. We see some jumps from the cursor due to the big steps @@ -479,12 +479,12 @@ touchpad_lenovo_x230_accel_profile(struct motion_filter *filter, * Apply a factor to minimize those jumps at low speed, and try * keeping the same feeling as regular touchpads at high speed. * It still feels slower but it is usable at least */ - const double TP_MAGIC_LOW_RES_FACTOR = 4.0; - double speed_out; + const double TP_MAGIC_LOW_RES_FACTOR = 4.0; /* unitless */ + double factor; /* unitless */ struct pointer_accelerator *accel_filter = (struct pointer_accelerator *)filter; - double s1, s2; + double f1, f2; /* unitless */ const double max_accel = accel_filter->accel * TP_MAGIC_LOW_RES_FACTOR; /* unitless factor */ const double threshold = accel_filter->threshold / @@ -493,10 +493,10 @@ touchpad_lenovo_x230_accel_profile(struct motion_filter *filter, speed_in *= TP_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR; - s1 = min(1, speed_in * 5 * 1000.0); - s2 = 1 + (speed_in * 1000.0 - threshold * 1000.0) * incline; + f1 = min(1, speed_in * 5 * 1000.0); + f2 = 1 + (speed_in * 1000.0 - threshold * 1000.0) * incline; - speed_out = min(max_accel, s2 > 1 ? s2 : s1); + factor = min(max_accel, f2 > 1 ? f2 : f1); - return speed_out * TP_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR; + return factor * TP_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR; } From 1cbcc641a06e49d676263093e088c5c25c47cb4d Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 4 Aug 2015 16:04:06 +1000 Subject: [PATCH 11/43] filter: add two helper functions to convert between speeds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes it more obvious where we're using units/us and units/ms as input variable and what the output is. Clutters up the code, but still better than dealing with us/ms differently per function, and still better than carrying all the 1000.0 multiplications/divisions manually. Signed-off-by: Peter Hutterer Reviewed-by: Jonas Ådahl --- src/filter.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/src/filter.c b/src/filter.c index 9aaf1f42..425bc795 100644 --- a/src/filter.c +++ b/src/filter.c @@ -36,6 +36,20 @@ #include "libinput-util.h" #include "filter-private.h" +/* Convert speed/velocity from units/us to units/ms */ +static inline double +v_us2ms(double units_per_us) +{ + return units_per_us * 1000.0; +} + +/* Convert speed/velocity from units/ms to units/us */ +static inline double +v_ms2us(double units_per_ms) +{ + return units_per_ms/1000.0; +} + struct normalized_coords filter_dispatch(struct motion_filter *filter, const struct normalized_coords *unaccelerated, @@ -77,8 +91,8 @@ filter_get_speed(struct motion_filter *filter) * Default parameters for pointer acceleration profiles. */ -#define DEFAULT_THRESHOLD 0.0004 /* in units/us */ -#define MINIMUM_THRESHOLD 0.0002 /* in units/us */ +#define DEFAULT_THRESHOLD v_ms2us(0.4) /* in units/us */ +#define MINIMUM_THRESHOLD v_ms2us(0.2) /* in units/us */ #define DEFAULT_ACCELERATION 2.0 /* unitless factor */ #define DEFAULT_INCLINE 1.1 /* unitless factor */ @@ -86,7 +100,7 @@ filter_get_speed(struct motion_filter *filter) * Pointer acceleration filter constants */ -#define MAX_VELOCITY_DIFF 0.001 /* units/us */ +#define MAX_VELOCITY_DIFF v_ms2us(1) /* units/us */ #define MOTION_TIMEOUT ms2us(1000) #define NUM_POINTER_TRACKERS 16 @@ -332,8 +346,12 @@ accelerator_set_speed(struct motion_filter *filter, assert(speed_adjustment >= -1.0 && speed_adjustment <= 1.0); + /* Note: the numbers below are nothing but trial-and-error magic, + don't read more into them other than "they mostly worked ok" */ + /* delay when accel kicks in */ - accel_filter->threshold = DEFAULT_THRESHOLD - speed_adjustment / 4000.0; + accel_filter->threshold = DEFAULT_THRESHOLD - + v_ms2us(0.25) * speed_adjustment; if (accel_filter->threshold < MINIMUM_THRESHOLD) accel_filter->threshold = MINIMUM_THRESHOLD; @@ -412,8 +430,8 @@ pointer_accel_profile_linear_low_dpi(struct motion_filter *filter, max_accel /= dpi_factor; - f1 = min(1, 0.3 + speed_in * 10000.0); - f2 = 1 + (speed_in * 1000.0 - threshold * dpi_factor * 1000.0) * incline; + f1 = min(1, 0.3 + v_us2ms(speed_in) * 10.0); + f2 = 1 + (v_us2ms(speed_in) - v_us2ms(threshold) * dpi_factor) * incline; factor = min(max_accel, f2 > 1 ? f2 : f1); @@ -435,8 +453,8 @@ pointer_accel_profile_linear(struct motion_filter *filter, const double incline = accel_filter->incline; double factor; /* unitless */ - f1 = min(1, 0.3 + speed_in * 10 * 1000.0); - f2 = 1 + (speed_in * 1000.0 - threshold * 1000.0) * incline; + f1 = min(1, 0.3 + v_us2ms(speed_in) * 10); + f2 = 1 + (v_us2ms(speed_in) - v_us2ms(threshold)) * incline; factor = min(max_accel, f2 > 1 ? f2 : f1); @@ -493,8 +511,8 @@ touchpad_lenovo_x230_accel_profile(struct motion_filter *filter, speed_in *= TP_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR; - f1 = min(1, speed_in * 5 * 1000.0); - f2 = 1 + (speed_in * 1000.0 - threshold * 1000.0) * incline; + f1 = min(1, v_us2ms(speed_in) * 5); + f2 = 1 + (v_us2ms(speed_in) - v_us2ms(threshold)) * incline; factor = min(max_accel, f2 > 1 ? f2 : f1); From 723dccfd939d151ad460e166c7a73a25ea7c0fc5 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 5 Aug 2015 13:39:33 +1000 Subject: [PATCH 12/43] filter: explain the acceleration function in detail MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit And switch to a code-flow that's a bit more self-explanatory than the current min/max combinations. Signed-off-by: Peter Hutterer Reviewed-by: Jonas Ådahl --- src/filter.c | 83 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 73 insertions(+), 10 deletions(-) diff --git a/src/filter.c b/src/filter.c index 425bc795..467eb225 100644 --- a/src/filter.c +++ b/src/filter.c @@ -421,19 +421,26 @@ pointer_accel_profile_linear_low_dpi(struct motion_filter *filter, struct pointer_accelerator *accel_filter = (struct pointer_accelerator *)filter; - double f1, f2; /* unitless */ double max_accel = accel_filter->accel; /* unitless factor */ - const double threshold = accel_filter->threshold; /* units/us */ + double threshold = accel_filter->threshold; /* units/us */ const double incline = accel_filter->incline; double factor; /* unitless */ double dpi_factor = accel_filter->dpi_factor; + /* dpi_factor is always < 1.0, increase max_accel, reduce + the threshold so it kicks in earlier */ max_accel /= dpi_factor; + threshold *= dpi_factor; - f1 = min(1, 0.3 + v_us2ms(speed_in) * 10.0); - f2 = 1 + (v_us2ms(speed_in) - v_us2ms(threshold) * dpi_factor) * incline; + /* see pointer_accel_profile_linear for a long description */ + if (v_us2ms(speed_in) < 0.07) + factor = 10 * v_us2ms(speed_in) + 0.3; + else if (speed_in < threshold) + factor = 1; + else + factor = incline * v_us2ms(speed_in - threshold) + 1; - factor = min(max_accel, f2 > 1 ? f2 : f1); + factor = min(max_accel, factor); return factor; } @@ -446,17 +453,67 @@ pointer_accel_profile_linear(struct motion_filter *filter, { struct pointer_accelerator *accel_filter = (struct pointer_accelerator *)filter; - - double f1, f2; /* unitless */ const double max_accel = accel_filter->accel; /* unitless factor */ const double threshold = accel_filter->threshold; /* units/us */ const double incline = accel_filter->incline; double factor; /* unitless */ - f1 = min(1, 0.3 + v_us2ms(speed_in) * 10); - f2 = 1 + (v_us2ms(speed_in) - v_us2ms(threshold)) * incline; + /* + Our acceleration function calculates a factor to accelerate input + deltas with. The function is a double incline with a plateau, + with a rough shape like this: - factor = min(max_accel, f2 > 1 ? f2 : f1); + accel + factor + ^ + | / + | _____/ + | / + |/ + +-------------> speed in + + The two inclines are linear functions in the form + y = ax + b + where y is speed_out + x is speed_in + a is the incline of acceleration + b is minimum acceleration factor + + for speeds up to 0.07 u/ms, we decelerate, down to 30% of input + speed. + hence 1 = a * 0.07 + 0.3 + 0.3 = a * 0.00 + 0.3 => a := 10 + deceleration function is thus: + y = 10x + 0.3 + + Note: + * 0.07u/ms as threshold is a result of trial-and-error and + has no other intrinsic meaning. + * 0.3 is chosen simply because it is above the Nyquist frequency + for subpixel motion within a pixel. + */ + if (v_us2ms(speed_in) < 0.07) { + factor = 10 * v_us2ms(speed_in) + 0.3; + /* up to the threshold, we keep factor 1, i.e. 1:1 movement */ + } else if (speed_in < threshold) { + factor = 1; + + } else { + /* Acceleration function above the threshold: + y = ax' + b + where T is threshold + x is speed_in + x' is speed + and + y(T) == 1 + hence 1 = ax' + 1 + => x' := (x - T) + */ + factor = incline * v_us2ms(speed_in - threshold) + 1; + } + + /* Cap at the maximum acceleration factor */ + factor = min(max_accel, factor); return factor; } @@ -509,6 +566,12 @@ touchpad_lenovo_x230_accel_profile(struct motion_filter *filter, TP_MAGIC_LOW_RES_FACTOR; /* units/us */ const double incline = accel_filter->incline * TP_MAGIC_LOW_RES_FACTOR; + /* Note: the magic values in this function are obtained by + * trial-and-error. No other meaning should be interpreted. + * The calculation is a compressed form of + * pointer_accel_profile_linear(), look at the git history of that + * function for an explaination of what the min/max/etc. does. + */ speed_in *= TP_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR; f1 = min(1, v_us2ms(speed_in) * 5); From 5ec449f7dce7df4ac685449bc152a2e92289cb53 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 28 Jul 2015 15:39:19 +1000 Subject: [PATCH 13/43] filter: drop accel->last, write-only value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Peter Hutterer Reviewed-by: Jonas Ådahl --- src/filter.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/filter.c b/src/filter.c index 467eb225..4c00dbb8 100644 --- a/src/filter.c +++ b/src/filter.c @@ -117,7 +117,6 @@ struct pointer_accelerator { double velocity; /* units/us */ double last_velocity; /* units/us */ - struct normalized_coords last; struct pointer_tracker *trackers; int cur_tracker; @@ -297,8 +296,6 @@ accelerator_filter(struct motion_filter *filter, accelerated.x = accel_value * unnormalized.x; accelerated.y = accel_value * unnormalized.y; - accel->last = unnormalized; - accel->last_velocity = velocity; return accelerated; @@ -386,8 +383,6 @@ create_pointer_accelerator_filter(accel_profile_func_t profile, filter->profile = profile; filter->last_velocity = 0.0; - filter->last.x = 0; - filter->last.y = 0; filter->trackers = calloc(NUM_POINTER_TRACKERS, sizeof *filter->trackers); From 4cdcf5cc381c6cfbe552b642e56e1c6a68263876 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 28 Jul 2015 14:45:51 +1000 Subject: [PATCH 14/43] filter: move create_pointer_accelerator_filter down in the file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No functional changes, just moving code in preparation for filter patches Signed-off-by: Peter Hutterer Reviewed-by: Jonas Ådahl --- src/filter.c | 70 ++++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/filter.c b/src/filter.c index 4c00dbb8..38d0d367 100644 --- a/src/filter.c +++ b/src/filter.c @@ -362,41 +362,6 @@ accelerator_set_speed(struct motion_filter *filter, return true; } -struct motion_filter_interface accelerator_interface = { - accelerator_filter, - accelerator_restart, - accelerator_destroy, - accelerator_set_speed, -}; - -struct motion_filter * -create_pointer_accelerator_filter(accel_profile_func_t profile, - int dpi) -{ - struct pointer_accelerator *filter; - - filter = zalloc(sizeof *filter); - if (filter == NULL) - return NULL; - - filter->base.interface = &accelerator_interface; - - filter->profile = profile; - filter->last_velocity = 0.0; - - filter->trackers = - calloc(NUM_POINTER_TRACKERS, sizeof *filter->trackers); - filter->cur_tracker = 0; - - filter->threshold = DEFAULT_THRESHOLD; - filter->accel = DEFAULT_ACCELERATION; - filter->incline = DEFAULT_INCLINE; - - filter->dpi_factor = dpi/(double)DEFAULT_MOUSE_DPI; - - return &filter->base; -} - /** * Custom acceleration function for mice < 1000dpi. * At slow motion, a single device unit causes a one-pixel movement. @@ -576,3 +541,38 @@ touchpad_lenovo_x230_accel_profile(struct motion_filter *filter, return factor * TP_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR; } + +struct motion_filter_interface accelerator_interface = { + accelerator_filter, + accelerator_restart, + accelerator_destroy, + accelerator_set_speed, +}; + +struct motion_filter * +create_pointer_accelerator_filter(accel_profile_func_t profile, + int dpi) +{ + struct pointer_accelerator *filter; + + filter = zalloc(sizeof *filter); + if (filter == NULL) + return NULL; + + filter->base.interface = &accelerator_interface; + + filter->profile = profile; + filter->last_velocity = 0.0; + + filter->trackers = + calloc(NUM_POINTER_TRACKERS, sizeof *filter->trackers); + filter->cur_tracker = 0; + + filter->threshold = DEFAULT_THRESHOLD; + filter->accel = DEFAULT_ACCELERATION; + filter->incline = DEFAULT_INCLINE; + + filter->dpi_factor = dpi/(double)DEFAULT_MOUSE_DPI; + + return &filter->base; +} From 4c48b46d15497fec9fa16cbf39f83bc3c090db6f Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 28 Jul 2015 15:06:13 +1000 Subject: [PATCH 15/43] filter: revamp to create device-specific filters, rather than accel functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous approach to pointer acceleration was to initialize the same motion filter behavior but a different acceleration profile depending on the hardware (the profile converts a speed to a multiplier for input deltas). To be more flexible for hardware-specifics, change this into a set of specific pointer acceleration init functions. This patch has no effective functional changes, they're still all the same. The acceleration functions are kept for direct access by the ptraccel-debug tool. Signed-off-by: Peter Hutterer Reviewed-by: Jonas Ådahl --- src/evdev-mt-touchpad.c | 10 +++---- src/evdev.c | 18 ++++++------ src/evdev.h | 2 +- src/filter.c | 62 ++++++++++++++++++++++++++++++++++++++--- src/filter.h | 14 ++++++++-- tools/ptraccel-debug.c | 3 +- 6 files changed, 86 insertions(+), 23 deletions(-) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index a683d9a4..f48aa26d 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1510,7 +1510,7 @@ static int tp_init_accel(struct tp_dispatch *tp, double diagonal) { int res_x, res_y; - accel_profile_func_t profile; + struct motion_filter *filter; res_x = tp->device->abs.absinfo_x->resolution; res_y = tp->device->abs.absinfo_y->resolution; @@ -1526,14 +1526,14 @@ tp_init_accel(struct tp_dispatch *tp, double diagonal) tp->accel.y_scale_coeff = (DEFAULT_MOUSE_DPI/25.4) / res_y; if (tp->device->model_flags & EVDEV_MODEL_LENOVO_X230) - profile = touchpad_lenovo_x230_accel_profile; + filter = create_pointer_accelerator_filter_lenovo_x230(tp->device->dpi); else - profile = touchpad_accel_profile_linear; + filter = create_pointer_accelerator_filter_touchpad(tp->device->dpi); - if (evdev_device_init_pointer_acceleration(tp->device, profile) == -1) + if (!filter) return -1; - return 0; + return evdev_device_init_pointer_acceleration(tp->device, filter); } static uint32_t diff --git a/src/evdev.c b/src/evdev.c index 17c26043..bb317248 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1408,12 +1408,9 @@ evdev_accel_config_get_default_speed(struct libinput_device *device) int evdev_device_init_pointer_acceleration(struct evdev_device *device, - accel_profile_func_t profile) + struct motion_filter *filter) { - device->pointer.filter = create_pointer_accelerator_filter(profile, - device->dpi); - if (!device->pointer.filter) - return -1; + device->pointer.filter = filter; device->pointer.config.available = evdev_accel_config_available; device->pointer.config.set_speed = evdev_accel_config_set_speed; @@ -1862,14 +1859,17 @@ evdev_configure_mt_device(struct evdev_device *device) static inline int evdev_init_accel(struct evdev_device *device) { - accel_profile_func_t profile; + struct motion_filter *filter; if (device->dpi < DEFAULT_MOUSE_DPI) - profile = pointer_accel_profile_linear_low_dpi; + filter = create_pointer_accelerator_filter_linear_low_dpi(device->dpi); else - profile = pointer_accel_profile_linear; + filter = create_pointer_accelerator_filter_linear(device->dpi); - return evdev_device_init_pointer_acceleration(device, profile); + if (!filter) + return -1; + + return evdev_device_init_pointer_acceleration(device, filter); } static int diff --git a/src/evdev.h b/src/evdev.h index be5df0d0..42404fc2 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -280,7 +280,7 @@ evdev_device_create(struct libinput_seat *seat, int evdev_device_init_pointer_acceleration(struct evdev_device *device, - accel_profile_func_t profile); + struct motion_filter *filter); struct evdev_dispatch * evdev_touchpad_create(struct evdev_device *device); diff --git a/src/filter.c b/src/filter.c index 38d0d367..b94647d2 100644 --- a/src/filter.c +++ b/src/filter.c @@ -549,9 +549,8 @@ struct motion_filter_interface accelerator_interface = { accelerator_set_speed, }; -struct motion_filter * -create_pointer_accelerator_filter(accel_profile_func_t profile, - int dpi) +static struct pointer_accelerator * +create_default_filter(int dpi) { struct pointer_accelerator *filter; @@ -561,7 +560,6 @@ create_pointer_accelerator_filter(accel_profile_func_t profile, filter->base.interface = &accelerator_interface; - filter->profile = profile; filter->last_velocity = 0.0; filter->trackers = @@ -574,5 +572,61 @@ create_pointer_accelerator_filter(accel_profile_func_t profile, filter->dpi_factor = dpi/(double)DEFAULT_MOUSE_DPI; + return filter; +} + +struct motion_filter * +create_pointer_accelerator_filter_linear(int dpi) +{ + struct pointer_accelerator *filter; + + filter = create_default_filter(dpi); + if (!filter) + return NULL; + + filter->profile = pointer_accel_profile_linear; + + return &filter->base; +} + +struct motion_filter * +create_pointer_accelerator_filter_linear_low_dpi(int dpi) +{ + struct pointer_accelerator *filter; + + filter = create_default_filter(dpi); + if (!filter) + return NULL; + + filter->profile = pointer_accel_profile_linear_low_dpi; + + return &filter->base; +} + +struct motion_filter * +create_pointer_accelerator_filter_touchpad(int dpi) +{ + struct pointer_accelerator *filter; + + filter = create_default_filter(dpi); + if (!filter) + return NULL; + + filter->profile = touchpad_accel_profile_linear; + + return &filter->base; +} + +struct motion_filter * +create_pointer_accelerator_filter_lenovo_x230(int dpi) +{ + struct pointer_accelerator *filter; + + filter = create_default_filter(dpi); + if (!filter) + return NULL; + + filter->profile = touchpad_lenovo_x230_accel_profile; + return &filter->base; } diff --git a/src/filter.h b/src/filter.h index 617fab1f..76fc1476 100644 --- a/src/filter.h +++ b/src/filter.h @@ -57,9 +57,19 @@ typedef double (*accel_profile_func_t)(struct motion_filter *filter, double velocity, uint64_t time); +/* Pointer acceleration types */ + struct motion_filter * -create_pointer_accelerator_filter(accel_profile_func_t filter, - int dpi); +create_pointer_accelerator_filter_linear(int dpi); + +struct motion_filter * +create_pointer_accelerator_filter_linear_low_dpi(int dpi); + +struct motion_filter * +create_pointer_accelerator_filter_touchpad(int dpi); + +struct motion_filter * +create_pointer_accelerator_filter_lenovo_x230(int dpi); /* * Pointer acceleration profiles. diff --git a/tools/ptraccel-debug.c b/tools/ptraccel-debug.c index b0867db3..077da59d 100644 --- a/tools/ptraccel-debug.c +++ b/tools/ptraccel-debug.c @@ -272,8 +272,7 @@ main(int argc, char **argv) } } - filter = create_pointer_accelerator_filter(pointer_accel_profile_linear, - dpi); + filter = create_pointer_accelerator_filter_linear(dpi); assert(filter != NULL); filter_set_speed(filter, speed); From f2663e2b255e71aac6045c7a6bd3f7679fb16078 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 28 Jul 2015 15:46:33 +1000 Subject: [PATCH 16/43] filter: split calculating the accel factor into a helper function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No functional changes. Signed-off-by: Peter Hutterer Reviewed-by: Jonas Ådahl --- src/filter.c | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/src/filter.c b/src/filter.c index b94647d2..f3e0fb32 100644 --- a/src/filter.c +++ b/src/filter.c @@ -266,6 +266,27 @@ calculate_acceleration(struct pointer_accelerator *accel, return factor; /* unitless factor */ } +static inline double +calculate_acceleration_factor(struct pointer_accelerator *accel, + const struct normalized_coords *unaccelerated, + void *data, + uint64_t time) +{ + double velocity; /* units/us */ + double accel_factor; + + feed_trackers(accel, unaccelerated, time); + velocity = calculate_velocity(accel, time); + accel_factor = calculate_acceleration(accel, + data, + velocity, + accel->last_velocity, + time); + accel->last_velocity = velocity; + + return accel_factor; +} + static struct normalized_coords accelerator_filter(struct motion_filter *filter, const struct normalized_coords *unaccelerated, @@ -273,7 +294,6 @@ accelerator_filter(struct motion_filter *filter, { struct pointer_accelerator *accel = (struct pointer_accelerator *) filter; - double velocity; /* units/us */ double accel_value; /* unitless factor */ struct normalized_coords accelerated; struct normalized_coords unnormalized; @@ -285,19 +305,14 @@ accelerator_filter(struct motion_filter *filter, unnormalized.x = unaccelerated->x * dpi_factor; unnormalized.y = unaccelerated->y * dpi_factor; - feed_trackers(accel, &unnormalized, time); - velocity = calculate_velocity(accel, time); - accel_value = calculate_acceleration(accel, - data, - velocity, - accel->last_velocity, - time); + accel_value = calculate_acceleration_factor(accel, + &unnormalized, + data, + time); accelerated.x = accel_value * unnormalized.x; accelerated.y = accel_value * unnormalized.y; - accel->last_velocity = velocity; - return accelerated; } From ef3f234345a459cda1dd24ce43d6034038e8e4a3 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 28 Jul 2015 15:49:22 +1000 Subject: [PATCH 17/43] filter: split out handling of the low-dpi accel method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Peter Hutterer Reviewed-by: Jonas Ådahl --- src/filter.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/filter.c b/src/filter.c index f3e0fb32..369d7370 100644 --- a/src/filter.c +++ b/src/filter.c @@ -296,6 +296,27 @@ accelerator_filter(struct motion_filter *filter, (struct pointer_accelerator *) filter; double accel_value; /* unitless factor */ struct normalized_coords accelerated; + + accel_value = calculate_acceleration_factor(accel, + unaccelerated, + data, + time); + + accelerated.x = accel_value * unaccelerated->x; + accelerated.y = accel_value * unaccelerated->y; + + return accelerated; +} + +static struct normalized_coords +accelerator_filter_low_dpi(struct motion_filter *filter, + const struct normalized_coords *unaccelerated, + void *data, uint64_t time) +{ + struct pointer_accelerator *accel = + (struct pointer_accelerator *) filter; + double accel_value; /* unitless factor */ + struct normalized_coords accelerated; struct normalized_coords unnormalized; double dpi_factor = accel->dpi_factor; @@ -573,8 +594,6 @@ create_default_filter(int dpi) if (filter == NULL) return NULL; - filter->base.interface = &accelerator_interface; - filter->last_velocity = 0.0; filter->trackers = @@ -599,11 +618,19 @@ create_pointer_accelerator_filter_linear(int dpi) if (!filter) return NULL; + filter->base.interface = &accelerator_interface; filter->profile = pointer_accel_profile_linear; return &filter->base; } +struct motion_filter_interface accelerator_interface_low_dpi = { + accelerator_filter_low_dpi, + accelerator_restart, + accelerator_destroy, + accelerator_set_speed, +}; + struct motion_filter * create_pointer_accelerator_filter_linear_low_dpi(int dpi) { @@ -613,6 +640,7 @@ create_pointer_accelerator_filter_linear_low_dpi(int dpi) if (!filter) return NULL; + filter->base.interface = &accelerator_interface_low_dpi; filter->profile = pointer_accel_profile_linear_low_dpi; return &filter->base; @@ -627,6 +655,7 @@ create_pointer_accelerator_filter_touchpad(int dpi) if (!filter) return NULL; + filter->base.interface = &accelerator_interface; filter->profile = touchpad_accel_profile_linear; return &filter->base; @@ -641,6 +670,7 @@ create_pointer_accelerator_filter_lenovo_x230(int dpi) if (!filter) return NULL; + filter->base.interface = &accelerator_interface; filter->profile = touchpad_lenovo_x230_accel_profile; return &filter->base; From 0cd54c59879063240c88f10b721470d29dbe4659 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 11 Aug 2015 12:40:45 +1000 Subject: [PATCH 18/43] touchpad: enable natural scrolling for edge scrolling Instead of going straight to pointer_notify_axis, go through evdev_notify_axis() which flips the scroll direction around for us. https://bugs.freedesktop.org/show_bug.cgi?id=91597 Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad-edge-scroll.c | 20 +++++++++---------- src/evdev.c | 2 +- src/evdev.h | 7 +++++++ test/touchpad.c | 30 +++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 11 deletions(-) diff --git a/src/evdev-mt-touchpad-edge-scroll.c b/src/evdev-mt-touchpad-edge-scroll.c index 49028087..eda62e4d 100644 --- a/src/evdev-mt-touchpad-edge-scroll.c +++ b/src/evdev-mt-touchpad-edge-scroll.c @@ -342,7 +342,7 @@ tp_edge_scroll_handle_state(struct tp_dispatch *tp, uint64_t time) int tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time) { - struct libinput_device *device = &tp->device->base; + struct evdev_device *device = tp->device; struct tp_touch *t; enum libinput_pointer_axis axis; double *delta; @@ -369,7 +369,7 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time) case EDGE_NONE: if (t->scroll.direction != -1) { /* Send stop scroll event */ - pointer_notify_axis(device, time, + evdev_notify_axis(device, time, AS_MASK(t->scroll.direction), LIBINPUT_POINTER_AXIS_SOURCE_FINGER, &zero, @@ -395,7 +395,7 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time) switch (t->scroll.edge_state) { case EDGE_SCROLL_TOUCH_STATE_NONE: case EDGE_SCROLL_TOUCH_STATE_AREA: - log_bug_libinput(device->seat->libinput, + log_bug_libinput(tp_libinput_context(tp), "unexpected scroll state %d\n", t->scroll.edge_state); break; @@ -416,11 +416,11 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time) if (*delta == 0.0) continue; - pointer_notify_axis(device, time, - AS_MASK(axis), - LIBINPUT_POINTER_AXIS_SOURCE_FINGER, - &normalized, - &zero_discrete); + evdev_notify_axis(device, time, + AS_MASK(axis), + LIBINPUT_POINTER_AXIS_SOURCE_FINGER, + &normalized, + &zero_discrete); t->scroll.direction = axis; tp_edge_scroll_handle_event(tp, t, SCROLL_EVENT_POSTED); @@ -432,14 +432,14 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time) void tp_edge_scroll_stop_events(struct tp_dispatch *tp, uint64_t time) { - struct libinput_device *device = &tp->device->base; + struct evdev_device *device = tp->device; struct tp_touch *t; const struct normalized_coords zero = { 0.0, 0.0 }; const struct discrete_coords zero_discrete = { 0.0, 0.0 }; tp_for_each_touch(tp, t) { if (t->scroll.direction != -1) { - pointer_notify_axis(device, time, + evdev_notify_axis(device, time, AS_MASK(t->scroll.direction), LIBINPUT_POINTER_AXIS_SOURCE_FINGER, &zero, diff --git a/src/evdev.c b/src/evdev.c index 53ebf9dc..225c3acc 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -612,7 +612,7 @@ evdev_process_absolute_motion(struct evdev_device *device, } } -static void +void evdev_notify_axis(struct evdev_device *device, uint64_t time, uint32_t axes, diff --git a/src/evdev.h b/src/evdev.h index 65c5a41a..c951671e 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -380,6 +380,13 @@ evdev_pointer_notify_physical_button(struct evdev_device *device, void evdev_init_natural_scroll(struct evdev_device *device); +void +evdev_notify_axis(struct evdev_device *device, + uint64_t time, + uint32_t axes, + enum libinput_pointer_axis_source source, + const struct normalized_coords *delta_in, + const struct discrete_coords *discrete_in); void evdev_post_scroll(struct evdev_device *device, uint64_t time, diff --git a/test/touchpad.c b/test/touchpad.c index 6e7ea5ff..bbdbc21d 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -350,6 +350,35 @@ START_TEST(touchpad_scroll_natural_2fg) } END_TEST +START_TEST(touchpad_scroll_natural_edge) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + + litest_enable_edge_scroll(dev); + litest_drain_events(li); + + libinput_device_config_scroll_set_natural_scroll_enabled(dev->libinput_device, 1); + + litest_touch_down(dev, 0, 99, 20); + litest_touch_move_to(dev, 0, 99, 20, 99, 80, 10, 0); + litest_touch_up(dev, 0); + + libinput_dispatch(li); + litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, -4); + litest_assert_empty_queue(li); + + litest_touch_down(dev, 0, 99, 80); + litest_touch_move_to(dev, 0, 99, 80, 99, 20, 10, 0); + litest_touch_up(dev, 0); + + libinput_dispatch(li); + litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 4); + litest_assert_empty_queue(li); + +} +END_TEST + START_TEST(touchpad_edge_scroll) { struct litest_device *dev = litest_current_device(); @@ -3450,6 +3479,7 @@ litest_setup_tests(void) 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_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add("touchpad:scroll", touchpad_scroll_natural_edge, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); litest_add("touchpad:scroll", touchpad_scroll_defaults, LITEST_TOUCHPAD, LITEST_ANY); litest_add("touchpad:scroll", touchpad_edge_scroll, LITEST_TOUCHPAD, LITEST_ANY); litest_add("touchpad:scroll", touchpad_edge_scroll_no_motion, LITEST_TOUCHPAD, LITEST_ANY); From e1be2f54cad745b4c6d8764f3352c1be50729985 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 28 Jul 2015 15:53:23 +1000 Subject: [PATCH 19/43] filter: duplicate the code for the Lenovo x230 accel method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is "once-tested, don't touch it again" code. The quirks on the touchpad means we'd have to find that specific device again and re-test everything if we change anything elsewhere in the code. So duplicate it properly, so that we don't have to touch it again. Signed-off-by: Peter Hutterer Reviewed-by: Jonas Ådahl --- src/filter.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/src/filter.c b/src/filter.c index 369d7370..0c3e1de2 100644 --- a/src/filter.c +++ b/src/filter.c @@ -96,6 +96,11 @@ filter_get_speed(struct motion_filter *filter) #define DEFAULT_ACCELERATION 2.0 /* unitless factor */ #define DEFAULT_INCLINE 1.1 /* unitless factor */ +/* for the Lenovo x230 custom accel. do not touch */ +#define X230_THRESHOLD v_ms2us(0.4) /* in units/us */ +#define X230_ACCELERATION 2.0 /* unitless factor */ +#define X230_INCLINE 1.1 /* unitless factor */ + /* * Pointer acceleration filter constants */ @@ -337,6 +342,32 @@ accelerator_filter_low_dpi(struct motion_filter *filter, return accelerated; } +static struct normalized_coords +accelerator_filter_x230(struct motion_filter *filter, + const struct normalized_coords *unaccelerated, + void *data, uint64_t time) +{ + struct pointer_accelerator *accel = + (struct pointer_accelerator *) filter; + double accel_factor; /* unitless factor */ + struct normalized_coords accelerated; + double velocity; /* units/us */ + + feed_trackers(accel, unaccelerated, time); + velocity = calculate_velocity(accel, time); + accel_factor = calculate_acceleration(accel, + data, + velocity, + accel->last_velocity, + time); + accel->last_velocity = velocity; + + accelerated.x = accel_factor * unaccelerated->x; + accelerated.y = accel_factor * unaccelerated->y; + + return accelerated; +} + static void accelerator_restart(struct motion_filter *filter, void *data, @@ -661,17 +692,39 @@ create_pointer_accelerator_filter_touchpad(int dpi) return &filter->base; } +struct motion_filter_interface accelerator_interface_x230 = { + accelerator_filter_x230, + accelerator_restart, + accelerator_destroy, + accelerator_set_speed, +}; + +/* The Lenovo x230 has a bad touchpad. This accel method has been + * trial-and-error'd, any changes to it will require re-testing everything. + * Don't touch this. + */ struct motion_filter * create_pointer_accelerator_filter_lenovo_x230(int dpi) { struct pointer_accelerator *filter; - filter = create_default_filter(dpi); - if (!filter) + filter = zalloc(sizeof *filter); + if (filter == NULL) return NULL; - filter->base.interface = &accelerator_interface; + filter->base.interface = &accelerator_interface_x230; filter->profile = touchpad_lenovo_x230_accel_profile; + filter->last_velocity = 0.0; + + filter->trackers = + calloc(NUM_POINTER_TRACKERS, sizeof *filter->trackers); + filter->cur_tracker = 0; + + filter->threshold = X230_THRESHOLD; + filter->accel = X230_ACCELERATION; /* unitless factor */ + filter->incline = X230_INCLINE; /* incline of the acceleration function */ + + filter->dpi_factor = 1; /* unused for this accel method */ return &filter->base; } From 4c1c572b19dec80b5d08125272f2f635ada2bd57 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 28 Jul 2015 16:02:05 +1000 Subject: [PATCH 20/43] filter: split trackpoint acceleration out MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is step one to fixing trackpoint acceleration, separating it from the other acceleration code. No functional changes yet, it still uses the low-dpi accel method. https://bugs.freedesktop.org/show_bug.cgi?id=91369 Signed-off-by: Peter Hutterer Reviewed-by: Jonas Ådahl --- src/evdev.c | 4 ++- src/filter.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/filter.h | 8 +++++ 3 files changed, 98 insertions(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index bb317248..22d51dcb 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1861,7 +1861,9 @@ evdev_init_accel(struct evdev_device *device) { struct motion_filter *filter; - if (device->dpi < DEFAULT_MOUSE_DPI) + if (device->tags & EVDEV_TAG_TRACKPOINT) + filter = create_pointer_accelerator_filter_trackpoint(device->dpi); + else if (device->dpi < DEFAULT_MOUSE_DPI) filter = create_pointer_accelerator_filter_linear_low_dpi(device->dpi); else filter = create_pointer_accelerator_filter_linear(device->dpi); diff --git a/src/filter.c b/src/filter.c index 0c3e1de2..7054fafa 100644 --- a/src/filter.c +++ b/src/filter.c @@ -342,6 +342,36 @@ accelerator_filter_low_dpi(struct motion_filter *filter, return accelerated; } +static struct normalized_coords +accelerator_filter_trackpoint(struct motion_filter *filter, + const struct normalized_coords *unaccelerated, + void *data, uint64_t time) +{ + struct pointer_accelerator *accel = + (struct pointer_accelerator *) filter; + double accel_value; /* unitless factor */ + struct normalized_coords accelerated; + struct normalized_coords unnormalized; + double dpi_factor = accel->dpi_factor; + + /* trackpoints with a dpi factor have a const accel set, remove that + * and restore device units. The accel profile takes const accel + * into account */ + dpi_factor = min(1.0, dpi_factor); + unnormalized.x = unaccelerated->x * dpi_factor; + unnormalized.y = unaccelerated->y * dpi_factor; + + accel_value = calculate_acceleration_factor(accel, + &unnormalized, + data, + time); + + accelerated.x = accel_value * unnormalized.x; + accelerated.y = accel_value * unnormalized.y; + + return accelerated; +} + static struct normalized_coords accelerator_filter_x230(struct motion_filter *filter, const struct normalized_coords *unaccelerated, @@ -609,6 +639,38 @@ touchpad_lenovo_x230_accel_profile(struct motion_filter *filter, return factor * TP_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR; } +double +trackpoint_accel_profile(struct motion_filter *filter, + void *data, + double speed_in, /* 1000-dpi normalized */ + uint64_t time) +{ + struct pointer_accelerator *accel_filter = + (struct pointer_accelerator *)filter; + double max_accel = accel_filter->accel; /* unitless factor */ + double threshold = accel_filter->threshold; /* units/ms */ + const double incline = accel_filter->incline; + double factor; + double dpi_factor = accel_filter->dpi_factor; + + /* dpi_factor is always < 1.0, increase max_accel, reduce + the threshold so it kicks in earlier */ + max_accel /= dpi_factor; + threshold *= dpi_factor; + + /* see pointer_accel_profile_linear for a long description */ + if (v_us2ms(speed_in) < 0.07) + factor = 10 * v_us2ms(speed_in) + 0.3; + else if (speed_in < threshold) + factor = 1; + else + factor = incline * v_us2ms(speed_in - threshold) + 1; + + factor = min(max_accel, factor); + + return factor; +} + struct motion_filter_interface accelerator_interface = { accelerator_filter, accelerator_restart, @@ -728,3 +790,28 @@ create_pointer_accelerator_filter_lenovo_x230(int dpi) return &filter->base; } + +struct motion_filter_interface accelerator_interface_trackpoint = { + accelerator_filter_trackpoint, + accelerator_restart, + accelerator_destroy, + accelerator_set_speed, +}; + +struct motion_filter * +create_pointer_accelerator_filter_trackpoint(int dpi) +{ + struct pointer_accelerator *filter; + + filter = create_default_filter(dpi); + if (!filter) + return NULL; + + filter->base.interface = &accelerator_interface_trackpoint; + filter->profile = trackpoint_accel_profile; + filter->threshold = DEFAULT_THRESHOLD; + filter->accel = DEFAULT_ACCELERATION; + filter->incline = DEFAULT_INCLINE; + + return &filter->base; +} diff --git a/src/filter.h b/src/filter.h index 76fc1476..fd36da49 100644 --- a/src/filter.h +++ b/src/filter.h @@ -71,6 +71,9 @@ create_pointer_accelerator_filter_touchpad(int dpi); struct motion_filter * create_pointer_accelerator_filter_lenovo_x230(int dpi); +struct motion_filter * +create_pointer_accelerator_filter_trackpoint(int dpi); + /* * Pointer acceleration profiles. */ @@ -95,4 +98,9 @@ touchpad_lenovo_x230_accel_profile(struct motion_filter *filter, void *data, double speed_in, uint64_t time); +double +trackpoint_accel_profile(struct motion_filter *filter, + void *data, + double speed_in, + uint64_t time); #endif /* FILTER_H */ From e1849b3e58a3ddcb1b8e288e4d9dc2ab89fac9cf Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 31 Jul 2015 12:29:23 +1000 Subject: [PATCH 21/43] tools: allow filter-switching in ptraccel-debug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Peter Hutterer Reviewed-by: Jonas Ådahl --- tools/ptraccel-debug.c | 43 +++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/tools/ptraccel-debug.c b/tools/ptraccel-debug.c index 077da59d..aa887fec 100644 --- a/tools/ptraccel-debug.c +++ b/tools/ptraccel-debug.c @@ -138,7 +138,7 @@ print_ptraccel_sequence(struct motion_filter *filter, } static void -print_accel_func(struct motion_filter *filter) +print_accel_func(struct motion_filter *filter, accel_profile_func_t profile) { double vel; @@ -148,10 +148,7 @@ print_accel_func(struct motion_filter *filter) printf("# set style data lines\n"); printf("# plot \"gnuplot.data\" using 1:2\n"); for (vel = 0.0; vel < 0.003; vel += 0.0000001) { - double result = pointer_accel_profile_linear(filter, - NULL, - vel, - 0 /* time */); + double result = profile(filter, NULL, vel, 0 /* time */); printf("%.8f\t%.4f\n", vel, result); } } @@ -171,6 +168,12 @@ usage(void) "--steps= ... in motion and delta modes only. Increase dx by step each round\n" "--speed= ... accel speed [-1, 1], default 0\n" "--dpi= ... device resolution in DPI (default: 1000)\n" + "--filter= \n" + " linear ... the default motion filter\n" + " low-dpi ... low-dpi filter, use --dpi with this argument\n" + " touchpad ... the touchpad motion filter\n" + " x230 ... custom filter for the Lenovo x230 touchpad\n" + " trackpoint... trackpoint motion filter\n" "\n" "If extra arguments are present and mode is not given, mode defaults to 'sequence'\n" "and the arguments are interpreted as sequence of delta x coordinates\n" @@ -195,6 +198,8 @@ main(int argc, char **argv) double custom_deltas[1024]; double speed = 0.0; int dpi = 1000; + const char *filter_type = "linear"; + accel_profile_func_t profile = NULL; enum { OPT_MODE = 1, @@ -203,6 +208,7 @@ main(int argc, char **argv) OPT_STEP, OPT_SPEED, OPT_DPI, + OPT_FILTER, }; while (1) { @@ -215,6 +221,7 @@ main(int argc, char **argv) {"step", 1, 0, OPT_STEP }, {"speed", 1, 0, OPT_SPEED }, {"dpi", 1, 0, OPT_DPI }, + {"filter", 1, 0, OPT_FILTER}, {0, 0, 0, 0} }; @@ -265,6 +272,9 @@ main(int argc, char **argv) case OPT_DPI: dpi = strtod(optarg, NULL); break; + case OPT_FILTER: + filter_type = optarg; + break; default: usage(); exit(1); @@ -272,7 +282,26 @@ main(int argc, char **argv) } } - filter = create_pointer_accelerator_filter_linear(dpi); + if (streq(filter_type, "linear")) { + filter = create_pointer_accelerator_filter_linear(dpi); + profile = pointer_accel_profile_linear; + } else if (streq(filter_type, "low-dpi")) { + filter = create_pointer_accelerator_filter_linear_low_dpi(dpi); + profile = pointer_accel_profile_linear_low_dpi; + } else if (streq(filter_type, "touchpad")) { + filter = create_pointer_accelerator_filter_touchpad(dpi); + profile = touchpad_accel_profile_linear; + } else if (streq(filter_type, "x230")) { + filter = create_pointer_accelerator_filter_lenovo_x230(dpi); + profile = touchpad_lenovo_x230_accel_profile; + } else if (streq(filter_type, "trackpoint")) { + filter = create_pointer_accelerator_filter_trackpoint(dpi); + profile = trackpoint_accel_profile; + } else { + fprintf(stderr, "Invalid filter type %s\n", filter_type); + return 1; + } + assert(filter != NULL); filter_set_speed(filter, speed); @@ -296,7 +325,7 @@ main(int argc, char **argv) } if (print_accel) - print_accel_func(filter); + print_accel_func(filter, profile); else if (print_delta) print_ptraccel_deltas(filter, step); else if (print_motion) From 9424fb6f99d9032a73130e6f380eb11be1988025 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 29 Jul 2015 15:05:52 +1000 Subject: [PATCH 22/43] doc: add pointer acceleration documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Peter Hutterer Reviewed-by: Jonas Ådahl --- doc/Makefile.am | 5 + doc/page-hierarchy.dox | 1 + doc/pointer-acceleration.dox | 110 + doc/svg/ptraccel-linear.svg | 5486 +++++++++++++++++++++++++++++++ doc/svg/ptraccel-low-dpi.svg | 3748 +++++++++++++++++++++ doc/svg/ptraccel-touchpad.svg | 1723 ++++++++++ doc/svg/ptraccel-trackpoint.svg | 3689 +++++++++++++++++++++ 7 files changed, 14762 insertions(+) create mode 100644 doc/pointer-acceleration.dox create mode 100644 doc/svg/ptraccel-linear.svg create mode 100644 doc/svg/ptraccel-low-dpi.svg create mode 100644 doc/svg/ptraccel-touchpad.svg create mode 100644 doc/svg/ptraccel-trackpoint.svg diff --git a/doc/Makefile.am b/doc/Makefile.am index c9dccfda..a8d41822 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -18,6 +18,7 @@ header_files = \ $(srcdir)/normalization-of-relative-motion.dox \ $(srcdir)/palm-detection.dox \ $(srcdir)/page-hierarchy.dox \ + $(srcdir)/pointer-acceleration.dox \ $(srcdir)/reporting-bugs.dox \ $(srcdir)/scrolling.dox \ $(srcdir)/seats.dox \ @@ -39,6 +40,10 @@ diagram_files = \ $(srcdir)/svg/edge-scrolling.svg \ $(srcdir)/svg/palm-detection.svg \ $(srcdir)/svg/pinch-gestures.svg \ + $(srcdir)/svg/ptraccel-linear.svg \ + $(srcdir)/svg/ptraccel-low-dpi.svg \ + $(srcdir)/svg/ptraccel-touchpad.svg \ + $(srcdir)/svg/ptraccel-trackpoint.svg \ $(srcdir)/svg/swipe-gestures.svg \ $(srcdir)/svg/tap-n-drag.svg \ $(srcdir)/svg/thumb-detection.svg \ diff --git a/doc/page-hierarchy.dox b/doc/page-hierarchy.dox index 1e82535f..3fdb1f72 100644 --- a/doc/page-hierarchy.dox +++ b/doc/page-hierarchy.dox @@ -31,5 +31,6 @@ - @subpage test-suite - @subpage tools +- @subpage pointer-acceleration */ diff --git a/doc/pointer-acceleration.dox b/doc/pointer-acceleration.dox new file mode 100644 index 00000000..a372e154 --- /dev/null +++ b/doc/pointer-acceleration.dox @@ -0,0 +1,110 @@ +/** +@page pointer-acceleration Pointer acceleration + +libinput uses device-specific pointer acceleration methods, with the default +being the @ref ptraccel-linear. The methods share common properties, such as +@ref ptraccel-velocity. + +This page explains the high-level concepts used in the code. It aims to +provide an overview for developers and is not necessarily useful for +users. + +@section ptraccel-velocity Velocity calculation + +The device's speed of movement is measured across multiple input events +through so-called "trackers". Each event prepends a the tracker item, each +subsequent tracker contains the delta of that item to the current position, +the timestamp of the event that created it and the cardinal direction of the +movement at the time. If a device moves into the same direction, the +velocity is calculated across multiple trackers. For example, if a device +moves steadily for 10 events to the left, the velocity is calculated across +all 10 events. + +Whenever the movement changes direction or significantly changes speed, the +velocity is calculated from the direction/speed change only. For example, if +a device moves steadily for 8 events to the left and then 2 events to the +right, the velocity is only that of the last 2 events. + +An extra time limit prevents events that are too old to factor into the +velocity calculation. For example, if a device moves steadily for 5 events +to the left, then pauses, then moves again for 5 events to the left, only +the last 5 events are used for velocity calculation. + +The velocity is then used to calculate the acceleration factor + +@section ptraccel-factor Acceleration factor + +The acceleration factor is the final outcome of the pointer acceleration +calculations. It is a unitless factor that is applied to the current delta, +a factor of 2 doubles the delta (i.e. speeds up the movement), a factor of +less than 1 reduces the delta (i.e. slows the movement). + +Any factor less than 1 requires the user to move the device further to move +the visible pointer. This is called deceleration and enables high precision +target selection through subpixel movements. libinput's current maximum +deceleration factor is 0.3 (i.e. slow down to 30% of the pointer speed). + +A factor higher than 1 moves the pointer further than the physical device +moves. This is acceleration and allows a user to cross the screen quickly +but effectively skips pixels. libinput's current maximum acceleration factor +is 3.5. + +@section ptraccel-linear Linear pointer acceleration + +The linear pointer acceleration method is the default for most pointer +devices. It provides deceleration at very slow movements, a 1:1 mapping for +regular movements and a linear increase to the maximum acceleration factor +for fast movements. + +Linear pointer acceleration applies to devices with above 1000dpi resolution +and after @ref motion_normalization is applied. + +@image html ptraccel-linear.svg "Linear pointer acceleration" + +The image above shows the linear pointer acceleration settings at various +speeds. The line for 0.0 is the default acceleration curve, speed settings +above 0.0 accelerate sooner, faster and to a higher maximum acceleration. +Speed settings below 0 delay when acceleration kicks in, how soon the +maximum acceleration is reached and the maximum acceleration factor. + +Extremely low speed settings provide no acceleration and additionally +decelerate all movement by a constant factor. + +@section ptraccel-low-dpi Pointer acceleration for low-dpi devices + +Low-dpi devices are those with a physical resolution of less than 1000 dots +per inch (dpi). The pointer acceleration is adjusted to provide roughly the +same feel for all devices at normal to high speeds. At slow speeds, the +pointer acceleration works on device-units rather than normalized +coordinates (see @ref motion_normalization). + +@image html ptraccel-low-dpi.svg "Pointer acceleration for low-dpi devices" + +The image above shows the default pointer acceleration curve for a speed of +0.0 at different DPI settings. A device with low DPI has the acceleration +applied sooner and with a stronger acceleration factor. + +@section ptraccel-touchpad Pointer acceleration on touchpads + +Touchpad pointer acceleration uses the @ref ptraccel-linear profile, with a +constant deceleration factor applied. The user expectation of how much a +pointer should move in response to finger movement is different to that of a +mouse device, hence the constant deceleration factor. + +@image html ptraccel-touchpad.svg "Pointer acceleration curve for touchpads" + +The image above shows the touchpad acceleration profile in comparison to the +@ref ptraccel-linear. The shape of the curve is identical but vertically squashed. + +@section ptraccel-trackpoint Pointer acceleration on trackpoints + +Trackpoint pointer acceleration uses the @ref ptraccel-low-dpi profile, with a +constant deceleration factor taking the place of the DPI settings. + +@image html ptraccel-trackpoint.svg "Pointer acceleration curves for trackpoints" + +The image above shows the trackpoint acceleration profile in comparison to the +@ref ptraccel-linear. The constant acceleration factor, usually applied by +udev, shapes the acceleration profile. + +*/ diff --git a/doc/svg/ptraccel-linear.svg b/doc/svg/ptraccel-linear.svg new file mode 100644 index 00000000..cb575f21 --- /dev/null +++ b/doc/svg/ptraccel-linear.svg @@ -0,0 +1,5486 @@ + + + + +Gnuplot +Produced by GNUPLOT 5.0 patchlevel 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + 0.5 + + + + + 1 + + + + + 1.5 + + + + + 2 + + + + + 2.5 + + + + + 3 + + + + + 0 + + + + + 0.0005 + + + + + 0.001 + + + + + 0.0015 + + + + + 0.002 + + + + + 0.0025 + + + + + 0.003 + + + + + + + + + accel factor + + + + + speed in units/us + + + + + -1.0 + + + -1.0 + + + + + + -0.75 + + + -0.75 + + + + + + -0.5 + + + -0.5 + + + + + + -0.25 + + + -0.25 + + + + + + 0.0 + + + 0.0 + + + + + + 0.5 + + + 0.5 + + + + + + 1.0 + + + 1.0 + + + + + + + + + + + + + + + + + + diff --git a/doc/svg/ptraccel-low-dpi.svg b/doc/svg/ptraccel-low-dpi.svg new file mode 100644 index 00000000..e31eaa1a --- /dev/null +++ b/doc/svg/ptraccel-low-dpi.svg @@ -0,0 +1,3748 @@ + + + + +Gnuplot +Produced by GNUPLOT 5.0 patchlevel 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + 1 + + + + + 2 + + + + + 3 + + + + + 4 + + + + + 5 + + + + + 0 + + + + + 0.0005 + + + + + 0.001 + + + + + 0.0015 + + + + + 0.002 + + + + + 0.0025 + + + + + 0.003 + + + + + + + + + accel factor + + + + + speed in units/us + + + + + 200dpi + + + 200dpi + + + + + + 400dpi + + + 400dpi + + + + + + 800dpi + + + 800dpi + + + + + + 1000dpi + + + 1000dpi + + + + + + + + + + + + + + + + + + diff --git a/doc/svg/ptraccel-touchpad.svg b/doc/svg/ptraccel-touchpad.svg new file mode 100644 index 00000000..1befa1e5 --- /dev/null +++ b/doc/svg/ptraccel-touchpad.svg @@ -0,0 +1,1723 @@ + + + + +Gnuplot +Produced by GNUPLOT 5.0 patchlevel 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + 0.5 + + + + + 1 + + + + + 1.5 + + + + + 2 + + + + + 2.5 + + + + + 3 + + + + + 0 + + + + + 0.0005 + + + + + 0.001 + + + + + 0.0015 + + + + + 0.002 + + + + + 0.0025 + + + + + 0.003 + + + + + + + + + accel factor + + + + + speed in units/us + + + + + linear (mouse) + + + linear (mouse) + + + + + + touchpad + + + touchpad + + + + + + + + + + + + + + + + + + diff --git a/doc/svg/ptraccel-trackpoint.svg b/doc/svg/ptraccel-trackpoint.svg new file mode 100644 index 00000000..79589c24 --- /dev/null +++ b/doc/svg/ptraccel-trackpoint.svg @@ -0,0 +1,3689 @@ + + + + +Gnuplot +Produced by GNUPLOT 5.0 patchlevel 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + 1 + + + + + 2 + + + + + 3 + + + + + 4 + + + + + 5 + + + + + 0 + + + + + 0.0005 + + + + + 0.001 + + + + + 0.0015 + + + + + 0.002 + + + + + 0.0025 + + + + + 0.003 + + + + + + + + + accel factor + + + + + speed in units/us + + + + + linear (mouse) + + + linear (mouse) + + + + + + const accel 1 + + + const accel 1 + + + + + + const accel 2 + + + const accel 2 + + + + + + const accel 3 + + + const accel 3 + + + + + + + + + + + + + + + + + + From cd63a06153cbb6ec95fb221b99a463a1f7a8a1d6 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 5 Aug 2015 14:47:59 +1000 Subject: [PATCH 23/43] tools: add shell script for making the pointer acceleration graphs in the docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Peter Hutterer Reviewed-by: Jonas Ådahl --- tools/Makefile.am | 2 + tools/make-ptraccel-graphs.sh | 79 +++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100755 tools/make-ptraccel-graphs.sh diff --git a/tools/Makefile.am b/tools/Makefile.am index 68e60cbb..8f72db99 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -39,3 +39,5 @@ event_gui_LDADD = ../src/libinput.la libshared.la $(CAIRO_LIBS) $(GTK_LIBS) $(LI event_gui_CFLAGS = $(CAIRO_CFLAGS) $(GTK_CFLAGS) $(LIBUDEV_CFLAGS) event_gui_LDFLAGS = -no-install endif + +EXTRA_DIST = make-ptraccel-graphs.sh diff --git a/tools/make-ptraccel-graphs.sh b/tools/make-ptraccel-graphs.sh new file mode 100755 index 00000000..901baf9c --- /dev/null +++ b/tools/make-ptraccel-graphs.sh @@ -0,0 +1,79 @@ +#!/bin/bash + +tool=`dirname $0`/ptraccel-debug +gnuplot=/usr/bin/gnuplot + +outfile="ptraccel-linear" +for speed in -1 -0.75 -0.5 -0.25 0 0.5 1; do + $tool --mode=accel --dpi=1000 --filter=linear --speed=$speed > $outfile-$speed.gnuplot +done +$gnuplot < $outfile-$dpi.gnuplot +done + +$gnuplot < $outfile-mouse.gnuplot +$tool --mode=accel --dpi=1000 --filter=touchpad > $outfile-touchpad.gnuplot +$gnuplot < $outfile-mouse.gnuplot +for constaccel in 1 2 3; do + dpi=$((1000/$constaccel)) + $tool --mode=accel --dpi=$dpi --filter=trackpoint > $outfile-trackpoint-$constaccel.gnuplot +done +$gnuplot < Date: Wed, 27 May 2015 13:02:52 +1000 Subject: [PATCH 24/43] test: add a comment Signed-off-by: Peter Hutterer --- test/litest-int.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/litest-int.h b/test/litest-int.h index ab611a56..ffa30a74 100644 --- a/test/litest-int.h +++ b/test/litest-int.h @@ -97,8 +97,8 @@ struct litest_device_interface { struct input_event *touch_move_events; struct input_event *touch_up_events; - int min[2]; - int max[2]; + int min[2]; /* x/y axis minimum */ + int max[2]; /* x/y axis maximum */ }; void litest_set_current_device(struct litest_device *device); From 5311d76ec19ce2cebf73cd4e49a58a4c08e216b5 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 17 Aug 2015 15:56:50 +1000 Subject: [PATCH 25/43] doc: fix typos Signed-off-by: Peter Hutterer --- doc/normalization-of-relative-motion.dox | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/normalization-of-relative-motion.dox b/doc/normalization-of-relative-motion.dox index 58ed151b..31596a93 100644 --- a/doc/normalization-of-relative-motion.dox +++ b/doc/normalization-of-relative-motion.dox @@ -25,16 +25,16 @@ movement speed increases, acceleration is applied - at high speeds a low-dpi device will roughly feel the same as a higher-dpi mouse. This normalization only applies to accelerated coordinates, unaccelerated -coordiantes are left in device-units. It is up to the caller to interpret +coordinates are left in device-units. It is up to the caller to interpret those coordinates correctly. @section Normalization of touchpad coordinates Touchpads may have a different resolution for the horizontal and vertical -axis. Interpreting coordinates from the touchpad without taking resolutino +axis. Interpreting coordinates from the touchpad without taking resolution into account results in uneven motion. -libinput scales unaccelerated touchpad motion do the resolution of the +libinput scales unaccelerated touchpad motion to the resolution of the touchpad's x axis, i.e. the unaccelerated value for the y axis is: y = (x / resolution_x) * resolution_y From 6953b51b7ebe079b94322447f795e308b6ac8447 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 18 Aug 2015 13:00:15 +1000 Subject: [PATCH 26/43] evdev: drop relative x/y motion from a device not marked as pointer A device with REL_X/Y and keys gets marked only as ID_INPUT_KEY, initializes as keyboard and then segfaults when we send x/y coordinates - pointer acceleration never initializes. Ignore the events and log a bug instead. This intentionally only papers over the underlying issue, let's wait for a real device to trigger this and then look at the correct solution. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev.c | 35 ++++++++++++ src/evdev.h | 1 + test/device.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++ test/litest.c | 2 + 4 files changed, 193 insertions(+) diff --git a/src/evdev.c b/src/evdev.c index 9414d9d6..97c007cd 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -638,6 +638,36 @@ evdev_notify_axis(struct evdev_device *device, &discrete); } +static inline bool +evdev_reject_relative(struct evdev_device *device, + const struct input_event *e, + uint64_t time) +{ + struct libinput *libinput = device->base.seat->libinput; + + if ((e->code == REL_X || e->code == REL_Y) && + (device->seat_caps & EVDEV_DEVICE_POINTER) == 0) { + switch (ratelimit_test(&device->nonpointer_rel_limit)) { + case RATELIMIT_PASS: + log_bug_libinput(libinput, + "REL_X/Y from device '%s', but this device is not a pointer\n", + device->devname); + break; + case RATELIMIT_THRESHOLD: + log_bug_libinput(libinput, + "REL_X/Y event flood from '%s'\n", + device->devname); + break; + case RATELIMIT_EXCEEDED: + break; + } + + return true; + } + + return false; +} + static inline void evdev_process_relative(struct evdev_device *device, struct input_event *e, uint64_t time) @@ -645,6 +675,9 @@ evdev_process_relative(struct evdev_device *device, struct normalized_coords wheel_degrees = { 0.0, 0.0 }; struct discrete_coords discrete = { 0.0, 0.0 }; + if (evdev_reject_relative(device, e, time)) + return; + switch (e->code) { case REL_X: if (device->pending_event != EVDEV_RELATIVE_MOTION) @@ -2157,6 +2190,8 @@ evdev_device_create(struct libinput_seat *seat, /* at most 5 SYN_DROPPED log-messages per 30s */ ratelimit_init(&device->syn_drop_limit, s2us(30), 5); + /* at most 5 log-messages per 5s */ + ratelimit_init(&device->nonpointer_rel_limit, s2us(5), 5); matrix_init_identity(&device->abs.calibration); matrix_init_identity(&device->abs.usermatrix); diff --git a/src/evdev.h b/src/evdev.h index 9f026b89..e44a65de 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -223,6 +223,7 @@ struct evdev_device { int dpi; /* HW resolution */ struct ratelimit syn_drop_limit; /* ratelimit for SYN_DROPPED logging */ + struct ratelimit nonpointer_rel_limit; /* ratelimit for REL_* events from non-pointer devices */ uint32_t model_flags; }; diff --git a/test/device.c b/test/device.c index 59939d67..aff5ee29 100644 --- a/test/device.c +++ b/test/device.c @@ -1030,6 +1030,156 @@ START_TEST(device_udev_tag_synaptics_serial) } END_TEST +START_TEST(device_nonpointer_rel) +{ + struct libevdev_uinput *uinput; + struct libinput *li; + struct libinput_device *device; + int i; + + uinput = litest_create_uinput_device("test device", + NULL, + EV_KEY, KEY_A, + EV_KEY, KEY_B, + EV_REL, REL_X, + EV_REL, REL_Y, + -1); + li = litest_create_context(); + device = libinput_path_add_device(li, + libevdev_uinput_get_devnode(uinput)); + ck_assert(device != NULL); + + litest_disable_log_handler(li); + for (i = 0; i < 100; i++) { + libevdev_uinput_write_event(uinput, EV_REL, REL_X, 1); + libevdev_uinput_write_event(uinput, EV_REL, REL_Y, -1); + libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0); + libinput_dispatch(li); + } + litest_restore_log_handler(li); + + libinput_unref(li); + libevdev_uinput_destroy(uinput); +} +END_TEST + +START_TEST(device_touchpad_rel) +{ + struct libevdev_uinput *uinput; + struct libinput *li; + struct libinput_device *device; + const struct input_absinfo abs[] = { + { ABS_X, 0, 10, 0, 0, 10 }, + { ABS_Y, 0, 10, 0, 0, 10 }, + { ABS_MT_SLOT, 0, 2, 0, 0, 0 }, + { ABS_MT_TRACKING_ID, 0, 255, 0, 0, 0 }, + { ABS_MT_POSITION_X, 0, 10, 0, 0, 10 }, + { ABS_MT_POSITION_Y, 0, 10, 0, 0, 10 }, + { -1, -1, -1, -1, -1, -1 } + }; + int i; + + uinput = litest_create_uinput_abs_device("test device", + NULL, abs, + EV_KEY, BTN_TOOL_FINGER, + EV_KEY, BTN_TOUCH, + EV_REL, REL_X, + EV_REL, REL_Y, + -1); + li = litest_create_context(); + device = libinput_path_add_device(li, + libevdev_uinput_get_devnode(uinput)); + ck_assert(device != NULL); + + for (i = 0; i < 100; i++) { + libevdev_uinput_write_event(uinput, EV_REL, REL_X, 1); + libevdev_uinput_write_event(uinput, EV_REL, REL_Y, -1); + libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0); + libinput_dispatch(li); + } + + libinput_unref(li); + libevdev_uinput_destroy(uinput); +} +END_TEST + +START_TEST(device_touch_rel) +{ + struct libevdev_uinput *uinput; + struct libinput *li; + struct libinput_device *device; + const struct input_absinfo abs[] = { + { ABS_X, 0, 10, 0, 0, 10 }, + { ABS_Y, 0, 10, 0, 0, 10 }, + { ABS_MT_SLOT, 0, 2, 0, 0, 0 }, + { ABS_MT_TRACKING_ID, 0, 255, 0, 0, 0 }, + { ABS_MT_POSITION_X, 0, 10, 0, 0, 10 }, + { ABS_MT_POSITION_Y, 0, 10, 0, 0, 10 }, + { -1, -1, -1, -1, -1, -1 } + }; + int i; + + uinput = litest_create_uinput_abs_device("test device", + NULL, abs, + EV_KEY, BTN_TOUCH, + EV_REL, REL_X, + EV_REL, REL_Y, + -1); + li = litest_create_context(); + device = libinput_path_add_device(li, + libevdev_uinput_get_devnode(uinput)); + ck_assert(device != NULL); + + litest_disable_log_handler(li); + for (i = 0; i < 100; i++) { + libevdev_uinput_write_event(uinput, EV_REL, REL_X, 1); + libevdev_uinput_write_event(uinput, EV_REL, REL_Y, -1); + libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0); + libinput_dispatch(li); + } + litest_restore_log_handler(li); + + libinput_unref(li); + libevdev_uinput_destroy(uinput); +} +END_TEST + +START_TEST(device_abs_rel) +{ + struct libevdev_uinput *uinput; + struct libinput *li; + struct libinput_device *device; + const struct input_absinfo abs[] = { + { ABS_X, 0, 10, 0, 0, 10 }, + { ABS_Y, 0, 10, 0, 0, 10 }, + { -1, -1, -1, -1, -1, -1 } + }; + int i; + + uinput = litest_create_uinput_abs_device("test device", + NULL, abs, + EV_KEY, BTN_TOUCH, + EV_KEY, BTN_LEFT, + EV_REL, REL_X, + EV_REL, REL_Y, + -1); + li = litest_create_context(); + device = libinput_path_add_device(li, + libevdev_uinput_get_devnode(uinput)); + ck_assert(device != NULL); + + for (i = 0; i < 100; i++) { + libevdev_uinput_write_event(uinput, EV_REL, REL_X, 1); + libevdev_uinput_write_event(uinput, EV_REL, REL_Y, -1); + libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0); + libinput_dispatch(li); + } + + libinput_unref(li); + libevdev_uinput_destroy(uinput); +} +END_TEST + void litest_setup_tests(void) { @@ -1077,4 +1227,9 @@ litest_setup_tests(void) litest_add("device:udev tags", device_udev_tag_wacom, LITEST_TOUCHPAD, LITEST_ANY); litest_add("device:udev tags", device_udev_tag_apple, LITEST_TOUCHPAD, LITEST_ANY); litest_add("device:udev tags", device_udev_tag_synaptics_serial, LITEST_TOUCHPAD, LITEST_ANY); + + litest_add_no_device("device:invalid rel events", device_nonpointer_rel); + litest_add_no_device("device:invalid rel events", device_touchpad_rel); + litest_add_no_device("device:invalid rel events", device_touch_rel); + litest_add_no_device("device:invalid rel events", device_abs_rel); } diff --git a/test/litest.c b/test/litest.c index 3a16cd7c..26c5e432 100644 --- a/test/litest.c +++ b/test/litest.c @@ -778,9 +778,11 @@ litest_log_handler(struct libinput *libinput, fprintf(stderr, "litest %s: ", priority); vfprintf(stderr, format, args); +#if 0 if (strstr(format, "client bug: ") || strstr(format, "libinput bug: ")) litest_abort_msg("libinput bug triggered, aborting.\n"); +#endif } static int From 42f482b43dfb6b16a1c05f561f3e12c07921c6e4 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 18 Aug 2015 15:46:41 +1000 Subject: [PATCH 27/43] tools: fix switch statement indentation Signed-off-by: Peter Hutterer --- tools/shared.c | 246 ++++++++++++++++++++++++------------------------- 1 file changed, 123 insertions(+), 123 deletions(-) diff --git a/tools/shared.c b/tools/shared.c index cea4c50c..9dba955e 100644 --- a/tools/shared.c +++ b/tools/shared.c @@ -166,131 +166,131 @@ tools_parse_args(int argc, char **argv, struct tools_context *context) break; switch(c) { - case 'h': - case OPT_HELP: - tools_usage(); - exit(0); - case OPT_DEVICE: - options->backend = BACKEND_DEVICE; - if (!optarg) { - tools_usage(); - return 1; - } - options->device = optarg; - break; - case OPT_UDEV: - options->backend = BACKEND_UDEV; - if (optarg) - options->seat = optarg; - break; - case OPT_GRAB: - options->grab = 1; - break; - case OPT_VERBOSE: - options->verbose = 1; - break; - case OPT_TAP_ENABLE: - options->tapping = 1; - break; - case OPT_TAP_DISABLE: - options->tapping = 0; - break; - case OPT_DRAG_LOCK_ENABLE: - options->drag_lock = 1; - break; - case OPT_DRAG_LOCK_DISABLE: - options->drag_lock = 0; - break; - case OPT_NATURAL_SCROLL_ENABLE: - options->natural_scroll = 1; - break; - case OPT_NATURAL_SCROLL_DISABLE: - options->natural_scroll = 0; - break; - case OPT_LEFT_HANDED_ENABLE: - options->left_handed = 1; - break; - case OPT_LEFT_HANDED_DISABLE: - options->left_handed = 0; - break; - case OPT_MIDDLEBUTTON_ENABLE: - options->middlebutton = 1; - break; - case OPT_MIDDLEBUTTON_DISABLE: - options->middlebutton = 0; - break; - case OPT_DWT_ENABLE: - options->dwt = LIBINPUT_CONFIG_DWT_ENABLED; - break; - case OPT_DWT_DISABLE: - options->dwt = LIBINPUT_CONFIG_DWT_DISABLED; - break; - case OPT_CLICK_METHOD: - if (!optarg) { - tools_usage(); - return 1; - } - if (streq(optarg, "none")) { - options->click_method = - LIBINPUT_CONFIG_CLICK_METHOD_NONE; - } else if (streq(optarg, "clickfinger")) { - options->click_method = - LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER; - } else if (streq(optarg, "buttonareas")) { - options->click_method = - LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; - } else { - tools_usage(); - return 1; - } - break; - case OPT_SCROLL_METHOD: - if (!optarg) { - tools_usage(); - return 1; - } - if (streq(optarg, "none")) { - options->scroll_method = - LIBINPUT_CONFIG_SCROLL_NO_SCROLL; - } else if (streq(optarg, "twofinger")) { - options->scroll_method = - LIBINPUT_CONFIG_SCROLL_2FG; - } else if (streq(optarg, "edge")) { - options->scroll_method = - LIBINPUT_CONFIG_SCROLL_EDGE; - } else if (streq(optarg, "button")) { - options->scroll_method = - LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN; - } else { - tools_usage(); - return 1; - } - break; - case OPT_SCROLL_BUTTON: - if (!optarg) { - tools_usage(); - return 1; - } - options->scroll_button = - libevdev_event_code_from_name(EV_KEY, - optarg); - if (options->scroll_button == -1) { - fprintf(stderr, - "Invalid button %s\n", - optarg); - return 1; - } - break; - case OPT_SPEED: - if (!optarg) { - tools_usage(); - return 1; - } - options->speed = atof(optarg); - break; - default: + case 'h': + case OPT_HELP: + tools_usage(); + exit(0); + case OPT_DEVICE: + options->backend = BACKEND_DEVICE; + if (!optarg) { tools_usage(); return 1; + } + options->device = optarg; + break; + case OPT_UDEV: + options->backend = BACKEND_UDEV; + if (optarg) + options->seat = optarg; + break; + case OPT_GRAB: + options->grab = 1; + break; + case OPT_VERBOSE: + options->verbose = 1; + break; + case OPT_TAP_ENABLE: + options->tapping = 1; + break; + case OPT_TAP_DISABLE: + options->tapping = 0; + break; + case OPT_DRAG_LOCK_ENABLE: + options->drag_lock = 1; + break; + case OPT_DRAG_LOCK_DISABLE: + options->drag_lock = 0; + break; + case OPT_NATURAL_SCROLL_ENABLE: + options->natural_scroll = 1; + break; + case OPT_NATURAL_SCROLL_DISABLE: + options->natural_scroll = 0; + break; + case OPT_LEFT_HANDED_ENABLE: + options->left_handed = 1; + break; + case OPT_LEFT_HANDED_DISABLE: + options->left_handed = 0; + break; + case OPT_MIDDLEBUTTON_ENABLE: + options->middlebutton = 1; + break; + case OPT_MIDDLEBUTTON_DISABLE: + options->middlebutton = 0; + break; + case OPT_DWT_ENABLE: + options->dwt = LIBINPUT_CONFIG_DWT_ENABLED; + break; + case OPT_DWT_DISABLE: + options->dwt = LIBINPUT_CONFIG_DWT_DISABLED; + break; + case OPT_CLICK_METHOD: + if (!optarg) { + tools_usage(); + return 1; + } + if (streq(optarg, "none")) { + options->click_method = + LIBINPUT_CONFIG_CLICK_METHOD_NONE; + } else if (streq(optarg, "clickfinger")) { + options->click_method = + LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER; + } else if (streq(optarg, "buttonareas")) { + options->click_method = + LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; + } else { + tools_usage(); + return 1; + } + break; + case OPT_SCROLL_METHOD: + if (!optarg) { + tools_usage(); + return 1; + } + if (streq(optarg, "none")) { + options->scroll_method = + LIBINPUT_CONFIG_SCROLL_NO_SCROLL; + } else if (streq(optarg, "twofinger")) { + options->scroll_method = + LIBINPUT_CONFIG_SCROLL_2FG; + } else if (streq(optarg, "edge")) { + options->scroll_method = + LIBINPUT_CONFIG_SCROLL_EDGE; + } else if (streq(optarg, "button")) { + options->scroll_method = + LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN; + } else { + tools_usage(); + return 1; + } + break; + case OPT_SCROLL_BUTTON: + if (!optarg) { + tools_usage(); + return 1; + } + options->scroll_button = + libevdev_event_code_from_name(EV_KEY, + optarg); + if (options->scroll_button == -1) { + fprintf(stderr, + "Invalid button %s\n", + optarg); + return 1; + } + break; + case OPT_SPEED: + if (!optarg) { + tools_usage(); + return 1; + } + options->speed = atof(optarg); + break; + default: + tools_usage(); + return 1; } } From 6d26728a1636b7dbc9af0daeb9f37ca725692429 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 19 Aug 2015 08:51:58 +1000 Subject: [PATCH 28/43] Change a fprintf to log_error Signed-off-by: Peter Hutterer --- src/libinput.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libinput.c b/src/libinput.c index 7d017e38..4673073d 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -1672,8 +1672,9 @@ libinput_post_event(struct libinput *libinput, events_len *= 2; events = realloc(events, events_len * sizeof *events); if (!events) { - fprintf(stderr, "Failed to reallocate event ring " - "buffer"); + log_error(libinput, + "Failed to reallocate event ring buffer. " + "Events may be discarded\n"); return; } From 2e7a585faa3f398d19a4761de50661adcb2019f0 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 19 Aug 2015 14:39:59 +1000 Subject: [PATCH 29/43] Drop obsolete unused declarations for log_info/set_logging_enabled Signed-off-by: Peter Hutterer --- src/libinput-util.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/libinput-util.h b/src/libinput-util.h index de9b98e1..ba253b57 100644 --- a/src/libinput-util.h +++ b/src/libinput-util.h @@ -45,12 +45,6 @@ #define CASE_RETURN_STRING(a) case a: return #a; -void -set_logging_enabled(int enabled); - -void -log_info(const char *format, ...); - /* * This list data structure is a verbatim copy from wayland-util.h from the * Wayland project; except that wl_ prefix has been removed. From b88fd375930544fd8b01c9b154ed4980c2b844eb Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 19 Aug 2015 15:21:53 +1000 Subject: [PATCH 30/43] Add log_*_ratelimit wrappers Don't open-code the rate-limited log messages, use a simple wrapper instead. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev.c | 37 ++++++++----------------------------- src/libinput-private.h | 14 ++++++++++++++ src/libinput.c | 25 +++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 29 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 97c007cd..303e4475 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -647,21 +647,10 @@ evdev_reject_relative(struct evdev_device *device, if ((e->code == REL_X || e->code == REL_Y) && (device->seat_caps & EVDEV_DEVICE_POINTER) == 0) { - switch (ratelimit_test(&device->nonpointer_rel_limit)) { - case RATELIMIT_PASS: - log_bug_libinput(libinput, - "REL_X/Y from device '%s', but this device is not a pointer\n", - device->devname); - break; - case RATELIMIT_THRESHOLD: - log_bug_libinput(libinput, - "REL_X/Y event flood from '%s'\n", - device->devname); - break; - case RATELIMIT_EXCEEDED: - break; - } - + log_bug_libinput_ratelimit(libinput, + &device->nonpointer_rel_limit, + "REL_X/Y from device '%s', but this device is not a pointer\n", + device->devname); return true; } @@ -1371,20 +1360,10 @@ evdev_device_dispatch(void *data) rc = libevdev_next_event(device->evdev, LIBEVDEV_READ_FLAG_NORMAL, &ev); if (rc == LIBEVDEV_READ_STATUS_SYNC) { - switch (ratelimit_test(&device->syn_drop_limit)) { - case RATELIMIT_PASS: - log_info(libinput, "SYN_DROPPED event from " - "\"%s\" - some input events have " - "been lost.\n", device->devname); - break; - case RATELIMIT_THRESHOLD: - log_info(libinput, "SYN_DROPPED flood " - "from \"%s\"\n", - device->devname); - break; - case RATELIMIT_EXCEEDED: - break; - } + log_info_ratelimit(libinput, + &device->syn_drop_limit, + "SYN_DROPPED event from \"%s\" - some input events have been lost.\n", + device->devname); /* send one more sync event so we handle all currently pending events before we sync up diff --git a/src/libinput-private.h b/src/libinput-private.h index 5d0826d0..8b161cc3 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -256,6 +256,20 @@ typedef void (*libinput_source_dispatch_t)(void *data); #define log_bug_libinput(li_, ...) log_msg((li_), LIBINPUT_LOG_PRIORITY_ERROR, "libinput bug: " __VA_ARGS__) #define log_bug_client(li_, ...) log_msg((li_), LIBINPUT_LOG_PRIORITY_ERROR, "client bug: " __VA_ARGS__) +#define log_debug_ratelimit(li_, r_, ...) log_msg_ratelimit((li_), (r_), LIBINPUT_LOG_PRIORITY_DEBUG, __VA_ARGS__) +#define log_info_ratelimit(li_, r_, ...) log_msg_ratelimit((li_), (r_), LIBINPUT_LOG_PRIORITY_INFO, __VA_ARGS__) +#define log_error_ratelimit(li_, r_, ...) log_msg_ratelimit((li_), (r_), LIBINPUT_LOG_PRIORITY_ERROR, __VA_ARGS__) +#define log_bug_kernel_ratelimit(li_, r_, ...) log_msg_ratelimit((li_), (r_), LIBINPUT_LOG_PRIORITY_ERROR, "kernel bug: " __VA_ARGS__) +#define log_bug_libinput_ratelimit(li_, r_, ...) log_msg_ratelimit((li_), (r_), LIBINPUT_LOG_PRIORITY_ERROR, "libinput bug: " __VA_ARGS__) +#define log_bug_client_ratelimit(li_, r_, ...) log_msg_ratelimit((li_), (r_), LIBINPUT_LOG_PRIORITY_ERROR, "client bug: " __VA_ARGS__) + +void +log_msg_ratelimit(struct libinput *libinput, + struct ratelimit *ratelimit, + enum libinput_log_priority priority, + const char *format, ...) + LIBINPUT_ATTRIBUTE_PRINTF(4, 5); + void log_msg(struct libinput *libinput, enum libinput_log_priority priority, diff --git a/src/libinput.c b/src/libinput.c index 4673073d..e5645714 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -166,6 +166,31 @@ log_msg(struct libinput *libinput, va_end(args); } +void +log_msg_ratelimit(struct libinput *libinput, + struct ratelimit *ratelimit, + enum libinput_log_priority priority, + const char *format, ...) +{ + va_list args; + enum ratelimit_state state; + + state = ratelimit_test(ratelimit); + if (state == RATELIMIT_EXCEEDED) + return; + + va_start(args, format); + log_msg_va(libinput, priority, format, args); + va_end(args); + + if (state == RATELIMIT_THRESHOLD) + log_msg(libinput, + priority, + "WARNING: log rate limit exceeded (%d msgs per %dms). Discarding future messages.\n", + ratelimit->burst, + us2ms(ratelimit->interval)); +} + LIBINPUT_EXPORT void libinput_log_set_priority(struct libinput *libinput, enum libinput_log_priority priority) From c7b11644c6a80442591b6663823b4879d48c12c6 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 17 Aug 2015 14:14:33 +1000 Subject: [PATCH 31/43] test: use the touchpad size for the 7mm movement Makes the code more straightforward, and we now require the devices to have a height/width anyway. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- test/touchpad.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/test/touchpad.c b/test/touchpad.c index bbdbc21d..ef262f97 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -150,20 +150,17 @@ START_TEST(touchpad_2fg_scroll_slow_distance) struct libinput *li = dev->libinput; struct libinput_event *event; struct libinput_event_pointer *ptrev; - const struct input_absinfo *y; - double y_move; + double width, height; + double y_move = 100; if (!litest_has_2fg_scroll(dev)) return; /* We want to move > 5 mm. */ - y = libevdev_get_abs_info(dev->evdev, ABS_Y); - if (y->resolution) { - y_move = 7.0 * y->resolution / - (y->maximum - y->minimum) * 100; - } else { - y_move = 20.0; - } + ck_assert_int_eq(libinput_device_get_size(dev->libinput_device, + &width, + &height), 0); + y_move = 100.0/height * 7; litest_enable_2fg_scroll(dev); litest_drain_events(li); From 168c61920c0c8b85d4ec138bc5760c90db9a2835 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 18 Aug 2015 08:47:28 +1000 Subject: [PATCH 32/43] test: fix edge scroll timeout test This test is supposed to test for the timeout kicking in on edge scrolling - if the finger is in the edge for longer than the timeout, we switch to scrolling without requiring the motion threshold to be met first. To emulate this, move the finger ever so slightly first to load up the motion history, then timeout, then move. We expect a bunch of motion events with a small delta. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- test/touchpad.c | 64 +++++++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/test/touchpad.c b/test/touchpad.c index ef262f97..8bff5a9f 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -463,54 +463,60 @@ START_TEST(touchpad_edge_scroll_timeout) struct libinput_event *event; struct libinput_event_pointer *ptrev; double width = 0, height = 0; - int y_movement = 30; /* in percent of height */ + int nevents = 0; + double mm; /* one mm in percent of the device */ - /* account for different touchpad heights, let's move 100% on a 15mm - high touchpad, less on anything else. This number is picked at - random, we just want deltas less than 5. - */ - if (libinput_device_get_size(dev->libinput_device, - &width, - &height) != -1) { - y_movement = 100 * 15/height; - } + ck_assert_int_eq(libinput_device_get_size(dev->libinput_device, + &width, + &height), 0); + mm = 100.0/height; + + /* timeout-based scrolling is disabled when software buttons are + * active, so switch to clickfinger. Not all test devices support + * that, hence the extra check. */ + if (libinput_device_config_click_get_methods(dev->libinput_device) & + LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER) + litest_enable_clickfinger(dev); litest_drain_events(li); litest_enable_edge_scroll(dev); + /* move 0.5mm, enough to load up the motion history, but less than + * the scroll threshold of 2mm */ litest_touch_down(dev, 0, 99, 20); + litest_touch_move_to(dev, 0, 99, 20, 99, 20 + mm/2, 8, 0); libinput_dispatch(li); + litest_assert_empty_queue(li); + litest_timeout_edgescroll(); libinput_dispatch(li); - litest_touch_move_to(dev, 0, 99, 20, 99, 20 + y_movement, 100, 10); + litest_assert_empty_queue(li); + + /* now move slowly up to the 2mm scroll threshold. we expect events */ + litest_touch_move_to(dev, 0, 99, 20 + mm/2, 99, 20 + mm * 2, 20, 0); litest_touch_up(dev, 0); libinput_dispatch(li); - 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), - LIBINPUT_EVENT_POINTER_AXIS); - ptrev = libinput_event_get_pointer_event(event); - - axisval = libinput_event_pointer_get_axis_value(ptrev, - LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); - ck_assert(axisval > 0.0); - - /* this is to verify we test the right thing, if the value - is greater than scroll.threshold we triggered the wrong - condition */ - ck_assert(axisval < 5.0); + while ((event = libinput_get_event(li))) { + double value; + ptrev = litest_is_axis_event(event, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + 0); + value = libinput_event_pointer_get_axis_value(ptrev, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); + ck_assert_double_lt(value, 5.0); libinput_event_destroy(event); - event = libinput_get_event(li); + nevents++; } + /* we sent 20 events but allow for some to be swallowed by rounding + * errors, the hysteresis, etc. */ + ck_assert_int_ge(nevents, 10); + litest_assert_empty_queue(li); libinput_event_destroy(event); } From dac38a08288a791756587a0053f3b7c1af63ec01 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 17 Aug 2015 16:17:41 +1000 Subject: [PATCH 33/43] filter: use named initalizers for the accelerator interface Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/filter.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/filter.c b/src/filter.c index 7054fafa..d05b53ad 100644 --- a/src/filter.c +++ b/src/filter.c @@ -672,10 +672,10 @@ trackpoint_accel_profile(struct motion_filter *filter, } struct motion_filter_interface accelerator_interface = { - accelerator_filter, - accelerator_restart, - accelerator_destroy, - accelerator_set_speed, + .filter = accelerator_filter, + .restart = accelerator_restart, + .destroy = accelerator_destroy, + .set_speed = accelerator_set_speed, }; static struct pointer_accelerator * @@ -718,10 +718,10 @@ create_pointer_accelerator_filter_linear(int dpi) } struct motion_filter_interface accelerator_interface_low_dpi = { - accelerator_filter_low_dpi, - accelerator_restart, - accelerator_destroy, - accelerator_set_speed, + .filter = accelerator_filter_low_dpi, + .restart = accelerator_restart, + .destroy = accelerator_destroy, + .set_speed = accelerator_set_speed, }; struct motion_filter * @@ -755,10 +755,10 @@ create_pointer_accelerator_filter_touchpad(int dpi) } struct motion_filter_interface accelerator_interface_x230 = { - accelerator_filter_x230, - accelerator_restart, - accelerator_destroy, - accelerator_set_speed, + .filter = accelerator_filter_x230, + .restart = accelerator_restart, + .destroy = accelerator_destroy, + .set_speed = accelerator_set_speed, }; /* The Lenovo x230 has a bad touchpad. This accel method has been @@ -792,10 +792,10 @@ create_pointer_accelerator_filter_lenovo_x230(int dpi) } struct motion_filter_interface accelerator_interface_trackpoint = { - accelerator_filter_trackpoint, - accelerator_restart, - accelerator_destroy, - accelerator_set_speed, + .filter = accelerator_filter_trackpoint, + .restart = accelerator_restart, + .destroy = accelerator_destroy, + .set_speed = accelerator_set_speed, }; struct motion_filter * From e4fd60ce5ef0f634ecbc3c445b5a05acee66a09d Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 18 Aug 2015 09:11:48 +1000 Subject: [PATCH 34/43] filter: move the TP_MAGIC_SLOWDOWN to a single definition Requires splitting out the X230 one so we don't accidentally break things if we ever change this. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/filter.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/filter.c b/src/filter.c index d05b53ad..f92b9fdc 100644 --- a/src/filter.c +++ b/src/filter.c @@ -36,6 +36,12 @@ #include "libinput-util.h" #include "filter-private.h" +/* Once normalized, touchpads see the same acceleration as mice. that is + * technically correct but subjectively wrong, we expect a touchpad to be a + * lot slower than a mouse. Apply a magic factor to slow down all movements + */ +#define TP_MAGIC_SLOWDOWN 0.4 /* unitless factor */ + /* Convert speed/velocity from units/us to units/ms */ static inline double v_us2ms(double units_per_us) @@ -581,12 +587,6 @@ touchpad_accel_profile_linear(struct motion_filter *filter, double speed_in, /* units/us */ uint64_t time) { - /* Once normalized, touchpads see the same - acceleration as mice. that is technically correct but - subjectively wrong, we expect a touchpad to be a lot - slower than a mouse. Apply a magic factor here and proceed - as normal. */ - const double TP_MAGIC_SLOWDOWN = 0.4; /* unitless */ double factor; /* unitless */ speed_in *= TP_MAGIC_SLOWDOWN; @@ -603,7 +603,7 @@ touchpad_lenovo_x230_accel_profile(struct motion_filter *filter, uint64_t time) { /* Keep the magic factor from touchpad_accel_profile_linear. */ - const double TP_MAGIC_SLOWDOWN = 0.4; /* unitless */ + const double X230_MAGIC_SLOWDOWN = 0.4; /* unitless */ /* Those touchpads presents an actual lower resolution that what is * advertised. We see some jumps from the cursor due to the big steps @@ -629,14 +629,14 @@ touchpad_lenovo_x230_accel_profile(struct motion_filter *filter, * pointer_accel_profile_linear(), look at the git history of that * function for an explaination of what the min/max/etc. does. */ - speed_in *= TP_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR; + speed_in *= X230_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR; f1 = min(1, v_us2ms(speed_in) * 5); f2 = 1 + (v_us2ms(speed_in) - v_us2ms(threshold)) * incline; factor = min(max_accel, f2 > 1 ? f2 : f1); - return factor * TP_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR; + return factor * X230_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR; } double From d8c37a94c0fe9c77e39034e377ab8796ddc0da3f Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 17 Aug 2015 16:32:20 +1000 Subject: [PATCH 35/43] filter: add a "filter_constant" hook to the filter interface For when we need to apply some transformation to the data but it shouldn't be acceleration. Example use are touchpad coordinates, even when not accelerating, we still want to apply the magic slowdown. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/filter-private.h | 4 ++++ src/filter.c | 20 ++++++++++++++++++++ src/filter.h | 22 ++++++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/src/filter-private.h b/src/filter-private.h index f5e8b7f7..eaf84eda 100644 --- a/src/filter-private.h +++ b/src/filter-private.h @@ -33,6 +33,10 @@ struct motion_filter_interface { struct motion_filter *filter, const struct normalized_coords *unaccelerated, void *data, uint64_t time); + struct normalized_coords (*filter_constant)( + struct motion_filter *filter, + const struct normalized_coords *unaccelerated, + void *data, uint64_t time); void (*restart)(struct motion_filter *filter, void *data, uint64_t time); diff --git a/src/filter.c b/src/filter.c index f92b9fdc..674b439b 100644 --- a/src/filter.c +++ b/src/filter.c @@ -64,6 +64,14 @@ filter_dispatch(struct motion_filter *filter, return filter->interface->filter(filter, unaccelerated, data, time); } +struct normalized_coords +filter_dispatch_constant(struct motion_filter *filter, + const struct normalized_coords *unaccelerated, + void *data, uint64_t time) +{ + return filter->interface->filter_constant(filter, unaccelerated, data, time); +} + void filter_restart(struct motion_filter *filter, void *data, uint64_t time) @@ -319,6 +327,14 @@ accelerator_filter(struct motion_filter *filter, return accelerated; } +static struct normalized_coords +accelerator_filter_noop(struct motion_filter *filter, + const struct normalized_coords *unaccelerated, + void *data, uint64_t time) +{ + return *unaccelerated; +} + static struct normalized_coords accelerator_filter_low_dpi(struct motion_filter *filter, const struct normalized_coords *unaccelerated, @@ -673,6 +689,7 @@ trackpoint_accel_profile(struct motion_filter *filter, struct motion_filter_interface accelerator_interface = { .filter = accelerator_filter, + .filter_constant = accelerator_filter_noop, .restart = accelerator_restart, .destroy = accelerator_destroy, .set_speed = accelerator_set_speed, @@ -719,6 +736,7 @@ create_pointer_accelerator_filter_linear(int dpi) struct motion_filter_interface accelerator_interface_low_dpi = { .filter = accelerator_filter_low_dpi, + .filter_constant = accelerator_filter_noop, .restart = accelerator_restart, .destroy = accelerator_destroy, .set_speed = accelerator_set_speed, @@ -756,6 +774,7 @@ create_pointer_accelerator_filter_touchpad(int dpi) struct motion_filter_interface accelerator_interface_x230 = { .filter = accelerator_filter_x230, + .filter_constant = accelerator_filter_noop, .restart = accelerator_restart, .destroy = accelerator_destroy, .set_speed = accelerator_set_speed, @@ -793,6 +812,7 @@ create_pointer_accelerator_filter_lenovo_x230(int dpi) struct motion_filter_interface accelerator_interface_trackpoint = { .filter = accelerator_filter_trackpoint, + .filter_constant = accelerator_filter_noop, .restart = accelerator_restart, .destroy = accelerator_destroy, .set_speed = accelerator_set_speed, diff --git a/src/filter.h b/src/filter.h index fd36da49..c8ade07d 100644 --- a/src/filter.h +++ b/src/filter.h @@ -34,11 +34,33 @@ struct motion_filter; +/** + * Accelerate the given coordinates. + * Takes a set of unaccelerated deltas and accelerates them based on the + * current and previous motion. + * + * This is a superset of filter_dispatch_constant() + * + * @see filter_dispatch_constant + */ struct normalized_coords filter_dispatch(struct motion_filter *filter, const struct normalized_coords *unaccelerated, void *data, uint64_t time); +/** + * Apply constant motion filters, but no acceleration. + * + * Takes a set of unaccelerated deltas and applies any constant filters to + * it but does not accelerate the delta in the conventional sense. + * + * @see filter_dispatch + */ +struct normalized_coords +filter_dispatch_constant(struct motion_filter *filter, + const struct normalized_coords *unaccelerated, + void *data, uint64_t time); + void filter_restart(struct motion_filter *filter, void *data, uint64_t time); From c8da19b50a30d840484383f41e0218814f1501a0 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 6 Aug 2015 14:59:38 +1000 Subject: [PATCH 36/43] touchpad: use unaccelerated motion data for scrolling For short and quick scroll gestures, those that should only trigger a few lines of scroll the pointer acceleration is wildly unpredictable. Since we average the motion of both fingers it's hard enough to intuitively predict what the motion will be like. On top of that is the small threshold before we start scrolling, so some of the initial motion gets swallowed before we accelerate, making the next motion even more unpredictable. The end result is that multiple seemingly identical finger motions cause wildly different scroll motion. Drop pointer acceleration for two-finger and edge scrolling. This makes short scroll motions much more predictable and doesn't seem to have much effect on long scroll motions. Plus, in natural scroll mode it really feels like the content is stuck to your fingers now. Go wash your hands. https://bugzilla.redhat.com/show_bug.cgi?id=1249365 Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad-edge-scroll.c | 3 ++- src/evdev-mt-touchpad-gestures.c | 3 ++- src/evdev-mt-touchpad.c | 12 ++++++++++++ src/evdev-mt-touchpad.h | 4 ++++ src/filter.c | 23 ++++++++++++++++++++++- 5 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/evdev-mt-touchpad-edge-scroll.c b/src/evdev-mt-touchpad-edge-scroll.c index eda62e4d..b572a9fb 100644 --- a/src/evdev-mt-touchpad-edge-scroll.c +++ b/src/evdev-mt-touchpad-edge-scroll.c @@ -390,7 +390,8 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time) } normalized = tp_get_delta(t); - normalized = tp_filter_motion(tp, &normalized, time); + /* scroll is not accelerated */ + normalized = tp_filter_motion_unaccelerated(tp, &normalized, time); switch (t->scroll.edge_state) { case EDGE_SCROLL_TOUCH_STATE_NONE: diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c index d82a6fb9..cc26e2a9 100644 --- a/src/evdev-mt-touchpad-gestures.c +++ b/src/evdev-mt-touchpad-gestures.c @@ -328,7 +328,8 @@ tp_gesture_twofinger_handle_state_scroll(struct tp_dispatch *tp, uint64_t time) delta = tp_get_average_touches_delta(tp); } - delta = tp_filter_motion(tp, &delta, time); + /* scroll is not accelerated */ + delta = tp_filter_motion_unaccelerated(tp, &delta, time); if (normalized_is_zero(delta)) return GESTURE_2FG_STATE_SCROLL; diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index a32a771c..aeb6c314 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -71,6 +71,18 @@ tp_filter_motion(struct tp_dispatch *tp, unaccelerated, tp, time); } +struct normalized_coords +tp_filter_motion_unaccelerated(struct tp_dispatch *tp, + const struct normalized_coords *unaccelerated, + uint64_t time) +{ + if (normalized_is_zero(*unaccelerated)) + return *unaccelerated; + + return filter_dispatch_constant(tp->device->pointer.filter, + unaccelerated, tp, time); +} + static inline void tp_motion_history_push(struct tp_touch *t) { diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index 3bd84258..5f87c3f3 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -395,6 +395,10 @@ struct normalized_coords tp_filter_motion(struct tp_dispatch *tp, const struct normalized_coords *unaccelerated, uint64_t time); +struct normalized_coords +tp_filter_motion_unaccelerated(struct tp_dispatch *tp, + const struct normalized_coords *unaccelerated, + uint64_t time); int tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t); diff --git a/src/filter.c b/src/filter.c index 674b439b..5df50d38 100644 --- a/src/filter.c +++ b/src/filter.c @@ -420,6 +420,19 @@ accelerator_filter_x230(struct motion_filter *filter, return accelerated; } +static struct normalized_coords +touchpad_constant_filter(struct motion_filter *filter, + const struct normalized_coords *unaccelerated, + void *data, uint64_t time) +{ + struct normalized_coords normalized; + + normalized.x = TP_MAGIC_SLOWDOWN * unaccelerated->x; + normalized.y = TP_MAGIC_SLOWDOWN * unaccelerated->y; + + return normalized; +} + static void accelerator_restart(struct motion_filter *filter, void *data, @@ -757,6 +770,14 @@ create_pointer_accelerator_filter_linear_low_dpi(int dpi) return &filter->base; } +struct motion_filter_interface accelerator_interface_touchpad = { + .filter = accelerator_filter, + .filter_constant = touchpad_constant_filter, + .restart = accelerator_restart, + .destroy = accelerator_destroy, + .set_speed = accelerator_set_speed, +}; + struct motion_filter * create_pointer_accelerator_filter_touchpad(int dpi) { @@ -766,7 +787,7 @@ create_pointer_accelerator_filter_touchpad(int dpi) if (!filter) return NULL; - filter->base.interface = &accelerator_interface; + filter->base.interface = &accelerator_interface_touchpad; filter->profile = touchpad_accel_profile_linear; return &filter->base; From 9c4241ca8274c599c630ec5eb0df0b93f70944d9 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 17 Aug 2015 13:15:01 +1000 Subject: [PATCH 37/43] configure.ac: libinput 1.0RC1 Signed-off-by: Peter Hutterer --- configure.ac | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 885cb394..b54c2add 100644 --- a/configure.ac +++ b/configure.ac @@ -1,8 +1,8 @@ AC_PREREQ([2.64]) m4_define([libinput_major_version], [0]) -m4_define([libinput_minor_version], [21]) -m4_define([libinput_micro_version], [0]) +m4_define([libinput_minor_version], [99]) +m4_define([libinput_micro_version], [1]) m4_define([libinput_version], [libinput_major_version.libinput_minor_version.libinput_micro_version]) @@ -31,7 +31,7 @@ AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz]) # b) If interfaces have been changed or added, but binary compatibility has # been preserved, change to C+1:0:A+1 # c) If the interface is the same as the previous version, change to C:R+1:A -LIBINPUT_LT_VERSION=15:0:5 +LIBINPUT_LT_VERSION=15:1:5 AC_SUBST(LIBINPUT_LT_VERSION) AM_SILENT_RULES([yes]) From a2c9787a8bfa79f1ad2dce6e4bceda6ede3f5b49 Mon Sep 17 00:00:00 2001 From: Andreas Pokorny Date: Thu, 20 Aug 2015 10:33:32 +0200 Subject: [PATCH 38/43] doc: inverse event type restriction of x and y accessors Signed-off-by: Andreas Pokorny Signed-off-by: Peter Hutterer --- src/libinput.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/libinput.h b/src/libinput.h index f2b77b34..88b3c05f 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -894,7 +894,8 @@ libinput_event_touch_get_seat_slot(struct libinput_event_touch *event); * LIBINPUT_EVENT_TOUCH_MOTION, this function returns 0. * * @note It is an application bug to call this function for events of type - * @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref LIBINPUT_EVENT_TOUCH_MOTION. + * other than @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref + * LIBINPUT_EVENT_TOUCH_MOTION. * * @param event The libinput touch event * @return The current absolute x coordinate @@ -913,7 +914,8 @@ libinput_event_touch_get_x(struct libinput_event_touch *event); * LIBINPUT_EVENT_TOUCH_MOTION, this function returns 0. * * @note It is an application bug to call this function for events of type - * @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref LIBINPUT_EVENT_TOUCH_MOTION. + * other than @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref + * LIBINPUT_EVENT_TOUCH_MOTION. * * @param event The libinput touch event * @return The current absolute y coordinate @@ -931,7 +933,8 @@ libinput_event_touch_get_y(struct libinput_event_touch *event); * LIBINPUT_EVENT_TOUCH_MOTION, this function returns 0. * * @note It is an application bug to call this function for events of type - * @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref LIBINPUT_EVENT_TOUCH_MOTION. + * other than @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref + * LIBINPUT_EVENT_TOUCH_MOTION. * * @param event The libinput touch event * @param width The current output screen width @@ -951,7 +954,8 @@ libinput_event_touch_get_x_transformed(struct libinput_event_touch *event, * LIBINPUT_EVENT_TOUCH_MOTION, this function returns 0. * * @note It is an application bug to call this function for events of type - * @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref LIBINPUT_EVENT_TOUCH_MOTION. + * other than @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref + * LIBINPUT_EVENT_TOUCH_MOTION. * * @param event The libinput touch event * @param height The current output screen height From d0ae1d99b358c81b495d3ff2c0a89d2689692661 Mon Sep 17 00:00:00 2001 From: Andreas Pokorny Date: Thu, 20 Aug 2015 10:31:47 +0200 Subject: [PATCH 39/43] doc: ellipse instead of ellipsis Signed-off-by: Andreas Pokorny Signed-off-by: Peter Hutterer --- doc/touchpads.dox | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/touchpads.dox b/doc/touchpads.dox index fa509bc6..401f16a5 100644 --- a/doc/touchpads.dox +++ b/doc/touchpads.dox @@ -71,7 +71,7 @@ touches, others support 5 touches like the Synaptics touchpads when using SMBus. These touchpads usually also provide extra information. Apple touchpads -provide an ellipsis and the orientation of the ellipsis for each touch point. +provide an ellipse and the orientation of the ellipse for each touch point. Other touchpads provide a pressure value for each touch point (see @ref touchpads_pressure_handling). @@ -138,7 +138,7 @@ pressure data is often device-specific and unreliable. @subsection touchpads_circular Circular touchpads Only listed for completeness, circular touchpads have not been used in -laptops for a number of years. These touchpad shaped in an ellipsis or +laptops for a number of years. These touchpad shaped in an ellipse or straight. @subsection touchpads_tablets Graphics tablets From 4c8f8a7ea275c17ce95bbbd6e239a0e339e316ea Mon Sep 17 00:00:00 2001 From: Andreas Pokorny Date: Thu, 20 Aug 2015 12:51:37 +0200 Subject: [PATCH 40/43] test: fix gcc warning about missing prototypes Signed-off-by: Andreas Pokorny Signed-off-by: Peter Hutterer --- test/litest.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/litest.c b/test/litest.c index 26c5e432..6b28ee0b 100644 --- a/test/litest.c +++ b/test/litest.c @@ -44,6 +44,8 @@ #include #include #include +#include +#include #include #include "litest.h" From 7095b765acc8851d0faaab990d65028d5a1d0b86 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Fri, 21 Aug 2015 08:42:54 -0700 Subject: [PATCH 41/43] doc: fix more typos Signed-off-by: Jason Gerecke Signed-off-by: Peter Hutterer --- doc/absolute-axes.dox | 2 +- doc/faqs.dox | 2 +- doc/gestures.dox | 2 +- doc/palm-detection.dox | 4 ++-- doc/reporting-bugs.dox | 2 +- doc/seats.dox | 4 ++-- doc/tapping.dox | 2 +- doc/tools.dox | 4 ++-- doc/touchpads.dox | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) diff --git a/doc/absolute-axes.dox b/doc/absolute-axes.dox index 7d205f62..664c6164 100644 --- a/doc/absolute-axes.dox +++ b/doc/absolute-axes.dox @@ -67,7 +67,7 @@ or height. Note that rotation applies to the device's origin, rotation usually requires an offset to move the coordinates back into the original range. -The most comon matrices are: +The most common matrices are: - 90 degree clockwise: @f$ diff --git a/doc/faqs.dox b/doc/faqs.dox index 9a78dead..0e49dac5 100644 --- a/doc/faqs.dox +++ b/doc/faqs.dox @@ -30,7 +30,7 @@ scroll_sources. @section faq_gpl Is libinput GPL-licensed? No, libinput is MIT licensed. The Linux kernel header file linux/input.h in -libinput's tree is provded to ensure the same behavior regardless of which +libinput's tree is provided to ensure the same behavior regardless of which kernel version libinput is built on. It does not make libinput GPL-licensed. @section faq_config_options Where is the configuration stored? diff --git a/doc/gestures.dox b/doc/gestures.dox index a8cef36d..02ef09ab 100644 --- a/doc/gestures.dox +++ b/doc/gestures.dox @@ -82,7 +82,7 @@ screen as well as the context of those virtual objects: @image html touchscreen-gestures.svg "Context-sensitivity of touchscreen gestures" In this example, the finger movements are identical but in the left case -both fingers are located within the same window, thus suggesting an attemp +both fingers are located within the same window, thus suggesting an attempt to zoom. In the right case both fingers are located on a window border, thus suggesting a window movement. libinput only has knowledge of the finger coordinates (and even then only in device coordinates, not in screen diff --git a/doc/palm-detection.dox b/doc/palm-detection.dox index 1a5e6572..d30a2070 100644 --- a/doc/palm-detection.dox +++ b/doc/palm-detection.dox @@ -46,10 +46,10 @@ will generate a button event for this touch. If a device provides a trackpoint, it is -usually located above the touchpad. This increases the likelyhood of +usually located above the touchpad. This increases the likelihood of accidental touches whenever the trackpoint is used. -libinput disables the touchpad whenver it detects trackpoint activity for a +libinput disables the touchpad whenever it detects trackpoint activity for a certain timeout until after trackpoint activity stops. Touches generated during this timeout will not move the pointer, and touches started during this timeout will likewise not move the pointer (allowing for a user to rest diff --git a/doc/reporting-bugs.dox b/doc/reporting-bugs.dox index 0755a9ee..ec0ef9be 100644 --- a/doc/reporting-bugs.dox +++ b/doc/reporting-bugs.dox @@ -8,7 +8,7 @@ When reporting bugs against libinput, please follow the instructions below and provide the required data. This will speed up triage, resulting in a quicker bugfix. -First, try to identify the bugi by reproducing it reliably. The more +First, try to identify the bug by reproducing it reliably. The more specific a bug description is, the easier it is to fix. The @ref libinput-debug-events helper tool can help identify whether the bug is in libinput at all. This tool is a direct hook to libinput without a desktop diff --git a/doc/seats.dox b/doc/seats.dox index 5eec5ded..f67de6bb 100644 --- a/doc/seats.dox +++ b/doc/seats.dox @@ -5,7 +5,7 @@ Each device in libinput is assigned to one seat. A seat has two identifiers, the physical name and the logical name. The physical name is summarized as the list of devices a process on the same physical seat has access to. The logical seat name is the seat name for a -logical group of devices. A compositor may use that to create additonal +logical group of devices. A compositor may use that to create additional seats as independent device sets. Alternatively, a compositor may limit itself to a single logical seat, leaving a second compositor to manage devices on the other logical seats. @@ -32,7 +32,7 @@ libinput_seat, all other devices reference their own respective seats. @section seats_and_features The effect of seat assignment -A logical set is interprested as a group of devices that usually belong to a +A logical set is interpreted as a group of devices that usually belong to a single user that interacts with a computer. Thus, the devices are semantically related. This means for devices within the same logical seat: diff --git a/doc/tapping.dox b/doc/tapping.dox index 483219ad..e7044005 100644 --- a/doc/tapping.dox +++ b/doc/tapping.dox @@ -40,7 +40,7 @@ disabled with libinput_device_config_tap_set_drag_lock_enabled(). The above diagram explains the process, a tap (a) followed by a finger held down (b) starts the drag process and logically holds the left mouse button down. A movement of the finger (c) will drag the selected item until the -finger is relased (e). If needed and drag lock is enabled, the finger's +finger is released (e). If needed and drag lock is enabled, the finger's position can be reset by lifting and quickly setting it down again on the touchpad (d). This will be interpreted as continuing move and is especially useful on small touchpads or with slow pointer acceleration. diff --git a/doc/tools.dox b/doc/tools.dox index 2bf07935..7fe1e072 100644 --- a/doc/tools.dox +++ b/doc/tools.dox @@ -8,7 +8,7 @@ tools are usually installed, others are @ref developer_tools only. libinput ships with two tools to gather information about devices: @ref libinput-list-devices and @ref libinput-debug-events. Both tools must -be run as root to have acess to the kernel's @c /dev/input/event* device +be run as root to have access to the kernel's @c /dev/input/event* device files. @subsection libinput-list-devices @@ -97,6 +97,6 @@ $ sudo ./tools/event-gui See the @c --help output for information about the available options. @note The @c --grab flag puts an exclusive @c EVIOCGRAB on the device to -avoid interference with the desktiop while testing. +avoid interference with the desktop while testing. */ diff --git a/doc/touchpads.dox b/doc/touchpads.dox index 401f16a5..91a9b6a7 100644 --- a/doc/touchpads.dox +++ b/doc/touchpads.dox @@ -130,7 +130,7 @@ located underneath the keyboard, accidental palm touches are a non-issue. Pressure is usually directly related to contact area. Human fingers flatten out as the pressure on the pad increases, resulting in a bigger contact area -and the firmware then calculates that back into a ressure reading. +and the firmware then calculates that back into a pressure reading. libinput uses pressure to detect accidental palm contact and thumbs, though pressure data is often device-specific and unreliable. From 84318021c04bacd13d422614c06efad95d020cf6 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 24 Aug 2015 09:35:40 +1000 Subject: [PATCH 42/43] doc: add a diagram for evemu and note that libinput doesn't recordings Signed-off-by: Peter Hutterer --- doc/Makefile.am | 1 + doc/dot/evemu.gv | 19 +++++++++++++++++++ doc/reporting-bugs.dox | 6 ++++++ 3 files changed, 26 insertions(+) create mode 100644 doc/dot/evemu.gv diff --git a/doc/Makefile.am b/doc/Makefile.am index a8d41822..fe70f6a5 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -34,6 +34,7 @@ diagram_files = \ $(srcdir)/dot/libinput-stack-wayland.gv \ $(srcdir)/dot/libinput-stack-xorg.gv \ $(srcdir)/dot/libinput-stack-gnome.gv \ + $(srcdir)/dot/evemu.gv \ $(srcdir)/svg/software-buttons.svg \ $(srcdir)/svg/clickfinger.svg \ $(srcdir)/svg/button-scrolling.svg \ diff --git a/doc/dot/evemu.gv b/doc/dot/evemu.gv new file mode 100644 index 00000000..85e93f3e --- /dev/null +++ b/doc/dot/evemu.gv @@ -0,0 +1,19 @@ +digraph stack +{ + compound=true; + rankdir="LR"; + node [ + shape="box"; + ] + + kernel [label="Kernel"]; + + libinput; + xserver [label="X Server"]; + + kernel -> libinput + libinput -> xserver + + kernel -> evemu + evemu -> stdout +} diff --git a/doc/reporting-bugs.dox b/doc/reporting-bugs.dox index ec0ef9be..07f4be78 100644 --- a/doc/reporting-bugs.dox +++ b/doc/reporting-bugs.dox @@ -85,4 +85,10 @@ $ sudo evemu-play /dev/input/event4 < scroll.evemu If the bug is triggered by replaying on your device, attach the recording to the bug report. +@note libinput does not affect the evemu recording. libinput and evemu talk +directly to the kernel's device nodes. An evemu recording is not influenced +by the libinput version or whether a libinput context is currently active. + +@dotfile evemu.gv + */ From 8215d725d0918e98cc72ac8fb0bbe57eb133542f Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 26 Aug 2015 10:43:07 +1000 Subject: [PATCH 43/43] configure.ac: libinput 1.0 Signed-off-by: Peter Hutterer --- configure.ac | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index b54c2add..60664d1b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,8 +1,8 @@ AC_PREREQ([2.64]) -m4_define([libinput_major_version], [0]) -m4_define([libinput_minor_version], [99]) -m4_define([libinput_micro_version], [1]) +m4_define([libinput_major_version], [1]) +m4_define([libinput_minor_version], [0]) +m4_define([libinput_micro_version], [0]) m4_define([libinput_version], [libinput_major_version.libinput_minor_version.libinput_micro_version]) @@ -31,7 +31,7 @@ AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz]) # b) If interfaces have been changed or added, but binary compatibility has # been preserved, change to C+1:0:A+1 # c) If the interface is the same as the previous version, change to C:R+1:A -LIBINPUT_LT_VERSION=15:1:5 +LIBINPUT_LT_VERSION=15:2:5 AC_SUBST(LIBINPUT_LT_VERSION) AM_SILENT_RULES([yes])