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); } }