tech-x11 archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Precise scrolling for wsmouse



Greetz tech-x11,

OpenBSD has WSCONS_EVENT_HSCROLL and WSCONS_EVENT_VSCROLL.
These are useful for scrolling with precise coordinates.

The following diff adds support for HSCROLL and VSCROLL
to our wsmouse(4) and synaptics(4), where it's used to provide
much smoother two-finger and trackpoint scrolling.
The synaptics driver also gets some simplification.
I think this is much better than its previous state.

Also attached is a diff with the necessary changes to
xf86-input-ws.
 
Later I should make it so scrolling speed and
direction configurable in wsconsctl -m. But right now,
I should sleep.

Testing would be nice.

I have in my xorg.conf:

Section "ServerLayout"
        Identifier      "layout"
        InputDevice     "Mouse0" "CorePointer"
EndSection
 
Section "InputDevice"
        Identifier  "Mouse0"
        Driver      "ws"
        Option "Device" "/dev/wsmouse0"
EndSection
Index: dev/wscons/wsmouse.c
===================================================================
RCS file: /cvsroot/src/sys/dev/wscons/wsmouse.c,v
retrieving revision 1.69
diff -u -r1.69 wsmouse.c
--- dev/wscons/wsmouse.c	27 Dec 2020 16:09:33 -0000	1.69
+++ dev/wscons/wsmouse.c	21 Sep 2021 22:22:32 -0000
@@ -516,6 +516,37 @@
 	}
 }
 
