On Tue, Feb 20, 2018 at 08:58:33PM +0300, Konstantin Kharlamov wrote: > On 20.02.2018 17:31, Konstantin Kharlamov wrote: > > On 20.02.2018 13:44, Konstantin Kharlamov wrote: > > > On 20.02.2018 09:34, Peter Hutterer wrote: > > > > On Sun, Feb 18, 2018 at 11:14:55PM +0300, Konstantin Kharlamov wrote: > > > > > +static inline void > > > > > +tp_detect_wobbling(struct tp_dispatch *tp, int x_diff, uint64_t time) > > > > > +{ > > > > > + if (tp->hysteresis.enabled) > > > > > + return; > > > > > + > > > > > + /* Idea: if we got a tuple of *very* quick moves like > > > > > {Left, Right, Left}, or > > > > > + * {Right, Left, Right}, it means touchpad jitters > > > > > since no human supposed to > > > > > + * be able to move like that within thresholds > > > > > + * > > > > > + * Algo: we encode left moves as zeroes, and right as > > > > > ones. We also drop the > > > > > + * array to all zeroes when contraints are not > > > > > satisfied. Then we search for > > > > > + * the pattern {1,0,1}. It can't match {Left, Right, > > > > > Left}, but it does match > > > > > + * {Left, Right, Left, Right}, so it's okay. > > > > > + */ > > > > > > > > the interesting bit here will be whether there are touchpads > > > > that wobble but > > > > with more than one event per direction. I suspect there are but > > > > this should > > > > be simple enough that it catches the first RLR movement (bound > > > > to happen at > > > > some point) and enable it then. The main question is whether there is a > > > > noticeable period of wobbling until this happens. > > > > I honestly don't know, we won't know until ppl start shouting at us... > > > > > > My touchpad definitely does; however it does so many events for > > > every touch that I feel like it produces every possible combination > > > within a second or two. The more that the number for the three slots > > > is 2³ = 8, which isn't much. > > > > > > > > + if (time - tp->hysteresis.last_motion_time > ms2us(20) > > > > > || x_diff == 0) { > > > > > + tp->hysteresis.x_motion_in_threshold = 0; > > > > > + return; > > > > > + } > > > > > > > > empty line here please. > > > > > > > > > + tp->hysteresis.x_motion_in_threshold <<= 1; > > > > > + if (x_diff > 0) { /* right move */ > > > > > > > > s/x_diff/dx/, we use that everywhere else for deltas. > > > > > > > > > + tp->hysteresis.x_motion_in_threshold |= 1; > > > > > + static const char r_l_r = 5; /* {Right, Left, Right} */ > > > > > > > > declarations at the top of the block please, separated by an > > > > empty line. See > > > > CODING_STYLE in the repository. > > > > > > > > > + if (tp->hysteresis.x_motion_in_threshold & r_l_r) { > > > > > > > > this one will trigger on the first right movement, you need > > > > if ((tp->hysteresis.x_motion_in_threshold & r_l_r) == r_l_r) > > > > > > > > With that change, it seems to work correctly on my non-wobbling touchpad > > > > here. Does it still work for you when you add this? > > > > > > Thank you, nice catch! > > > > > > > > + tp->hysteresis.enabled = true; > > > > > + evdev_log_debug(tp->device, "hysteresis enabled\n"); > > > > > + } > > > > > + } > > > > > +} > > > > > + > > > > > static inline void > > > > > tp_motion_hysteresis(struct tp_dispatch *tp, > > > > > struct tp_touch *t) > > > > > @@ -1405,6 +1435,8 @@ tp_process_state(struct tp_dispatch > > > > > *tp, uint64_t time) > > > > > tp_thumb_detect(tp, t, time); > > > > > tp_palm_detect(tp, t, time); > > > > > + tp_detect_wobbling(tp, tp->hysteresis.prev_x - > > > > > t->point.x, time); > > > > > + tp->hysteresis.prev_x = t->point.x; > > > > > > > > the dx calculation should happen within tp_detect_wobbling, just > > > > pass the > > > > touch in and do the subtraction there. Plus that way you can do > > > > a simple: > > > > if (tp->prev.x == 0) dx = 0; > > > > which makes things more obvious. > > > > > > Well, not really can, the comparison for zero here would check > > > coordinate of previous x, whereas I need to check whether the delta > > > between prev. and curr. positions is zero, e.g. if a finger is still > > > and FW filters.
I was referring to your comment that it's unclear what value prev_x should be initialised to. even though it's not needed, it'll make the code a lot more obvious if you handle the zero case here. so the code would be something like: if (tp->prev.x == 0) /* first invocation */ dx = 0; else dx = t->point.x - t->hysteresis.prev.x also, please make prev a struct point, even if we don't use y at this point, easier to read and better for type-safety, as much as we get that in C. > > > > > tp_motion_hysteresis(tp, t); > > > > > tp_motion_history_push(t); > > > > > @@ -2918,6 +2950,7 @@ tp_init_hysteresis(struct tp_dispatch *tp) > > > > > tp->hysteresis.margin.x = res_x/2; > > > > > tp->hysteresis.margin.y = res_y/2; > > > > > tp->hysteresis.enabled = false; > > > > > + tp->hysteresis.x_motion_in_threshold = 0; > > > > > > > > 'threshold' usually refers to a distance in libinput, here it's more a > > > > timeout. But calling it x_motion_history would be best here, IMO. > > > > > > > > > } > > > > > static void > > > > > diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h > > > > > index 442f34a3..398a18ed 100644 > > > > > --- a/src/evdev-mt-touchpad.h > > > > > +++ b/src/evdev-mt-touchpad.h > > > > > @@ -276,6 +276,8 @@ struct tp_dispatch { > > > > > struct device_coords margin; > > > > > unsigned int other_event_count; > > > > > uint64_t last_motion_time; > > > > > + char x_motion_in_threshold; > > > > > + int prev_x; > > > > > > > > both of these need to be in the struct tp_touch, otherwise 2-finger > > > > scrolling may enable the hysteresis when the fingers move > > > > independently from > > > > each other but you're adding them to the same bitmask. > > > > > > Thanks for you comments! > > > > > > I tried addressing them, and found that the result of the time > > > calculation "time - tp->hysteresis.last_motion_time" whilst my > > > finger is down is constantly increasing, i.e. like "20, 30, 50, 100, > > > 120…". It looks as if "tp->hysteresis.last_motion_time" is not the > > > last motion time, but the last finger-down time. > > > > > > Do you happen to know anything about that? > > > > Although I did find what's the matter. Turns out, the last_motion_time > > have been assigned at tp_maybe_disable_hysteresis() which I did remove. > > But even there it's been guarded by if: > > > > if (tp->queued & TOUCHPAD_EVENT_MOTION) > > tp->hysteresis.last_motion_time = time; > > > > What does that condition mean? > > Ok, I see, I was mostly confused by "queued" name. It probably means "events > queued to get processed by libinput". the evdev protocol is serial, so we get a bunch of separate events, grouped into a frame by the subsequent EV_SYN SYN_REPORT event. We cannot process the events until we get this event, so we need to buffer what has happened and process the state once we have the SYN_REPORT. the tp->queued is a bitmask of the things that have happened, TOUCHPAD_EVENT_MOTION simply means either x or y has updated and we need to move the touch. > I wrote a code like: > > if (tp->queued & TOUCHPAD_EVENT_MOTION) { > tp_detect_wobbling(tp, t, time); > tp->hysteresis.last_motion_time = time; > t->prev_x = t->point.x; > } fwiw, this should all move into tp_detect_wobbling(), with an early return if tp->queued is emtpy. > It should work like it previously did; what bothers me however — shouldn't > that be specific to a touch, but not touchpad? Couldn't that get triggered > e.g. by 2-finger scrolling? (whatever that is, I dunno, touching with 2 > finger doesn't scroll for me — I do scroll instead using the right edge of > the touchpad). if you make it per-touch then yes, it can get triggered by 2-finger scrolling but it'll work per-touch so either touch has to wobble to disable the hysteresis. we can assume that if one touch wobbles, all of them will. 2-finger scrolling can be enabled with the libinput_device_config_set_scroll_method() call, or libinput debug-events --set-scroll-method=twofinger, you should give it a try. edge scrolling is going the way of the dodo. Cheers, Peter _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel