diff --git a/0001-filter-reduce-deceleration-to-minimal-speeds-only.patch b/0001-filter-reduce-deceleration-to-minimal-speeds-only.patch new file mode 100644 index 0000000..a0f77b0 --- /dev/null +++ b/0001-filter-reduce-deceleration-to-minimal-speeds-only.patch @@ -0,0 +1,40 @@ +From 6984628d6acf4695c24261c094def44ff37337be Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Fri, 12 Jun 2015 15:31:56 +1000 +Subject: [PATCH libinput 1/9] filter: reduce deceleration to minimal speeds + only + +Deceleration at low speeds is intended to enhance precision when moving the +pointer slowly. However, the adaptive deceleration we used was badly +calibrated, at slow-but-normal speeds the pointer became too slow to manouver. + +We don't want to drop deceleration completely, the subpixel precision it +provides is useful. And it also helps those that can't move a 1000dpi mouse by +exactly one unit. + +Make the adaptive deceleration steeper so it only kicks in at extremely slow +motions and defaults to 1 at anything resembling normal movement (i.e. pointer +moves like the physical device does). + +Signed-off-by: Peter Hutterer +Reviewed-by: Hans de Goede +--- + src/filter.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/filter.c b/src/filter.c +index a4142e9..69f78b1 100644 +--- a/src/filter.c ++++ b/src/filter.c +@@ -386,7 +386,7 @@ pointer_accel_profile_linear(struct motion_filter *filter, + const double threshold = accel_filter->threshold; /* units/ms */ + const double incline = accel_filter->incline; + +- s1 = min(1, 0.3 + speed_in * 4); ++ s1 = min(1, 0.3 + speed_in * 10); + s2 = 1 + (speed_in - threshold) * incline; + + return min(max_accel, s2 > 1 ? s2 : s1); +-- +2.4.3 + diff --git a/0002-evdev-read-dpi-before-evdev_configure_device.patch b/0002-evdev-read-dpi-before-evdev_configure_device.patch new file mode 100644 index 0000000..6721db6 --- /dev/null +++ b/0002-evdev-read-dpi-before-evdev_configure_device.patch @@ -0,0 +1,37 @@ +From d1639c88ce2a710ab9b771766f473a72b66100db Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Fri, 19 Jun 2015 16:01:34 +1000 +Subject: [PATCH libinput 2/9] evdev: read dpi before evdev_configure_device + +So we can use to set up accel during evdev_configure_device. + +Signed-off-by: Peter Hutterer +--- + src/evdev.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/evdev.c b/src/evdev.c +index 7e1e5c8..2644b76 100644 +--- a/src/evdev.c ++++ b/src/evdev.c +@@ -2083,6 +2083,8 @@ evdev_device_create(struct libinput_seat *seat, + device->scroll.wheel_click_angle = + evdev_read_wheel_click_prop(device); + device->model = evdev_read_model(device); ++ device->dpi = evdev_read_dpi_prop(device); ++ + /* at most 5 SYN_DROPPED log-messages per 30s */ + ratelimit_init(&device->syn_drop_limit, 30ULL * 1000, 5); + +@@ -2093,8 +2095,6 @@ evdev_device_create(struct libinput_seat *seat, + if (evdev_configure_device(device) == -1) + goto err; + +- device->dpi = evdev_read_dpi_prop(device); +- + if (device->seat_caps == 0) { + unhandled_device = 1; + goto err; +-- +2.4.3 + diff --git a/0003-evdev-log-device-s-DPI-setting-if-any.patch b/0003-evdev-log-device-s-DPI-setting-if-any.patch new file mode 100644 index 0000000..481f5d7 --- /dev/null +++ b/0003-evdev-log-device-s-DPI-setting-if-any.patch @@ -0,0 +1,30 @@ +From 6dbfd81e26a9adff5b07398ff7e588683e3e6bf6 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Tue, 23 Jun 2015 12:41:57 +1000 +Subject: [PATCH libinput 3/9] evdev: log device's DPI setting if any + +Makes debugging things easier. + +Signed-off-by: Peter Hutterer +--- + src/evdev.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/evdev.c b/src/evdev.c +index 2644b76..67843db 100644 +--- a/src/evdev.c ++++ b/src/evdev.c +@@ -1496,6 +1496,10 @@ evdev_read_dpi_prop(struct evdev_device *device) + DEFAULT_MOUSE_DPI); + dpi = DEFAULT_MOUSE_DPI; + } ++ log_info(libinput, ++ "Device '%s' set to %d DPI\n", ++ device->devname, ++ dpi); + } + + return dpi; +-- +2.4.3 + diff --git a/0004-evdev-move-posting-a-trackpoint-scroll-event-into-a-.patch b/0004-evdev-move-posting-a-trackpoint-scroll-event-into-a-.patch new file mode 100644 index 0000000..aca4114 --- /dev/null +++ b/0004-evdev-move-posting-a-trackpoint-scroll-event-into-a-.patch @@ -0,0 +1,59 @@ +From f9503763adbaef8fc7220e2da782917cea8803ee Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Fri, 26 Jun 2015 09:27:20 +1000 +Subject: [PATCH libinput 4/9] evdev: move posting a trackpoint scroll event + into a helper + +Signed-off-by: Peter Hutterer +--- + src/evdev.c | 27 +++++++++++++++++++-------- + 1 file changed, 19 insertions(+), 8 deletions(-) + +diff --git a/src/evdev.c b/src/evdev.c +index 67843db..b2595d4 100644 +--- a/src/evdev.c ++++ b/src/evdev.c +@@ -253,6 +253,23 @@ normalize_delta(struct evdev_device *device, + normalized->y = delta->y * DEFAULT_MOUSE_DPI / (double)device->dpi; + } + ++static inline bool ++evdev_post_trackpoint_scroll(struct evdev_device *device, ++ struct normalized_coords unaccel, ++ uint64_t time) ++{ ++ if (device->scroll.method != LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN || ++ !hw_is_key_down(device, device->scroll.button)) ++ return false; ++ ++ if (device->scroll.button_scroll_active) ++ evdev_post_scroll(device, time, ++ LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS, ++ &unaccel); ++ ++ return true; ++} ++ + static void + evdev_flush_pending_event(struct evdev_device *device, uint64_t time) + { +@@ -275,14 +292,8 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time) + device->rel.y = 0; + + /* Use unaccelerated deltas for pointing stick scroll */ +- if (device->scroll.method == LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN && +- hw_is_key_down(device, device->scroll.button)) { +- if (device->scroll.button_scroll_active) +- evdev_post_scroll(device, time, +- LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS, +- &unaccel); +- break; +- } ++ if (evdev_post_trackpoint_scroll(device, unaccel, time)) ++ break; + + /* Apply pointer acceleration. */ + accel = filter_dispatch(device->pointer.filter, +-- +2.4.3 + diff --git a/0005-tools-don-t-drop-the-accelerated-deltas-in-ptraccel-.patch b/0005-tools-don-t-drop-the-accelerated-deltas-in-ptraccel-.patch new file mode 100644 index 0000000..f91623f --- /dev/null +++ b/0005-tools-don-t-drop-the-accelerated-deltas-in-ptraccel-.patch @@ -0,0 +1,40 @@ +From 03a02107c597fd1b3e738002431c35bb2057b7ce Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Fri, 26 Jun 2015 10:00:24 +1000 +Subject: [PATCH libinput 5/9] tools: don't drop the accelerated deltas in + ptraccel-debug + +Leftover from the initial (out-of-tree) implementation where we updated motion +in place. That hasn't been true since libinput switched to type-safe +coordinates. + +Signed-off-by: Peter Hutterer +--- + tools/ptraccel-debug.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tools/ptraccel-debug.c b/tools/ptraccel-debug.c +index 8b800ee..335781b 100644 +--- a/tools/ptraccel-debug.c ++++ b/tools/ptraccel-debug.c +@@ -95,7 +95,7 @@ print_ptraccel_movement(struct motion_filter *filter, + motion.y = 0; + time += 12; /* pretend 80Hz data */ + +- filter_dispatch(filter, &motion, NULL, time); ++ motion = filter_dispatch(filter, &motion, NULL, time); + + printf("%d %.3f %.3f\n", i, motion.x, dx); + +@@ -129,7 +129,7 @@ print_ptraccel_sequence(struct motion_filter *filter, + motion.y = 0; + time += 12; /* pretend 80Hz data */ + +- filter_dispatch(filter, &motion, NULL, time); ++ motion = filter_dispatch(filter, &motion, NULL, time); + + printf("%d %.3f %.3f\n", i, motion.x, *dx); + } +-- +2.4.3 + diff --git a/0006-filter-use-a-tmp-variable-for-the-accel-factor.patch b/0006-filter-use-a-tmp-variable-for-the-accel-factor.patch new file mode 100644 index 0000000..440a5d3 --- /dev/null +++ b/0006-filter-use-a-tmp-variable-for-the-accel-factor.patch @@ -0,0 +1,35 @@ +From 07ffabc58c1f967e1efe0b593135e835aa5deed4 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Tue, 23 Jun 2015 12:45:55 +1000 +Subject: [PATCH libinput 6/9] filter: use a tmp variable for the accel factor + +No real effect, just makes the diff for debugging printfs smaller. + +Signed-off-by: Peter Hutterer +--- + src/filter.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/filter.c b/src/filter.c +index 69f78b1..1e05782 100644 +--- a/src/filter.c ++++ b/src/filter.c +@@ -385,11 +385,14 @@ pointer_accel_profile_linear(struct motion_filter *filter, + const double max_accel = accel_filter->accel; /* unitless factor */ + const double threshold = accel_filter->threshold; /* units/ms */ + const double incline = accel_filter->incline; ++ double factor; + + s1 = min(1, 0.3 + speed_in * 10); + s2 = 1 + (speed_in - threshold) * incline; + +- return min(max_accel, s2 > 1 ? s2 : s1); ++ factor = min(max_accel, s2 > 1 ? s2 : s1); ++ ++ return factor; + } + + double +-- +2.4.3 + diff --git a/0007-Drop-motion-normalization-of-unaccelerated-deltas.patch b/0007-Drop-motion-normalization-of-unaccelerated-deltas.patch new file mode 100644 index 0000000..5ceaead --- /dev/null +++ b/0007-Drop-motion-normalization-of-unaccelerated-deltas.patch @@ -0,0 +1,289 @@ +From 753e5eb654a5da96b5cb42e5d612380adac7229f Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Fri, 26 Jun 2015 09:07:24 +1000 +Subject: [PATCH libinput 7/9] Drop motion normalization of unaccelerated + deltas + +This simply doesn't work for low-dpi mice. Normalizing a 400dpi mouse to a +1000dpi mouse forces a minimum movement of 2.5 units and the resulting pixel +jumps. It is impossible for the caller to detect whether the jump was caused +by a single motion or multiple motion events. + +This is technically an API break, but not really. + +The accelerated data was already relatively meaningless, even if normalized as +the data did not correspond predictably to any input motion (unless you know +the implementation acceleration function in the caller). So we can drop the +mention from there without expecting any ill effects in the caller. + +The unaccelerated data was useless for low-dpi mice and could only be used to +measure the physical distance of the mouse movement - something not used in +any caller we're aware of (if needed, we can add that functionality as a +separate call). Dropping motion normalization for unaccelerated deltas also +restores true dpi capabilities to users of that API, mostly games that want to +make use of high-dpi mice. + +This is a simplified patch, the normalization is still in place for most of +libinput, it merely carries the original coordinates in the event itself. + +In the case of touchpads, the coordinates are unnormalized into the x-axis +coordinate space as per the documentation. + +Signed-off-by: Peter Hutterer +--- + doc/normalization-of-relative-motion.dox | 31 +++++++++++++++++++++++++++---- + src/evdev-mt-touchpad-gestures.c | 8 ++++++-- + src/evdev-mt-touchpad.h | 15 +++++++++++++++ + src/evdev.c | 5 ++++- + src/libinput-private.h | 2 +- + src/libinput.c | 10 +++++----- + src/libinput.h | 26 ++++++++++++++------------ + 7 files changed, 72 insertions(+), 25 deletions(-) + +diff --git a/doc/normalization-of-relative-motion.dox b/doc/normalization-of-relative-motion.dox +index aaa1735..dd5d39b 100644 +--- a/doc/normalization-of-relative-motion.dox ++++ b/doc/normalization-of-relative-motion.dox +@@ -12,10 +12,33 @@ physical movement or 10 millimeters, depending on the sensor. This + affects pointer acceleration in libinput and interpretation of relative + coordinates in callers. + +-libinput normalizes all relative input to a physical resolution of +-1000dpi, the same delta from two different devices thus represents the +-same physical movement of those two devices (within sensor error +-margins). ++libinput does partial normalization of relative input. For devices with a ++resolution of 1000dpi and higher, motion events are normalized to a default ++of 1000dpi before pointer acceleration is applied. As a result, devices with ++1000dpi and above feel the same. ++ ++Devices below 1000dpi are not normalized (normalization of a 1-device unit ++movement on a 400dpi mouse would cause a 2.5 pixel movement). Instead, ++libinput applies a dpi-dependent acceleration function. At low speeds, a ++1-device unit movement usually translates into a 1-pixel movements. As the ++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 ++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 ++into account results in uneven motion. ++ ++libinput scales unaccelerated touchpad motion do the resolution of the ++touchpad's x axis, i.e. the unaccelerated value for the y axis is: ++ y = (x / resolution_x) * resolution_y ++ ++@section Setting custom DPI settings + + Devices usually do not advertise their resolution and libinput relies on + the udev property MOUSE_DPI for this information. This property is usually +diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c +index 328a744..e85a9d7 100644 +--- a/src/evdev-mt-touchpad-gestures.c ++++ b/src/evdev-mt-touchpad-gestures.c +@@ -91,6 +91,7 @@ static void + tp_gesture_post_pointer_motion(struct tp_dispatch *tp, uint64_t time) + { + struct normalized_coords delta, unaccel; ++ struct device_float_coords raw; + + /* When a clickpad is clicked, combine motion of all active touches */ + if (tp->buttons.is_clickpad && tp->buttons.state) +@@ -101,8 +102,11 @@ tp_gesture_post_pointer_motion(struct tp_dispatch *tp, uint64_t time) + delta = tp_filter_motion(tp, &unaccel, time); + + if (!normalized_is_zero(delta) || !normalized_is_zero(unaccel)) { +- pointer_notify_motion(&tp->device->base, time, +- &delta, &unaccel); ++ raw = tp_unnormalize_for_xaxis(tp, unaccel); ++ pointer_notify_motion(&tp->device->base, ++ time, ++ &delta, ++ &raw); + } + } + +diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h +index 9357969..08c1732 100644 +--- a/src/evdev-mt-touchpad.h ++++ b/src/evdev-mt-touchpad.h +@@ -316,6 +316,21 @@ tp_normalize_delta(struct tp_dispatch *tp, struct device_float_coords delta) + return normalized; + } + ++/** ++ * Takes a dpi-normalized set of coordinates, returns a set of coordinates ++ * in the x-axis' coordinate space. ++ */ ++static inline struct device_float_coords ++tp_unnormalize_for_xaxis(struct tp_dispatch *tp, struct normalized_coords delta) ++{ ++ struct device_float_coords raw; ++ ++ raw.x = delta.x / tp->accel.x_scale_coeff; ++ raw.y = delta.y / tp->accel.x_scale_coeff; /* <--- not a typo */ ++ ++ return raw; ++} ++ + struct normalized_coords + tp_get_delta(struct tp_touch *t); + +diff --git a/src/evdev.c b/src/evdev.c +index b2595d4..a5f1d47 100644 +--- a/src/evdev.c ++++ b/src/evdev.c +@@ -280,6 +280,7 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time) + struct libinput_seat *seat = base->seat; + struct normalized_coords accel, unaccel; + struct device_coords point; ++ struct device_float_coords raw; + + slot = device->mt.slot; + +@@ -288,6 +289,8 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time) + return; + case EVDEV_RELATIVE_MOTION: + normalize_delta(device, &device->rel, &unaccel); ++ raw.x = device->rel.x; ++ raw.y = device->rel.y; + device->rel.x = 0; + device->rel.y = 0; + +@@ -304,7 +307,7 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time) + if (normalized_is_zero(accel) && normalized_is_zero(unaccel)) + break; + +- pointer_notify_motion(base, time, &accel, &unaccel); ++ pointer_notify_motion(base, time, &accel, &raw); + break; + case EVDEV_ABSOLUTE_MT_DOWN: + if (!(device->seat_caps & EVDEV_DEVICE_TOUCH)) +diff --git a/src/libinput-private.h b/src/libinput-private.h +index a7c8838..2f94597 100644 +--- a/src/libinput-private.h ++++ b/src/libinput-private.h +@@ -319,7 +319,7 @@ void + pointer_notify_motion(struct libinput_device *device, + uint64_t time, + const struct normalized_coords *delta, +- const struct normalized_coords *unaccel); ++ const struct device_float_coords *raw); + + void + pointer_notify_motion_absolute(struct libinput_device *device, +diff --git a/src/libinput.c b/src/libinput.c +index 7a097c0..a6bd079 100644 +--- a/src/libinput.c ++++ b/src/libinput.c +@@ -96,7 +96,7 @@ struct libinput_event_pointer { + struct libinput_event base; + uint32_t time; + struct normalized_coords delta; +- struct normalized_coords delta_unaccel; ++ struct device_float_coords delta_raw; + struct device_coords absolute; + struct discrete_coords discrete; + uint32_t button; +@@ -339,7 +339,7 @@ libinput_event_pointer_get_dx_unaccelerated( + 0, + LIBINPUT_EVENT_POINTER_MOTION); + +- return event->delta_unaccel.x; ++ return event->delta_raw.x; + } + + LIBINPUT_EXPORT double +@@ -351,7 +351,7 @@ libinput_event_pointer_get_dy_unaccelerated( + 0, + LIBINPUT_EVENT_POINTER_MOTION); + +- return event->delta_unaccel.y; ++ return event->delta_raw.y; + } + + LIBINPUT_EXPORT double +@@ -1130,7 +1130,7 @@ void + pointer_notify_motion(struct libinput_device *device, + uint64_t time, + const struct normalized_coords *delta, +- const struct normalized_coords *unaccel) ++ const struct device_float_coords *raw) + { + struct libinput_event_pointer *motion_event; + +@@ -1144,7 +1144,7 @@ pointer_notify_motion(struct libinput_device *device, + *motion_event = (struct libinput_event_pointer) { + .time = time, + .delta = *delta, +- .delta_unaccel = *unaccel, ++ .delta_raw = *raw, + }; + + post_device_event(device, time, +diff --git a/src/libinput.h b/src/libinput.h +index 0d3200f..e76fa9a 100644 +--- a/src/libinput.h ++++ b/src/libinput.h +@@ -460,8 +460,8 @@ libinput_event_pointer_get_time(struct libinput_event_pointer *event); + * If a device employs pointer acceleration, the delta returned by this + * function is the accelerated delta. + * +- * Relative motion deltas are normalized to represent those of a device with +- * 1000dpi resolution. See @ref motion_normalization for more details. ++ * Relative motion deltas are to be interpreted as pixel movement of a ++ * standardized mouse. See @ref motion_normalization for more details. + * + * @note It is an application bug to call this function for events other than + * @ref LIBINPUT_EVENT_POINTER_MOTION. +@@ -481,8 +481,8 @@ libinput_event_pointer_get_dx(struct libinput_event_pointer *event); + * If a device employs pointer acceleration, the delta returned by this + * function is the accelerated delta. + * +- * Relative motion deltas are normalized to represent those of a device with +- * 1000dpi resolution. See @ref motion_normalization for more details. ++ * Relative motion deltas are to be interpreted as pixel movement of a ++ * standardized mouse. See @ref motion_normalization for more details. + * + * @note It is an application bug to call this function for events other than + * @ref LIBINPUT_EVENT_POINTER_MOTION. +@@ -499,10 +499,11 @@ libinput_event_pointer_get_dy(struct libinput_event_pointer *event); + * current event. For pointer events that are not of type @ref + * LIBINPUT_EVENT_POINTER_MOTION, this function returns 0. + * +- * Relative unaccelerated motion deltas are normalized to represent those of a +- * device with 1000dpi resolution. See @ref motion_normalization for more +- * details. Note that unaccelerated events are not equivalent to 'raw' events +- * as read from the device. ++ * Relative unaccelerated motion deltas are raw device coordinates. ++ * Note that these coordinates are subject to the device's native ++ * resolution. Touchpad coordinates represent raw device coordinates in the ++ * X resolution of the touchpad. See @ref motion_normalization for more ++ * details. + * + * @note It is an application bug to call this function for events other than + * @ref LIBINPUT_EVENT_POINTER_MOTION. +@@ -520,10 +521,11 @@ libinput_event_pointer_get_dx_unaccelerated( + * current event. For pointer events that are not of type @ref + * LIBINPUT_EVENT_POINTER_MOTION, this function returns 0. + * +- * Relative unaccelerated motion deltas are normalized to represent those of a +- * device with 1000dpi resolution. See @ref motion_normalization for more +- * details. Note that unaccelerated events are not equivalent to 'raw' events +- * as read from the device. ++ * Relative unaccelerated motion deltas are raw device coordinates. ++ * Note that these coordinates are subject to the device's native ++ * resolution. Touchpad coordinates represent raw device coordinates in the ++ * X resolution of the touchpad. See @ref motion_normalization for more ++ * details. + * + * @note It is an application bug to call this function for events other than + * @ref LIBINPUT_EVENT_POINTER_MOTION. +-- +2.4.3 + diff --git a/0008-filter-pass-the-DPI-to-the-acceleration-filter.patch b/0008-filter-pass-the-DPI-to-the-acceleration-filter.patch new file mode 100644 index 0000000..ec494cf --- /dev/null +++ b/0008-filter-pass-the-DPI-to-the-acceleration-filter.patch @@ -0,0 +1,122 @@ +From 415bc6d956e9c4836f20e661e3ee77d2adfb1cd5 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Fri, 19 Jun 2015 16:03:42 +1000 +Subject: [PATCH libinput 8/9] filter: pass the DPI to the acceleration filter + +Currently unused, but store the ratio of DPI:default DPI for later use. + +Signed-off-by: Peter Hutterer +--- + src/evdev.c | 3 ++- + src/evdev.h | 3 --- + src/filter.c | 7 ++++++- + src/filter.h | 3 ++- + src/libinput-util.h | 3 +++ + tools/ptraccel-debug.c | 3 ++- + 6 files changed, 15 insertions(+), 7 deletions(-) + +diff --git a/src/evdev.c b/src/evdev.c +index a5f1d47..b98b47a 100644 +--- a/src/evdev.c ++++ b/src/evdev.c +@@ -1409,7 +1409,8 @@ int + evdev_device_init_pointer_acceleration(struct evdev_device *device, + accel_profile_func_t profile) + { +- device->pointer.filter = create_pointer_accelerator_filter(profile); ++ device->pointer.filter = create_pointer_accelerator_filter(profile, ++ device->dpi); + if (!device->pointer.filter) + return -1; + +diff --git a/src/evdev.h b/src/evdev.h +index 566b0a4..b58e021 100644 +--- a/src/evdev.h ++++ b/src/evdev.h +@@ -36,9 +36,6 @@ + #include "timer.h" + #include "filter.h" + +-/* The HW DPI rate we normalize to before calculating pointer acceleration */ +-#define DEFAULT_MOUSE_DPI 1000 +- + /* + * The constant (linear) acceleration factor we use to normalize trackpoint + * deltas before calculating pointer acceleration. +diff --git a/src/filter.c b/src/filter.c +index 1e05782..04dd2b9 100644 +--- a/src/filter.c ++++ b/src/filter.c +@@ -111,6 +111,8 @@ struct pointer_accelerator { + double threshold; /* units/ms */ + double accel; /* unitless factor */ + double incline; /* incline of the function */ ++ ++ double dpi_factor; + }; + + static void +@@ -346,7 +348,8 @@ struct motion_filter_interface accelerator_interface = { + }; + + struct motion_filter * +-create_pointer_accelerator_filter(accel_profile_func_t profile) ++create_pointer_accelerator_filter(accel_profile_func_t profile, ++ int dpi) + { + struct pointer_accelerator *filter; + +@@ -369,6 +372,8 @@ create_pointer_accelerator_filter(accel_profile_func_t profile) + filter->accel = DEFAULT_ACCELERATION; + filter->incline = DEFAULT_INCLINE; + ++ filter->dpi = dpi; ++ + return &filter->base; + } + +diff --git a/src/filter.h b/src/filter.h +index de94997..64a8b50 100644 +--- a/src/filter.h ++++ b/src/filter.h +@@ -58,7 +58,8 @@ typedef double (*accel_profile_func_t)(struct motion_filter *filter, + uint64_t time); + + struct motion_filter * +-create_pointer_accelerator_filter(accel_profile_func_t filter); ++create_pointer_accelerator_filter(accel_profile_func_t filter, ++ int dpi); + + /* + * Pointer acceleration profiles. +diff --git a/src/libinput-util.h b/src/libinput-util.h +index 4f73ad4..bb4834e 100644 +--- a/src/libinput-util.h ++++ b/src/libinput-util.h +@@ -37,6 +37,9 @@ + #define VENDOR_ID_APPLE 0x5ac + #define VENDOR_ID_WACOM 0x56a + ++/* The HW DPI rate we normalize to before calculating pointer acceleration */ ++#define DEFAULT_MOUSE_DPI 1000 ++ + void + set_logging_enabled(int enabled); + +diff --git a/tools/ptraccel-debug.c b/tools/ptraccel-debug.c +index 335781b..9fdb4cd 100644 +--- a/tools/ptraccel-debug.c ++++ b/tools/ptraccel-debug.c +@@ -199,7 +199,8 @@ main(int argc, char **argv) + OPT_SPEED, + }; + +- filter = create_pointer_accelerator_filter(pointer_accel_profile_linear); ++ filter = create_pointer_accelerator_filter(pointer_accel_profile_linear, ++ 1000); + assert(filter != NULL); + + while (1) { +-- +2.4.3 + diff --git a/0009-filter-add-a-custom-low-dpi-acceleration.patch b/0009-filter-add-a-custom-low-dpi-acceleration.patch new file mode 100644 index 0000000..2f367d8 --- /dev/null +++ b/0009-filter-add-a-custom-low-dpi-acceleration.patch @@ -0,0 +1,170 @@ +From 348401a5de950314faadfdd69d160cdeda1362fa Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Tue, 23 Jun 2015 12:45:16 +1000 +Subject: [PATCH libinput 9/9] filter: add a custom low-dpi acceleration + +Motion normalization does not work well for devices below the default 1000dpi +rate. A 400dpi mouse's minimum movement generates a 2.5 normalized motion, +causing it to skip pixels at low speeds even when unaccelerated. + +Likewise, we don't want 1000dpi mice to be normalized to a 400dpi mouse, it +feels sluggish even at higher acceleration speeds. +Instead, add a custom acceleration method for lower-dpi mice. At low-speeds, +one device unit results in a one-pixel movement. Depending on the DPI factor, +the acceleration kicks in earlier and goes to higher acceleration so faster +movements with a low-dpi mouse feel approximately the same as the same +movement on a higher-dpi mouse. + +https://bugzilla.redhat.com/show_bug.cgi?id=1231304 + +Signed-off-by: Peter Hutterer +--- + src/evdev.c | 17 ++++++++++++++--- + src/filter.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++------ + src/filter.h | 5 +++++ + 3 files changed, 69 insertions(+), 9 deletions(-) + +diff --git a/src/evdev.c b/src/evdev.c +index b98b47a..1edf93f 100644 +--- a/src/evdev.c ++++ b/src/evdev.c +@@ -1823,6 +1823,19 @@ evdev_configure_mt_device(struct evdev_device *device) + return 0; + } + ++static inline int ++evdev_init_accel(struct evdev_device *device) ++{ ++ accel_profile_func_t profile; ++ ++ if (device->dpi < DEFAULT_MOUSE_DPI) ++ profile = pointer_accel_profile_linear_low_dpi; ++ else ++ profile = pointer_accel_profile_linear; ++ ++ return evdev_device_init_pointer_acceleration(device, profile); ++} ++ + static int + evdev_configure_device(struct evdev_device *device) + { +@@ -1914,9 +1927,7 @@ evdev_configure_device(struct evdev_device *device) + udev_tags & EVDEV_UDEV_TAG_POINTINGSTICK) { + if (libevdev_has_event_code(evdev, EV_REL, REL_X) && + libevdev_has_event_code(evdev, EV_REL, REL_Y) && +- evdev_device_init_pointer_acceleration( +- device, +- pointer_accel_profile_linear) == -1) ++ evdev_init_accel(device) == -1) + return -1; + + device->seat_caps |= EVDEV_DEVICE_POINTER; +diff --git a/src/filter.c b/src/filter.c +index 04dd2b9..35449f5 100644 +--- a/src/filter.c ++++ b/src/filter.c +@@ -264,8 +264,16 @@ accelerator_filter(struct motion_filter *filter, + double velocity; /* units/ms */ + double accel_value; /* unitless factor */ + struct normalized_coords accelerated; ++ struct normalized_coords unnormalized; ++ double dpi_factor = accel->dpi_factor; + +- feed_trackers(accel, unaccelerated, time); ++ /* For low-dpi mice, use device units, everything else uses ++ 1000dpi normalized */ ++ dpi_factor = min(1.0, dpi_factor); ++ 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, +@@ -273,10 +281,10 @@ accelerator_filter(struct motion_filter *filter, + accel->last_velocity, + time); + +- accelerated.x = accel_value * unaccelerated->x; +- accelerated.y = accel_value * unaccelerated->y; ++ accelerated.x = accel_value * unnormalized.x; ++ accelerated.y = accel_value * unnormalized.y; + +- accel->last = *unaccelerated; ++ accel->last = unnormalized; + + accel->last_velocity = velocity; + +@@ -372,15 +380,51 @@ create_pointer_accelerator_filter(accel_profile_func_t profile, + filter->accel = DEFAULT_ACCELERATION; + filter->incline = DEFAULT_INCLINE; + +- filter->dpi = dpi; ++ 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. ++ * The threshold/max accel depends on the DPI, the smaller the DPI the ++ * earlier we accelerate and the higher the maximum acceleration is. Result: ++ * at low speeds we get pixel-precision, at high speeds we get approx. the ++ * same movement as a high-dpi mouse. ++ * ++ * Note: data fed to this function is in device units, not normalized. ++ */ ++double ++pointer_accel_profile_linear_low_dpi(struct motion_filter *filter, ++ void *data, ++ double speed_in, /* in device units */ ++ 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 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); ++ s2 = 1 + (speed_in - threshold * dpi_factor) * incline; ++ ++ factor = min(max_accel, s2 > 1 ? s2 : s1); ++ ++ return factor; ++} ++ + double + pointer_accel_profile_linear(struct motion_filter *filter, + void *data, +- double speed_in, ++ double speed_in, /* 1000-dpi normalized */ + uint64_t time) + { + struct pointer_accelerator *accel_filter = +diff --git a/src/filter.h b/src/filter.h +index 64a8b50..617fab1 100644 +--- a/src/filter.h ++++ b/src/filter.h +@@ -66,6 +66,11 @@ create_pointer_accelerator_filter(accel_profile_func_t filter, + */ + + double ++pointer_accel_profile_linear_low_dpi(struct motion_filter *filter, ++ void *data, ++ double speed_in, ++ uint64_t time); ++double + pointer_accel_profile_linear(struct motion_filter *filter, + void *data, + double speed_in, +-- +2.4.3 + diff --git a/libinput.spec b/libinput.spec index 8cafea1..58055d6 100644 --- a/libinput.spec +++ b/libinput.spec @@ -5,7 +5,7 @@ Name: libinput Version: 0.18.0 -Release: 3%{?gitdate:.%{gitdate}git%{gitversion}}%{?dist} +Release: 4%{?gitdate:.%{gitdate}git%{gitversion}}%{?dist} Summary: Input device library License: MIT @@ -22,6 +22,18 @@ Patch01: 0001-touchpad-only-send-most-recent-edge-delta-when-trigg.patch Patch02: 0001-touchpad-reduce-edge-scroll-motion-threshold-to-3mm.patch Patch03: 0001-touchpad-fix-stuck-finger-after-a-click.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1227039 +Patch04: 0001-filter-reduce-deceleration-to-minimal-speeds-only.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1231304 +Patch05: 0002-evdev-read-dpi-before-evdev_configure_device.patch +Patch06: 0003-evdev-log-device-s-DPI-setting-if-any.patch +Patch07: 0004-evdev-move-posting-a-trackpoint-scroll-event-into-a-.patch +Patch08: 0005-tools-don-t-drop-the-accelerated-deltas-in-ptraccel-.patch +Patch09: 0006-filter-use-a-tmp-variable-for-the-accel-factor.patch +Patch10: 0007-Drop-motion-normalization-of-unaccelerated-deltas.patch +Patch11: 0008-filter-pass-the-DPI-to-the-acceleration-filter.patch +Patch12: 0009-filter-add-a-custom-low-dpi-acceleration.patch + BuildRequires: git BuildRequires: autoconf automake libtool pkgconfig BuildRequires: libevdev-devel @@ -98,6 +110,11 @@ find $RPM_BUILD_ROOT -name '*.la' -delete %changelog +* Mon Jun 29 2015 Peter Hutterer 0.18.0-4 +- Steepen deceleration curve to get better 1:1 movement on slow speeds + (#1231304) +- Provide custom accel method for <1000dpi mice (#1227039) + * Thu Jun 25 2015 Peter Hutterer 0.18.0-3 - Fix stuck finger after a clickpad click on resolutionless touchpads