+void
+wsmouse_precision_scroll(device_t wsmousedev, int x, int y)
+{
+	struct wsmouse_softc *sc = device_private(wsmousedev);
+	struct wseventvar *evar;
+	struct wscons_event events[2];
+	int nevents = 0;
+
+	evar = sc->sc_base.me_evp;
+	if (evar == NULL)
+		return;
+
+	/* XXX: scroll distance should be configurable */
+	x = (x * 4096) / 12;
+	y = (y * 4096) / 12;
+
+	if (x != 0) {
+		events[nevents].type = WSCONS_EVENT_HSCROLL;
+		events[nevents].value = x;
+		nevents++;
+	}
+
+	if (y != 0) {
+		events[nevents].type = WSCONS_EVENT_VSCROLL;
+		events[nevents].value = y;
+		nevents++;
+	}
+
+	(void)wsevent_inject(evar, events, nevents);
+}
+
 static void
 wsmouse_repeat(void *v)
 {
Index: dev/wscons/wsmousevar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/wscons/wsmousevar.h,v
retrieving revision 1.11
diff -u -r1.11 wsmousevar.h
--- dev/wscons/wsmousevar.h	12 May 2009 14:47:55 -0000	1.11
+++ dev/wscons/wsmousevar.h	21 Sep 2021 22:22:32 -0000
@@ -73,3 +73,4 @@
 #define WSMOUSE_INPUT_ABSOLUTE_Z	(1<<2)
 #define WSMOUSE_INPUT_ABSOLUTE_W	(1<<3)
 void	wsmouse_input(device_t, u_int, int, int, int, int, u_int);
+void	wsmouse_precision_scroll(device_t, int, int);
Index: dev/pckbport/synaptics.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pckbport/synaptics.c,v
retrieving revision 1.71
diff -u -r1.71 synaptics.c
--- dev/pckbport/synaptics.c	30 May 2021 13:20:01 -0000	1.71
+++ dev/pckbport/synaptics.c	21 Sep 2021 22:22:32 -0000
@@ -120,9 +120,6 @@
 static int synaptics_max_speed_y = 32;
 static int synaptics_max_speed_z = 2;
 static int synaptics_movement_threshold = 4;
-static int synaptics_fscroll_min = 13;
-static int synaptics_fscroll_max = 14;
-static int synaptics_dz_hold = 30;
 static int synaptics_movement_enable = 1;
 static bool synaptics_aux_mid_button_scroll = TRUE;
 static int synaptics_debug = 0;
@@ -159,9 +156,6 @@
 static int synaptics_max_speed_y_nodenum;
 static int synaptics_max_speed_z_nodenum;
 static int synaptics_movement_threshold_nodenum;
-static int synaptics_finger_scroll_min_nodenum;
-static int synaptics_finger_scroll_max_nodenum;
-static int synaptics_dz_hold_nodenum;
 static int synaptics_movement_enable_nodenum;
 static int synaptics_aux_mid_button_scroll_nodenum;
 
@@ -503,7 +497,6 @@
 	sc->gesture_tap_packet = 0;
 	sc->gesture_type = 0;
 	sc->gesture_buttons = 0;
-	sc->dz_hold = 0;
 	for (i = 0; i < SYN_MAX_FINGERS; i++) {
 		sc->rem_x[i] = sc->rem_y[i] = sc->rem_z[i] = 0;
 		sc->movement_history[i] = 0;
@@ -809,42 +802,6 @@
 
 	if ((rc = sysctl_createv(clog, 0, NULL, &node,
 	    CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
-	    CTLTYPE_INT, "finger_scroll-min",
-	    SYSCTL_DESCR("Minimum width at which y cursor movements will be converted to scroll wheel events"),
-	    pms_sysctl_synaptics_verify, 0,
-	    &synaptics_fscroll_min,
-	    0, CTL_HW, root_num, CTL_CREATE,
-	    CTL_EOL)) != 0)
-		goto err;
-
-	synaptics_finger_scroll_min_nodenum = node->sysctl_num;
-
-	if ((rc = sysctl_createv(clog, 0, NULL, &node,
-	    CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
-	    CTLTYPE_INT, "finger_scroll-max",
-	    SYSCTL_DESCR("Maximum width at which y cursor movements will be converted to scroll wheel events"),
-	    pms_sysctl_synaptics_verify, 0,
-	    &synaptics_fscroll_max,
-	    0, CTL_HW, root_num, CTL_CREATE,
-	    CTL_EOL)) != 0)
-		goto err;
-
-	synaptics_finger_scroll_max_nodenum = node->sysctl_num;
-
-	if ((rc = sysctl_createv(clog, 0, NULL, &node,
-	    CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
-	    CTLTYPE_INT, "finger_scroll-hysteresis",
-	    SYSCTL_DESCR("Number of packets to keep reporting y cursor movements as scroll wheel events"),
-	    pms_sysctl_synaptics_verify, 0,
-	    &synaptics_dz_hold,
-	    0, CTL_HW, root_num, CTL_CREATE,
-	    CTL_EOL)) != 0)
-		goto err;
-
-	synaptics_dz_hold_nodenum = node->sysctl_num;
-
-	if ((rc = sysctl_createv(clog, 0, NULL, &node,
-	    CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
 	    CTLTYPE_BOOL, "aux_mid_button_scroll",
 	    SYSCTL_DESCR("Interpet Y-Axis movement with the middle button held as scrolling on the passthrough device (e.g. TrackPoint)"),
 	    pms_sysctl_synaptics_verify, 0,
@@ -943,17 +900,6 @@
 		if (t < SYNAPTICS_EDGE_LEFT || t > SYNAPTICS_EDGE_RIGHT)
 			return (EINVAL);
 	} else
-	if (node.sysctl_num == synaptics_finger_scroll_min_nodenum ||
-	    node.sysctl_num == synaptics_finger_scroll_max_nodenum) {
-		/* make sure we avoid the "magic" widths, 4 and below
-		   are for fingers, 15 is palm detect. */
-		if ((t < 5) || (t > 14))
-			return (EINVAL);
-	} else
-	if (node.sysctl_num == synaptics_dz_hold_nodenum) {
-		if (t < 0)
-			return (EINVAL);
-	} else
 	if (node.sysctl_num == synaptics_movement_enable_nodenum) {
 		if (t < 0 || t > 1)
 			return (EINVAL);
@@ -1213,20 +1159,20 @@
 	psc->buttons ^= changed;
 
 	if (dx || dy || dz || changed) {
+		s = spltty();
 		/*
-		 * If the middle button is held, interpret Y-axis
-		 * movement as scrolling.
+		 * If the middle button is held, interpret movement as
+		 * scrolling.
 		 */
 		if (synaptics_aux_mid_button_scroll &&
 		    dy && (psc->buttons & 0x2)) {
-			dz = -dy;
-			dx = dy = 0;
+			wsmouse_precision_scroll(psc->sc_wsmousedev, dx, dy);
+		} else {
+			buttons = (psc->buttons & 0x1f) | ((psc->buttons >> 5) & 0x7);
+			wsmouse_input(psc->sc_wsmousedev,
+				buttons, dx, dy, dz, 0,
+				WSMOUSE_INPUT_DELTA);
 		}
-		buttons = (psc->buttons & 0x1f) | ((psc->buttons >> 5) & 0x7);
-		s = spltty();
-		wsmouse_input(psc->sc_wsmousedev,
-			buttons, dx, dy, dz, 0,
-			WSMOUSE_INPUT_DELTA);
 		splx(s);
 	}
 }
@@ -1650,27 +1596,19 @@
 
 static inline void
 synaptics_movement(struct synaptics_softc *sc, struct synaptics_packet *sp,
-    int finger, int scroll_emul, int *dxp, int *dyp, int *dzp)
+    int finger, int *dxp, int *dyp, int *dzp)
 {
 	int dx, dy, dz, edge;
 
 	dx = dy = dz = 0;
 
 	/*
-	 * Compute the next values of dx and dy and dz.  If scroll_emul
-	 * is non-zero, take the dy and used it as use it as dz so we
-	 * can emulate a scroll wheel.
+	 * Compute the next values of dx and dy and dz.
 	 */
-	if (scroll_emul == 0) {
-		dx = synaptics_filter_policy(sc, finger, sc->history_x[finger],
-			sp->sp_x);
-		dy = synaptics_filter_policy(sc, finger, sc->history_y[finger],
-			sp->sp_y);
-	} else {
-		dz = synaptics_filter_policy(sc, finger, sc->history_z[finger],
-			sp->sp_y);
-		dx = dy = 0;
-	}
+	dx = synaptics_filter_policy(sc, finger, sc->history_x[finger],
+		sp->sp_x);
+	dy = synaptics_filter_policy(sc, finger, sc->history_y[finger],
+		sp->sp_y);
 
 	/*
 	 * If we're dealing with a drag gesture, and the finger moves to
@@ -1720,7 +1658,7 @@
 	struct synaptics_softc *sc = &psc->u.synaptics;
 	int dx, dy, dz;
 	int fingers, palm, buttons, changed;
-	int s, z_emul;
+	int s;
 
 	/*
 	 * Do Z-axis emulation using up/down buttons if required.
@@ -1781,20 +1719,21 @@
 	 */
 	if (palm == 0 && synaptics_movement_enable) {
 		if (fingers == 1) {
-			z_emul = 0;
-
-			if ((sp->sp_w >= synaptics_fscroll_min) &&
-			    (sp->sp_w <= synaptics_fscroll_max)) {
-				z_emul = 1;
-				sc->dz_hold = synaptics_dz_hold;
-			}
-
-			if (sc->dz_hold > 0) {
-				z_emul = 1;
-			}
-
+			/*
+			 * Single finger - normal movement.
+			 */
+			synaptics_movement(sc, sp, sp->sp_finger,
+			    &dx, &dy, &dz);
+		} else if (fingers == 2 && sc->gesture_type == 0) {
+			/*
+			 * Multiple finger movement. Interpret it as scrolling.
+			 */
 			synaptics_movement(sc, sp, sp->sp_finger,
-				z_emul, &dx, &dy, &dz);
+			    &dx, &dy, &dz);
+			s = spltty();
+			wsmouse_precision_scroll(psc->sc_wsmousedev, dx, dy);
+			splx(s);
+			return;
 		} else {
 			/*
 			 * No valid finger. Therefore no movement.
@@ -1812,9 +1751,6 @@
 		dx = dy = dz = 0;
 	}
 
-	if (sc->dz_hold > 0)
-		sc->dz_hold--;
-
 	/*
 	 * Pass the final results up to wsmouse_input() if necessary.
 	 */
Index: external/mit/xf86-input-ws/dist/src/ws.c
===================================================================
RCS file: /cvsroot/xsrc/external/mit/xf86-input-ws/dist/src/ws.c,v
retrieving revision 1.11
diff -u -r1.11 ws.c
--- external/mit/xf86-input-ws/dist/src/ws.c	14 Apr 2017 19:19:43 -0000	1.11
+++ external/mit/xf86-input-ws/dist/src/ws.c	21 Sep 2021 22:23:35 -0000
@@ -450,6 +450,10 @@
 		axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
 		axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
 	}
+	axes_labels[HSCROLL_AXIS] =
+	    XIGetKnownProperty(AXIS_LABEL_PROP_REL_HSCROLL);
+	axes_labels[VSCROLL_AXIS] =
+	    XIGetKnownProperty(AXIS_LABEL_PROP_REL_VSCROLL);
 	if (!InitValuatorClassDeviceStruct(pWS,
 		NAXES,
 		axes_labels,
@@ -478,6 +482,25 @@
 	);
 	xf86InitValuatorDefaults(pWS, 1);
 
+
+	xf86InitValuatorAxisStruct(pWS, HSCROLL_AXIS,
+	    axes_labels[HSCROLL_AXIS], 0, -1, 0, 0, 0, Relative);
+	xf86InitValuatorAxisStruct(pWS, VSCROLL_AXIS,
+	    axes_labels[VSCROLL_AXIS], 0, -1, 0, 0, 0, Relative);
+	priv->scroll_mask = valuator_mask_new(MAX_VALUATORS);
+	if (!priv->scroll_mask) {
+		return !Success;
+	}
+
+	/*
+	 * The value of an HSCROLL or VSCROLL event is the fraction
+	 *         motion_delta / scroll_distance
+	 * in [*.12] fixed-point format.  The 'increment' attribute of the
+	 * scroll axes is constant:
+	 */
+	SetScrollValuator(pWS, HSCROLL_AXIS, SCROLL_TYPE_HORIZONTAL, 4096, 0);
+	SetScrollValuator(pWS, VSCROLL_AXIS, SCROLL_TYPE_VERTICAL, 4096, 0);
+
 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12
 	xf86MotionHistoryAllocate(pInfo);
 	AssignTypeAndName(pWS, pInfo->atom, pInfo->name);
@@ -601,6 +624,7 @@
 		int buttons = priv->lastButtons;
 		int dx = 0, dy = 0, dz = 0, dw = 0;
 		int zbutton = 0, wbutton = 0;
+		int hscroll = 0, vscroll = 0;
 
 		ax = 0; ay = 0;
 		switch (event->type) {
@@ -650,6 +674,14 @@
 			DBG(4, ErrorF("Relative W %d\n", event->value));
 			dw = event->value;
 			break;
+		case WSCONS_EVENT_HSCROLL:
+			hscroll = event->value;
+			DBG(4, ErrorF("Horiz. Scrolling %d\n", event->value));
+			break;
+		case WSCONS_EVENT_VSCROLL:
+			vscroll = event->value;
+			DBG(4, ErrorF("Vert. Scrolling %d\n", event->value));
+			break;
 		default:
 			xf86Msg(X_WARNING, "%s: bad wsmouse event type=%d\n",
 			    pInfo->name, event->type);
@@ -694,6 +726,16 @@
 			buttons |= wbutton;
 			dw = 0;
 		}
+		if (hscroll || vscroll) {
+			xf86Msg(X_WARNING, "%s: hscroll=%d, vscroll=%d\n",
+			    pInfo->name, hscroll, vscroll);
+			valuator_mask_zero(priv->scroll_mask);
+			valuator_mask_set_double(priv->scroll_mask,
+			    HSCROLL_AXIS, (double) hscroll);
+			valuator_mask_set_double(priv->scroll_mask,
+			    VSCROLL_AXIS, (double) vscroll);
+			xf86PostMotionEventM(pInfo->dev, FALSE, priv->scroll_mask);
+ 		}
 		if (priv->lastButtons != buttons) {
 			/* button event */
 			wsSendButtons(pInfo, buttons);


Home | Main Index | Thread Index | Old Index