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