From 99334e11bfd426687edf99a913ae0502a428e107 Mon Sep 17 00:00:00 2001 From: Kim Lindberger Date: Fri, 17 Aug 2018 15:12:58 +0200 Subject: [PATCH] Add quirk to control velocity averaging, disable it by default libinput applies averaging to the velocity of most pointer devices. Averaging the velocity makes the motion look smooth and may be of benefit to bad input devices. For good devices, however, it comes at the unfortunate price of decreased accuaracy. This change turns velocity averaging off by default (sets ntrackers to 2 instead of 16) and allows for it to be turned back on via a quirk, for bad devices which require it. --- src/evdev-mt-touchpad.c | 11 ++++++++--- src/evdev.c | 36 +++++++++++++++++++++++++++++++++--- src/evdev.h | 1 + src/filter-low-dpi.c | 8 ++++---- src/filter-mouse.c | 8 ++++---- src/filter-private.h | 2 +- src/filter-touchpad-x230.c | 4 ++-- src/filter-touchpad.c | 5 +++-- src/filter-trackpoint.c | 4 ++-- src/filter.c | 4 +--- src/filter.h | 11 ++++++----- src/quirks.c | 13 +++++++++++++ src/quirks.h | 1 + tools/ptraccel-debug.c | 17 ++++++++++++----- tools/shared.c | 5 +++++ 15 files changed, 96 insertions(+), 34 deletions(-) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 1393c308..291b6322 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -2660,6 +2660,8 @@ tp_init_accel(struct tp_dispatch *tp) struct evdev_device *device = tp->device; int res_x, res_y; struct motion_filter *filter; + int dpi = device->dpi; + bool use_v_avg = device->use_velocity_averaging; res_x = tp->device->abs.absinfo_x->resolution; res_y = tp->device->abs.absinfo_y->resolution; @@ -2677,11 +2679,14 @@ tp_init_accel(struct tp_dispatch *tp) if (tp->device->model_flags & EVDEV_MODEL_LENOVO_X230 || tp->device->model_flags & EVDEV_MODEL_LENOVO_X220_TOUCHPAD_FW81) - filter = create_pointer_accelerator_filter_lenovo_x230(tp->device->dpi); + filter = create_pointer_accelerator_filter_lenovo_x230(dpi, use_v_avg); else if (libevdev_get_id_bustype(device->evdev) == BUS_BLUETOOTH) - filter = create_pointer_accelerator_filter_touchpad(device->dpi, ms2us(50), ms2us(10)); + filter = create_pointer_accelerator_filter_touchpad(dpi, + ms2us(50), + ms2us(10), + use_v_avg); else - filter = create_pointer_accelerator_filter_touchpad(device->dpi, 0, 0); + filter = create_pointer_accelerator_filter_touchpad(dpi, 0, 0, use_v_avg); if (!filter) return false; diff --git a/src/evdev.c b/src/evdev.c index 806b9a46..93955786 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -956,11 +956,14 @@ evdev_init_accel(struct evdev_device *device, if (which == LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT) filter = create_pointer_accelerator_filter_flat(device->dpi); else if (device->tags & EVDEV_TAG_TRACKPOINT) - filter = create_pointer_accelerator_filter_trackpoint(device->trackpoint_multiplier); + filter = create_pointer_accelerator_filter_trackpoint(device->trackpoint_multiplier, + device->use_velocity_averaging); else if (device->dpi < DEFAULT_MOUSE_DPI) - filter = create_pointer_accelerator_filter_linear_low_dpi(device->dpi); + filter = create_pointer_accelerator_filter_linear_low_dpi(device->dpi, + device->use_velocity_averaging); else - filter = create_pointer_accelerator_filter_linear(device->dpi); + filter = create_pointer_accelerator_filter_linear(device->dpi, + device->use_velocity_averaging); if (!filter) return false; @@ -1208,6 +1211,29 @@ evdev_get_trackpoint_multiplier(struct evdev_device *device) return multiplier; } +static inline bool +evdev_need_velocity_averaging(struct evdev_device *device) +{ + struct quirks_context *quirks; + struct quirks *q; + bool use_velocity_averaging = false; /* default off unless we have quirk */ + + quirks = evdev_libinput_context(device)->quirks; + q = quirks_fetch_for_device(quirks, device->udev_device); + if (q) { + quirks_get_bool(q, + QUIRK_ATTR_USE_VELOCITY_AVERAGING, + &use_velocity_averaging); + quirks_unref(q); + } + + if (use_velocity_averaging) + evdev_log_info(device, + "velocity averaging is turned on\n"); + + return use_velocity_averaging; +} + static inline int evdev_read_dpi_prop(struct evdev_device *device) { @@ -1716,6 +1742,8 @@ evdev_configure_device(struct evdev_device *device) if (udev_tags & EVDEV_UDEV_TAG_TOUCHPAD) { if (udev_tags & EVDEV_UDEV_TAG_TABLET) evdev_tag_tablet_touchpad(device); + /* whether velocity should be averaged, false by default */ + device->use_velocity_averaging = evdev_need_velocity_averaging(device); dispatch = evdev_mt_touchpad_create(device); evdev_log_info(device, "device is a touchpad\n"); return dispatch; @@ -1727,6 +1755,8 @@ evdev_configure_device(struct evdev_device *device) evdev_tag_trackpoint(device, device->udev_device); device->dpi = evdev_read_dpi_prop(device); device->trackpoint_multiplier = evdev_get_trackpoint_multiplier(device); + /* whether velocity should be averaged, false by default */ + device->use_velocity_averaging = evdev_need_velocity_averaging(device); device->seat_caps |= EVDEV_DEVICE_POINTER; diff --git a/src/evdev.h b/src/evdev.h index 347086a1..81d9a5f0 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -175,6 +175,7 @@ struct evdev_device { bool is_suspended; int dpi; /* HW resolution */ double trackpoint_multiplier; /* trackpoint constant multiplier */ + bool use_velocity_averaging; /* whether averaging should be applied on velocity calculation */ 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/src/filter-low-dpi.c b/src/filter-low-dpi.c index 6b017afb..9a39f525 100644 --- a/src/filter-low-dpi.c +++ b/src/filter-low-dpi.c @@ -236,14 +236,14 @@ struct motion_filter_interface accelerator_interface_low_dpi = { }; static struct pointer_accelerator_low_dpi * -create_default_filter(int dpi) +create_default_filter(int dpi, bool use_velocity_averaging) { struct pointer_accelerator_low_dpi *filter; filter = zalloc(sizeof *filter); filter->last_velocity = 0.0; - trackers_init(&filter->trackers); + trackers_init(&filter->trackers, use_velocity_averaging ? 16 : 2); filter->threshold = DEFAULT_THRESHOLD; filter->accel = DEFAULT_ACCELERATION; @@ -254,11 +254,11 @@ create_default_filter(int dpi) } struct motion_filter * -create_pointer_accelerator_filter_linear_low_dpi(int dpi) +create_pointer_accelerator_filter_linear_low_dpi(int dpi, bool use_velocity_averaging) { struct pointer_accelerator_low_dpi *filter; - filter = create_default_filter(dpi); + filter = create_default_filter(dpi, use_velocity_averaging); if (!filter) return NULL; diff --git a/src/filter-mouse.c b/src/filter-mouse.c index 37444869..89c3919b 100644 --- a/src/filter-mouse.c +++ b/src/filter-mouse.c @@ -310,14 +310,14 @@ struct motion_filter_interface accelerator_interface = { }; static struct pointer_accelerator * -create_default_filter(int dpi) +create_default_filter(int dpi, bool use_velocity_averaging) { struct pointer_accelerator *filter; filter = zalloc(sizeof *filter); filter->last_velocity = 0.0; - trackers_init(&filter->trackers); + trackers_init(&filter->trackers, use_velocity_averaging ? 16 : 2); filter->threshold = DEFAULT_THRESHOLD; filter->accel = DEFAULT_ACCELERATION; @@ -328,11 +328,11 @@ create_default_filter(int dpi) } struct motion_filter * -create_pointer_accelerator_filter_linear(int dpi) +create_pointer_accelerator_filter_linear(int dpi, bool use_velocity_averaging) { struct pointer_accelerator *filter; - filter = create_default_filter(dpi); + filter = create_default_filter(dpi, use_velocity_averaging); if (!filter) return NULL; diff --git a/src/filter-private.h b/src/filter-private.h index fa2fea40..b24a5c9a 100644 --- a/src/filter-private.h +++ b/src/filter-private.h @@ -71,7 +71,7 @@ struct pointer_trackers { struct pointer_delta_smoothener *smoothener; }; -void trackers_init(struct pointer_trackers *trackers); +void trackers_init(struct pointer_trackers *trackers, int ntrackers); void trackers_free(struct pointer_trackers *trackers); void diff --git a/src/filter-touchpad-x230.c b/src/filter-touchpad-x230.c index 10bdc1bb..65fae37b 100644 --- a/src/filter-touchpad-x230.c +++ b/src/filter-touchpad-x230.c @@ -331,7 +331,7 @@ struct motion_filter_interface accelerator_interface_x230 = { * Don't touch this. */ struct motion_filter * -create_pointer_accelerator_filter_lenovo_x230(int dpi) +create_pointer_accelerator_filter_lenovo_x230(int dpi, bool use_velocity_averaging) { struct pointer_accelerator_x230 *filter; @@ -340,7 +340,7 @@ create_pointer_accelerator_filter_lenovo_x230(int dpi) filter->profile = touchpad_lenovo_x230_accel_profile; filter->last_velocity = 0.0; - trackers_init(&filter->trackers); + trackers_init(&filter->trackers, use_velocity_averaging ? 16 : 2); filter->threshold = X230_THRESHOLD; filter->accel = X230_ACCELERATION; /* unitless factor */ diff --git a/src/filter-touchpad.c b/src/filter-touchpad.c index cfad1968..9c19527b 100644 --- a/src/filter-touchpad.c +++ b/src/filter-touchpad.c @@ -318,7 +318,8 @@ struct motion_filter_interface accelerator_interface_touchpad = { struct motion_filter * create_pointer_accelerator_filter_touchpad(int dpi, uint64_t event_delta_smooth_threshold, - uint64_t event_delta_smooth_value) + uint64_t event_delta_smooth_value, + bool use_velocity_averaging) { struct touchpad_accelerator *filter; struct pointer_delta_smoothener *smoothener; @@ -326,7 +327,7 @@ create_pointer_accelerator_filter_touchpad(int dpi, filter = zalloc(sizeof *filter); filter->last_velocity = 0.0; - trackers_init(&filter->trackers); + trackers_init(&filter->trackers, use_velocity_averaging ? 16 : 2); filter->threshold = 130; filter->dpi = dpi; diff --git a/src/filter-trackpoint.c b/src/filter-trackpoint.c index a401a712..c85a082a 100644 --- a/src/filter-trackpoint.c +++ b/src/filter-trackpoint.c @@ -182,7 +182,7 @@ struct motion_filter_interface accelerator_interface_trackpoint = { }; struct motion_filter * -create_pointer_accelerator_filter_trackpoint(double multiplier) +create_pointer_accelerator_filter_trackpoint(double multiplier, bool use_velocity_averaging) { struct trackpoint_accelerator *filter; struct pointer_delta_smoothener *smoothener; @@ -207,7 +207,7 @@ create_pointer_accelerator_filter_trackpoint(double multiplier) filter->multiplier = multiplier; - trackers_init(&filter->trackers); + trackers_init(&filter->trackers, use_velocity_averaging ? 16 : 2); filter->base.interface = &accelerator_interface_trackpoint; diff --git a/src/filter.c b/src/filter.c index fe60c62a..ef081dde 100644 --- a/src/filter.c +++ b/src/filter.c @@ -91,10 +91,8 @@ filter_get_type(struct motion_filter *filter) } void -trackers_init(struct pointer_trackers *trackers) +trackers_init(struct pointer_trackers *trackers, int ntrackers) { - const int ntrackers = 16; - trackers->trackers = zalloc(ntrackers * sizeof(*trackers->trackers)); trackers->ntrackers = ntrackers; diff --git a/src/filter.h b/src/filter.h index 7e001d2f..177acbdb 100644 --- a/src/filter.h +++ b/src/filter.h @@ -108,21 +108,22 @@ struct motion_filter * create_pointer_accelerator_filter_flat(int dpi); struct motion_filter * -create_pointer_accelerator_filter_linear(int dpi); +create_pointer_accelerator_filter_linear(int dpi, bool use_velocity_averaging); struct motion_filter * -create_pointer_accelerator_filter_linear_low_dpi(int dpi); +create_pointer_accelerator_filter_linear_low_dpi(int dpi, bool use_velocity_averaging); struct motion_filter * create_pointer_accelerator_filter_touchpad(int dpi, uint64_t event_delta_smooth_threshold, - uint64_t event_delta_smooth_value); + uint64_t event_delta_smooth_value, + bool use_velocity_averaging); struct motion_filter * -create_pointer_accelerator_filter_lenovo_x230(int dpi); +create_pointer_accelerator_filter_lenovo_x230(int dpi, bool use_velocity_averaging); struct motion_filter * -create_pointer_accelerator_filter_trackpoint(double multiplier); +create_pointer_accelerator_filter_trackpoint(double multiplier, bool use_velocity_averaging); struct motion_filter * create_pointer_accelerator_filter_tablet(int xres, int yres); diff --git a/src/quirks.c b/src/quirks.c index 0525e81a..54b207d1 100644 --- a/src/quirks.c +++ b/src/quirks.c @@ -267,6 +267,7 @@ quirk_get_name(enum quirk q) case QUIRK_ATTR_RESOLUTION_HINT: return "AttrResolutionHint"; case QUIRK_ATTR_TRACKPOINT_MULTIPLIER: return "AttrTrackpointMultiplier"; case QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD: return "AttrThumbPressureThreshold"; + case QUIRK_ATTR_USE_VELOCITY_AVERAGING: return "AttrUseVelocityAveraging"; default: abort(); } @@ -643,6 +644,7 @@ parse_attr(struct quirks_context *ctx, struct quirk_dimensions dim; struct quirk_range range; unsigned int v; + bool b; double d; if (streq(key, quirk_get_name(QUIRK_ATTR_SIZE_HINT))) { @@ -716,6 +718,17 @@ parse_attr(struct quirks_context *ctx, p->type = PT_DOUBLE; p->value.d = d; rc = true; + } else if (streq(key, quirk_get_name(QUIRK_ATTR_USE_VELOCITY_AVERAGING))) { + p->id = QUIRK_ATTR_USE_VELOCITY_AVERAGING; + if (streq(value, "1")) + b = true; + else if (streq(value, "0")) + b = false; + else + goto out; + p->type = PT_BOOL; + p->value.b = b; + rc = true; } else if (streq(key, quirk_get_name(QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD))) { p->id = QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD; if (!safe_atou(value, &v)) diff --git a/src/quirks.h b/src/quirks.h index c5d38b24..051ce7b6 100644 --- a/src/quirks.h +++ b/src/quirks.h @@ -95,6 +95,7 @@ enum quirk { QUIRK_ATTR_RESOLUTION_HINT, QUIRK_ATTR_TRACKPOINT_MULTIPLIER, QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD, + QUIRK_ATTR_USE_VELOCITY_AVERAGING, }; /** diff --git a/tools/ptraccel-debug.c b/tools/ptraccel-debug.c index 9a84688a..5e403b66 100644 --- a/tools/ptraccel-debug.c +++ b/tools/ptraccel-debug.c @@ -222,6 +222,7 @@ main(int argc, char **argv) double custom_deltas[1024]; double speed = 0.0; int dpi = 1000; + bool use_averaging = false; const char *filter_type = "linear"; accel_profile_func_t profile = NULL; double tp_multiplier = 1.0; @@ -314,19 +315,25 @@ main(int argc, char **argv) } if (streq(filter_type, "linear")) { - filter = create_pointer_accelerator_filter_linear(dpi); + filter = create_pointer_accelerator_filter_linear(dpi, + use_averaging); profile = pointer_accel_profile_linear; } else if (streq(filter_type, "low-dpi")) { - filter = create_pointer_accelerator_filter_linear_low_dpi(dpi); + filter = create_pointer_accelerator_filter_linear_low_dpi(dpi, + use_averaging); profile = pointer_accel_profile_linear_low_dpi; } else if (streq(filter_type, "touchpad")) { - filter = create_pointer_accelerator_filter_touchpad(dpi, 0, 0); + filter = create_pointer_accelerator_filter_touchpad(dpi, + 0, 0, + use_averaging); profile = touchpad_accel_profile_linear; } else if (streq(filter_type, "x230")) { - filter = create_pointer_accelerator_filter_lenovo_x230(dpi); + filter = create_pointer_accelerator_filter_lenovo_x230(dpi, + use_averaging); profile = touchpad_lenovo_x230_accel_profile; } else if (streq(filter_type, "trackpoint")) { - filter = create_pointer_accelerator_filter_trackpoint(tp_multiplier); + filter = create_pointer_accelerator_filter_trackpoint(tp_multiplier, + use_averaging); profile = trackpoint_accel_profile; } else { fprintf(stderr, "Invalid filter type %s\n", filter_type); diff --git a/tools/shared.c b/tools/shared.c index f68ffead..7b3b8de2 100644 --- a/tools/shared.c +++ b/tools/shared.c @@ -639,6 +639,7 @@ tools_list_device_quirks(struct quirks_context *ctx, QUIRK_ATTR_RESOLUTION_HINT, QUIRK_ATTR_TRACKPOINT_MULTIPLIER, QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD, + QUIRK_ATTR_USE_VELOCITY_AVERAGING, }; enum quirk *q; @@ -722,6 +723,10 @@ tools_list_device_quirks(struct quirks_context *ctx, snprintf(buf, sizeof(buf), "%s=%0.2f\n", name, d); callback(userdata, buf); break; + case QUIRK_ATTR_USE_VELOCITY_AVERAGING: + snprintf(buf, sizeof(buf), "%s=1", name); + callback(userdata, buf); + break; } }