On Fri, Mar 02, 2018 at 09:21:34PM +0300, Konstantin Kharlamov wrote: > On 02.03.2018 03:20, Peter Hutterer wrote: > > There, now I have your attention, right? :) > > > > TLDR: input_defuzz_abs_event() produces pointer jumps at certain slow > > movement speeds and I don't know what to do about it. > > > > While dealing with pointer jitter issues in libinput I stumbled into an > > issue with how the fuzz value in the kernel is handled during > > input_defuzz_abs_event(). Specifically, the response is nonlinear and can > > lead to jumpy pointer movement for deltas d = fuzz and d = fuzz * 2. > > > > Note, this bug affects a moving pointer, not a stationary one. For that the > > defuzzing works as intended. Let's assume that with a perceived-constant > > finger motion speed, you'll get deltas in the range (fuzz * 2) ± 3. > > > > input_defuzz_abs_event() returns: > > d = fuzz * 2 - 3 → value returned: fuzz - 1 > > d = fuzz * 2 - 2 → value returned: fuzz - 1 > > d = fuzz * 2 → value returned: fuzz * 2 > > d = fuzz * 2 + 1 → value returned: fuzz * 2 + 1 > > d = fuzz * 2 + 2 → value returned: fuzz * 2 + 2 > > > > There's another jump at the fuzz ± 2 range. In concrete numbers for a fuzz > > of 8, input deltas result in values: > > > > d = 6 → value 1 > > d = 7 → value 1 > > d = 8 → value 4 > > d = 9 → value 4 > > ... > > d = 14 → value 7 > > d = 15 → value 7 > > d = 16 → value 16 > > d = 17 → value 17 > > d = 18 → value 18 > > > > i.e. at the fuzz and fuzz * 2 points we see a jump of approx size fuzz/2 and > > fuzz, respectively. These are integer divisons, so some variance is expected. > > Obviously the numbers change for higher fuzz values but 8 seems to be the > > most common one. > > > > A few more details and a python script to recreate this and play around with > > it: https://bugs.freedesktop.org/show_bug.cgi?id=105303 > > > > In real terms, this means that a pointer moving at a percieved-constant > > speed will provide deltas of [7, 7, 16, 7, 16, 16, 7, 16, 7]. And if we were > > to rely on the fuzz in userspace as hint for our hysteresis, we'd end up > > filtering the 7 values but letting the 16 values pass through. This gives us > > pointer jumps. > > > > Those jumps happen right at the slow speed where we're moving slow enough to > > notice them. Ironically, slowing down to check what just happened will not > > reproduce the problem. The defuzzed value is used as 'old' value for the > > algorithm, so there's a feedback loop as well. So it's very hard to > > reproduce consistently, you cannot really get a [7, 16, 7, 16] motion with > > human input. But it's like bad kerning, once you see it you cannot unsee it > > :) > > > > I'm a bit out of ideas on how to deal with this: > > 1) improve the algorithm in the kernel so the response is more linear > > 2) figure out a way how to undo the kernel defuzz in userspace and > > do hysteresis based on the reconstructed raw value > > 3) provide some way of disabling in-kernel hysteres while leaving fuzz set > > 4) force the fuzz to 0, while remembering what it should be > > > > Neither of them is ideal, but 4 seems the best, with caveats. > > > > 1) can remove (some of) the jumps but since we already get processed > > coordinates, doing the correct thing in libinput is harder > > Another contra to 1 would be: userspace is easier to debug. > > > 2) possibly possible, but will be lossy or inaccurate > > 3) would require some new ioctl and per-client behaviour. not ideal > > 4) this one is both the easiest and messiest. The approach would be: > > * a udev rule extracts the fuzz value into a AXIS_FUZZ=$fuzz property > > * use EVIOCSABS to set the fuzz to 0 (thus disabling kernel defuzzing), > > * have libinput init the hysteresis based on AXIS_FUZZ > > * pray that no other input-handling clients relies on kernel fuzzing > > because we just changed the kernel device > > > > Any suggestions on how to handle this would be appreciated. > > I'm voting for the 4th option too. I'm wondering if there's a way to find > default fuzz values after they have been set to zero, i.e. to use them after > X11/compositor restart/crash. > > Do I correctly understand though that the fuzz value is used by kernel to do > some hysteresis algo on its own (i.e. the input_defuzz_abs_event())? correct > If it > is, I think it'd be better to remove this algorithm from the kernel > whatsoever — it'd allow to not even force fuzz values to zero (well, at > least not for patched kernels). as usual, removing something from the kernel is tricky and risky, who knows if anything relies on that defuzzing :) Preliminary patch set for 4) is available here: https://lists.freedesktop.org/archives/wayland-devel/2018-March/037299.html Cheers, Peter -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html