The touchpad input driver includes a function that identifies "stable"
movements.  It is very simple, but seems to work sufficiently well with
most kinds of inputs.  There is an exception: some touchpads regularly
report intermediate zero coordinate-deltas when a touch is moving very
slowly.  The filter state is cleared when it shouldn't be, which may
ruin slow scrolling.

This patch relaxes the filter conditions.  Zero deltas only reset the
state if a given time interval (55ms) has passed since the last change
of the touch position.  Moreover, as long as the contact count and the
button state don't change, the check is skipped after scrolling has
started (which makes it easier to correct a position). 

Any objections?


Index: dev/wscons/wstpad.c
===================================================================
RCS file: /cvs/src/sys/dev/wscons/wstpad.c,v
retrieving revision 1.17
diff -u -p -r1.17 wstpad.c
--- dev/wscons/wstpad.c 7 May 2018 21:58:42 -0000       1.17
+++ dev/wscons/wstpad.c 4 Nov 2018 12:45:06 -0000
@@ -60,6 +60,7 @@
 
 #define CLICKDELAY_MS          20
 #define FREEZE_MS              100
+#define MATCHINTERVAL_MS       55
 
 enum tpad_handlers {
        SOFTBUTTON_HDLR,
@@ -121,6 +122,7 @@ struct tpad_touch {
        int y;
        int dir;
        int matches;
+       struct timespec stop;
        struct {
                int x;
                int y;
@@ -296,20 +298,32 @@ dircmp(int dir1, int dir2)
 }
 
 void
-wstpad_set_direction(struct tpad_touch *t, int dx, int dy, int ratio)
+wstpad_set_direction(struct wstpad *tp, struct tpad_touch *t, int dx, int dy)
 {
        int dir;
+       static const struct timespec interval =
+           { .tv_sec = 0, .tv_nsec = MATCHINTERVAL_MS * 1000000 };
 
        if (t->state != TOUCH_UPDATE) {
                t->dir = -1;
                t->matches = 0;
        } else {
-               dir = direction(dx, dy, ratio);
-               if (t->dir >= 0 && dir >= 0 && dircmp(t->dir, dir) <= 1)
-                       t->matches++;
-               else
-                       t->matches = 1;
-               t->dir = dir;
+               dir = direction(dx, dy, tp->ratio);
+               if (dir >= 0) {
+                       if (t->dir >= 0 && dircmp(t->dir, dir) <= 1)
+                               t->matches++;
+                       else
+                               t->matches = 1;
+                       t->dir = dir;
+
+                       timespecadd(&tp->time, &interval, &t->stop);
+
+               } else if (t->dir >= 0) {
+                       if (timespeccmp(&tp->time, &t->stop, >=)) {
+                               t->dir = -1;
+                               t->matches = 0;
+                       }
+               }
        }
 }
 
@@ -367,6 +381,9 @@ chk_scroll_state(struct wstpad *tp)
                tp->scroll.dw = 0;
                return (0);
        }
+       if (tp->t->matches < STABLE && !(tp->scroll.dz || tp->scroll.dw))
+               return (0);
+
        return (tp->dx || tp->dy);
 }
 
@@ -433,7 +450,8 @@ wstpad_f2scroll(struct wsmouseinput *inp
                                return;
                        if ((dx > 0 && !EAST(dir)) || (dx < 0 && !WEST(dir)))
                                return;
-                       if (t2->matches < imin(STABLE, tp->t->matches / 4))
+                       if (t2->matches < STABLE &&
+                           !(tp->scroll.dz || tp->scroll.dw))
                                return;
                        centered |= CENTERED(t2);
                }
@@ -900,7 +918,7 @@ wstpad_mt_inputs(struct wsmouseinput *in
                t->orig.y = t->y;
                memcpy(&t->orig.time, &tp->time, sizeof(struct timespec));
                t->flags = edge_flags(tp, t->x, t->y);
-               wstpad_set_direction(t, 0, 0, tp->ratio);
+               wstpad_set_direction(tp, t, 0, 0);
        }
 
        /* TOUCH_UPDATE */
@@ -928,9 +946,9 @@ wstpad_mt_inputs(struct wsmouseinput *in
                        dy = normalize_abs(&input->filter.v, mts->pos.y) - t->y;
                        t->y += dy;
                        t->flags &= (~EDGES | edge_flags(tp, t->x, t->y));
-                       wstpad_set_direction(t, dx, dy, tp->ratio);
+                       wstpad_set_direction(tp, t, dx, dy);
                } else if ((1 << slot) & inactive) {
-                       wstpad_set_direction(t, 0, 0, tp->ratio);
+                       wstpad_set_direction(tp, t, 0, 0);
                }
        }
 
@@ -1035,7 +1053,7 @@ wstpad_touch_inputs(struct wsmouseinput 
                        t->flags &= (~EDGES | edge_flags(tp, t->x, t->y));
                }
 
-               wstpad_set_direction(t, tp->dx, tp->dy, input->filter.ratio);
+               wstpad_set_direction(tp, t, tp->dx, tp->dy);
        }
 }
 

Reply via email to