Hi Joshua,

could you make a test with the updated diff below and check whether
the scroll speed is normal? (There are no changes in ws, it's just
the kernel part).

On 3/16/19 4:16 PM, joshua stein wrote:
> On Thu, 14 Mar 2019 at 00:48:33 +0100, Ulf Brosziewski wrote:
>> Much too fast?  I'm a bit surprised.  In my tests, the new method was
>> generally somewhat slower than the old one (and I haven't changed the
>> "scroll units").  How did you test it?  Which hardware and which applications
>> did you use?
> 
> This is with an imt touchpad:
> 
>        ihidev0 at iic1 addr 0x15 irq 109 (polling), vendor 0x4f3 product 
> 0x3056, ELAN2201
>        ihidev0: 93 report ids
>        imt0 at ihidev0: clickpad, 5 contacts
>        wsmouse0 at imt0 mux 0
> 
> I tested with two-finger scrolling in Firefox and Chrome with a new 
> user and fresh browser profiles.  I loaded the same webpages with 
> the old wstpad code and the new, and the two-finger scrolling with 
> the new setup scrolls much too fast for even small finger movements 
> (~0.5").
> 
> A movement with the previous code that would trigger the 
> mousewheel-style scrolling of just a handful of lines causes the new 
> code to scroll nearly an entire screen-height of the page.
> 
> 

Index: dev/wscons/wsconsio.h
===================================================================
RCS file: /cvs/src/sys/dev/wscons/wsconsio.h,v
retrieving revision 1.90
diff -u -p -r1.90 wsconsio.h
--- dev/wscons/wsconsio.h       10 Nov 2018 14:27:51 -0000      1.90
+++ dev/wscons/wsconsio.h       17 Mar 2019 18:23:14 -0000
@@ -112,6 +112,12 @@ struct wscons_event {
 #define        WSCONS_EVENT_TOUCH_RESET        25      /* (no value) */

 /*
+ * Precision Scrolling
+ */
+#define WSCONS_EVENT_HSCROLL           26      /* dx * 4096 / scroll_unit */
+#define WSCONS_EVENT_VSCROLL           27      /* dy * 4096 / scroll_unit */
+
+/*
  * Keyboard ioctls (0 - 31)
  */

Index: dev/wscons/wsmouse.c
===================================================================
RCS file: /cvs/src/sys/dev/wscons/wsmouse.c,v
retrieving revision 1.51
diff -u -p -r1.51 wsmouse.c
--- dev/wscons/wsmouse.c        19 Feb 2019 07:01:02 -0000      1.51
+++ dev/wscons/wsmouse.c        17 Mar 2019 18:23:14 -0000
@@ -1034,10 +1034,18 @@ wsmouse_motion_sync(struct wsmouseinput
                        wsmouse_evq_put(evq, DELTA_X_EV(input), dx);
                if (dy)
                        wsmouse_evq_put(evq, DELTA_Y_EV(input), dy);
-               if (motion->dz)
-                       wsmouse_evq_put(evq, DELTA_Z_EV, motion->dz);
-               if (motion->dw)
-                       wsmouse_evq_put(evq, DELTA_W_EV, motion->dw);
+               if (motion->dz) {
+                       if (IS_TOUCHPAD(input))
+                               wsmouse_evq_put(evq, VSCROLL_EV, motion->dz);
+                       else
+                               wsmouse_evq_put(evq, DELTA_Z_EV, motion->dz);
+               }
+               if (motion->dw) {
+                       if (IS_TOUCHPAD(input))
+                               wsmouse_evq_put(evq, HSCROLL_EV, motion->dw);
+                       else
+                               wsmouse_evq_put(evq, DELTA_W_EV, motion->dw);
+               }
        }
        if (motion->sync & SYNC_POSITION) {
                if (motion->sync & SYNC_X) {
Index: dev/wscons/wsmouseinput.h
===================================================================
RCS file: /cvs/src/sys/dev/wscons/wsmouseinput.h,v
retrieving revision 1.12
diff -u -p -r1.12 wsmouseinput.h
--- dev/wscons/wsmouseinput.h   10 Nov 2018 14:27:51 -0000      1.12
+++ dev/wscons/wsmouseinput.h   17 Mar 2019 18:23:14 -0000
@@ -210,6 +210,8 @@ int wstpad_set_param(struct wsmouseinput
     WSCONS_EVENT_MOUSE_ABSOLUTE_X : WSCONS_EVENT_MOUSE_ABSOLUTE_Y)
 #define DELTA_Z_EV     WSCONS_EVENT_MOUSE_DELTA_Z
 #define DELTA_W_EV     WSCONS_EVENT_MOUSE_DELTA_W
+#define VSCROLL_EV     WSCONS_EVENT_VSCROLL
+#define HSCROLL_EV     WSCONS_EVENT_HSCROLL
 #define ABS_Z_EV       WSCONS_EVENT_TOUCH_PRESSURE
 #define ABS_W_EV       WSCONS_EVENT_TOUCH_CONTACTS
 #define BTN_DOWN_EV    WSCONS_EVENT_MOUSE_DOWN
Index: dev/wscons/wstpad.c
===================================================================
RCS file: /cvs/src/sys/dev/wscons/wstpad.c,v
retrieving revision 1.22
diff -u -p -r1.22 wstpad.c
--- dev/wscons/wstpad.c 29 Dec 2018 21:03:58 -0000      1.22
+++ dev/wscons/wstpad.c 17 Mar 2019 18:23:14 -0000
@@ -167,8 +167,6 @@ struct wstpad {
        u_int mtcycle;
        u_int ignore;

-       int dx;
-       int dy;
        int contacts;
        int prev_contacts;
        u_int btns;
@@ -223,12 +221,11 @@ struct wstpad {
        } tap;

        struct {
-               int acc_dx;
-               int acc_dy;
                int dz;
                int dw;
                int hdist;
                int vdist;
+               int mag;
        } scroll;
 };

@@ -435,8 +432,8 @@ set_freeze_ts(struct wstpad *tp, int sec


 /* Return TRUE if two-finger- or edge-scrolling would be valid. */
-static inline int
-chk_scroll_state(struct wsmouseinput *input)
+int
+wstpad_scroll_coords(struct wsmouseinput *input, int *dx, int *dy)
 {
        struct wstpad *tp = input->tp;

@@ -445,46 +442,51 @@ chk_scroll_state(struct wsmouseinput *in
                tp->scroll.dw = 0;
                return (0);
        }
+       if ((input->motion.sync & SYNC_POSITION) == 0)
+               return (0);
        /*
         * Try to exclude accidental scroll events by checking whether the
         * pointer-controlling touch is stable.  The check, which may cause
         * a short delay, is only applied initially, a touch that stops and
         * resumes scrolling is not affected.
         */
-       if (tp->scroll.dz || tp->scroll.dw || wstpad_is_stable(input, tp->t))
-               return (tp->dx || tp->dy);
+       if (tp->scroll.dz || tp->scroll.dw || wstpad_is_stable(input, tp->t)) {
+               *dx = normalize_rel(&input->filter.h, input->motion.pos.dx);
+               *dy = normalize_rel(&input->filter.v, input->motion.pos.dy);
+               return (*dx || *dy);
+       }

        return (0);
 }

 void
-wstpad_scroll(struct wstpad *tp, int dx, int dy, u_int *cmds)
+wstpad_scroll(struct wstpad *tp, int dx, int dy, int mag, u_int *cmds)
 {
-       int sign;
-
-       /* Scrolling is either horizontal or vertical, but not both. */
+       int dz, dw, n = 1;

-       sign = (dy > 0) - (dy < 0);
-       if (sign) {
-               if (tp->scroll.dz != -sign) {
-                       tp->scroll.dz = -sign;
-                       tp->scroll.acc_dy = -tp->scroll.vdist;
-               }
-               tp->scroll.acc_dy += abs(dy);
-               if (tp->scroll.acc_dy >= 0) {
-                       tp->scroll.acc_dy -= tp->scroll.vdist;
-                       *cmds |= 1 << VSCROLL;
-               }
-       } else if ((sign = (dx > 0) - (dx < 0))) {
-               if (tp->scroll.dw != sign) {
-                       tp->scroll.dw = sign;
-                       tp->scroll.acc_dx = -tp->scroll.hdist;
-               }
-               tp->scroll.acc_dx += abs(dx);
-               if (tp->scroll.acc_dx >= 0) {
-                       tp->scroll.acc_dx -= tp->scroll.hdist;
-                       *cmds |= 1 << HSCROLL;
-               }
+       /*
+        * The function applies strong deceleration, but only to input with
+        * very low speeds.  A higher threshold might make applications
+        * without support for precision scrolling appear unresponsive.
+        */
+       mag = tp->scroll.mag = imin(MAG_MEDIUM,
+           (mag + 3 * tp->scroll.mag) / 4);
+       if (mag < MAG_LOW)
+               n = (MAG_LOW - mag) / 4096 + 1;
+
+       if (dy && tp->scroll.vdist) {
+               dz = -dy * 4096 / (tp->scroll.vdist * n);
+               if (tp->scroll.dz && (dy < 0 == tp->scroll.dz > 0))
+                       dz = (dz + 3 * tp->scroll.dz) / 4;
+               tp->scroll.dz = dz;
+               *cmds |= 1 << VSCROLL;
+
+       } else if (dx && tp->scroll.hdist) {
+               dw = dx * 4096 / (tp->scroll.hdist * n);
+               if (tp->scroll.dw && (dx > 0 == tp->scroll.dw > 0))
+                       dw = (dw + 3 * tp->scroll.dw) / 4;
+               tp->scroll.dw = dw;
+               *cmds |= 1 << HSCROLL;
        }
 }

@@ -502,12 +504,14 @@ wstpad_f2scroll(struct wsmouseinput *inp
                return;
        }

-       if (!chk_scroll_state(input))
+       if (!wstpad_scroll_coords(input, &dx, &dy))
                return;

        dir = tp->t->dir;
-       dy = NORTH(dir) || SOUTH(dir) ? tp->dy : 0;
-       dx = EAST(dir) || WEST(dir) ? tp->dx : 0;
+       if (!(NORTH(dir) || SOUTH(dir)))
+               dy = 0;
+       if (!(EAST(dir) || WEST(dir)))
+               dx = 0;

        if (dx || dy) {
                centered = CENTERED(tp->t);
@@ -526,7 +530,8 @@ wstpad_f2scroll(struct wsmouseinput *inp
                        centered |= CENTERED(t2);
                }
                if (centered) {
-                       wstpad_scroll(tp, dx, dy, cmds);
+                       wstpad_scroll(tp, dx, dy,
+                           magnitude(input, dx, dy), cmds);
                        set_freeze_ts(tp, 0, FREEZE_MS);
                }
        }
@@ -540,17 +545,19 @@ wstpad_edgescroll(struct wsmouseinput *i
        u_int v_edge, b_edge;
        int dx, dy;

-       if (tp->contacts != 1 || !chk_scroll_state(input))
+       if (!wstpad_scroll_coords(input, &dx, &dy) || tp->contacts != 1)
                return;

        v_edge = (tp->features & WSTPAD_SWAPSIDES) ? L_EDGE : R_EDGE;
        b_edge = (tp->features & WSTPAD_HORIZSCROLL) ? B_EDGE : 0;

-       dy = (t->flags & v_edge) ? tp->dy : 0;
-       dx = (t->flags & b_edge) ? tp->dx : 0;
+       if ((t->flags & v_edge) == 0)
+               dy = 0;
+       if ((t->flags & b_edge) == 0)
+               dx = 0;

        if (dx || dy)
-               wstpad_scroll(tp, dx, dy, cmds);
+               wstpad_scroll(tp, dx, dy, magnitude(input, dx, dy), cmds);
 }

 static inline u_int
@@ -1121,20 +1128,7 @@ wstpad_touch_inputs(struct wsmouseinput
 {
        struct wstpad *tp = input->tp;
        struct tpad_touch *t;
-       int slot;
-
-       /*
-        * Use the normalized, hysteresis-filtered, but otherwise untransformed
-        * relative coordinates of the pointer-controlling touch for filtering
-        * and scrolling.
-        */
-       if ((input->motion.sync & SYNC_POSITION)
-           && !wsmouse_hysteresis(input, &input->motion.pos)) {
-               tp->dx = normalize_rel(&input->filter.h, input->motion.pos.dx);
-               tp->dy = normalize_rel(&input->filter.v, input->motion.pos.dy);
-       } else {
-               tp->dx = tp->dy = 0;
-       }
+       int slot, x, y, dx, dy;

        tp->btns = input->btn.buttons;
        tp->btns_sync = input->btn.sync;
@@ -1158,8 +1152,6 @@ wstpad_touch_inputs(struct wsmouseinput
                wstpad_mt_masks(input);
        } else {
                t = tp->t;
-               t->x = normalize_abs(&input->filter.h, t->pos->x);
-               t->y = normalize_abs(&input->filter.v, t->pos->y);
                if (tp->contacts)
                        t->state = (tp->prev_contacts ?
                            TOUCH_UPDATE : TOUCH_BEGIN);
@@ -1167,17 +1159,25 @@ wstpad_touch_inputs(struct wsmouseinput
                        t->state = (tp->prev_contacts ?
                            TOUCH_END : TOUCH_NONE);

+               dx = dy = 0;
+               x = normalize_abs(&input->filter.h, t->pos->x);
+               y = normalize_abs(&input->filter.v, t->pos->y);
                if (t->state == TOUCH_BEGIN) {
-                       t->orig.x = t->x;
-                       t->orig.y = t->y;
+                       t->x = t->orig.x = x;
+                       t->y = t->orig.y = y;
                        memcpy(&t->orig.time, &tp->time,
                            sizeof(struct timespec));
-                       t->flags = edge_flags(tp, t->x, t->y);
-               } else {
-                       t->flags &= (~EDGES | edge_flags(tp, t->x, t->y));
+                       t->flags = edge_flags(tp, x, y);
+               } else if (input->motion.sync & SYNC_POSITION) {
+                       if (!wsmouse_hysteresis(input, t->pos)) {
+                               dx = x - t->x;
+                               dy = y - t->y;
+                       }
+                       t->x = x;
+                       t->y = y;
+                       t->flags &= (~EDGES | edge_flags(tp, x, y));
                }
-
-               wstpad_set_direction(tp, t, tp->dx, tp->dy);
+               wstpad_set_direction(tp, t, dx, dy);
        }
 }

Reply via email to