tech-x11 archive

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

Proposed changes for xf86-input-ws to better support tablets and digitizers



Dear tech-x11,

I have used the patch below for a bit, and it suits my use case
quite well. This e-mail requests feedback on whether these changes
are worth integrating for other users.

The patch:

 a) extends the xorg.conf configuration for "ws" to allow minimum
    and maximum Z and W values to be specified (it was already possible
    to do so for X and Y, but Z and W were omitted),
 b) adds a "WS Pointer Pressure Calibration" property for xinput, similar
    to the "WS Pointer Axis Calibration" property,

with the main purpose of supporting pointing devices with pressure data.

-- 
Kind regards,

Yorick Hardy

Index: external/mit/xf86-input-ws/dist/src/ws.h
===================================================================
RCS file: /cvsroot/xsrc/external/mit/xf86-input-ws/dist/src/ws.h,v
retrieving revision 1.3
diff -u -u -r1.3 ws.h
--- external/mit/xf86-input-ws/dist/src/ws.h	1 Jan 2019 00:34:52 -0000	1.3
+++ external/mit/xf86-input-ws/dist/src/ws.h	24 Oct 2019 18:53:16 -0000
@@ -27,7 +27,7 @@
 # define DBG(lvl, f)
 #endif
 
-#define NAXES 2			/* X and Y axes only */
+#define NAXES 4			/* X, Y, Z and W axes */
 #define NBUTTONS 32		/* max theoretical buttons */
 #define DFLTBUTTONS 3		/* default number of buttons */
 #define NUMEVENTS 16		/* max # of ws events to read at once */
@@ -38,6 +38,7 @@
 	unsigned int buttons;	/* # of buttons */
 	unsigned int lastButtons; /* last state of buttons */
 	int min_x, max_x, min_y, max_y; /* coord space */
+	int min_z, max_z, min_w, max_w; /* coord space */
 	int swap_axes;
 	int raw;
 	int inv_x, inv_y;
Index: external/mit/xf86-input-ws/dist/include/ws-properties.h
===================================================================
RCS file: /cvsroot/xsrc/external/mit/xf86-input-ws/dist/include/ws-properties.h,v
retrieving revision 1.1.1.1
diff -u -u -r1.1.1.1 ws-properties.h
--- external/mit/xf86-input-ws/dist/include/ws-properties.h	27 Nov 2009 14:17:19 -0000	1.1.1.1
+++ external/mit/xf86-input-ws/dist/include/ws-properties.h	24 Oct 2019 18:53:37 -0000
@@ -27,6 +27,10 @@
 /* CARD32, 4 values [minx, maxx, miny, maxy], or no values for unset */
 #define WS_PROP_CALIBRATION "WS Pointer Axis Calibration"
 
+/* Run-time pressure calibration */
+/* CARD32, 2 values [minz, maxz], or no values for unset */
+#define WS_PROP_PRESSURE "WS Pointer Pressure Calibration"
+
 /* Swap x and y axis. */
 /* BOOL */
 #define WS_PROP_SWAP_AXES "WS Pointer Axes Swap"
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 -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	24 Oct 2019 18:54:07 -0000
@@ -66,6 +66,7 @@
 static int wsSetProperty(DeviceIntPtr, Atom, XIPropertyValuePtr, BOOL);
 
 static Atom prop_calibration = 0;
+static Atom prop_pressure = 0;
 static Atom prop_swap = 0;
 
 #ifdef DEBUG
@@ -271,7 +272,13 @@
 	priv->max_x = screenInfo.screens[priv->screen_no]->width - 1;
 	priv->min_y = 0;
 	priv->max_y = screenInfo.screens[priv->screen_no]->height - 1;
-	priv->raw = 0;
+	priv->min_z = -1;
+	priv->max_z = -1;
+	priv->min_w = -1;
+	priv->max_w = -1;
+	priv->raw = 0;
+	/* Allow options to override this */
+	priv->raw = xf86SetBoolOption(pInfo->options, "Raw", priv->raw);
 
 	/* don't rely on the device type - we may be listening to a mux */		
 	if (ioctl(pInfo->fd, WSMOUSEIO_GCALIBCOORDS,
@@ -302,6 +309,8 @@
 		xf86Msg(X_CONFIG,
 		    "%s device will work in raw mode\n",
 		    pInfo->name);
+		/* Assume a touch panel / tablet since we are in raw mode */
+		priv->type = WSMOUSE_TYPE_TPANEL;
 	}
 
 	/* Allow options to override this */
@@ -317,6 +326,18 @@
 	priv->max_y = xf86SetIntOption(pInfo->options, "MaxY", priv->max_y);
 	xf86Msg(X_INFO, "%s maximum y position: %d\n",
 	    pInfo->name, priv->max_y);
+	priv->min_z = xf86SetIntOption(pInfo->options, "MinZ", priv->min_z);
+	xf86Msg(X_INFO, "%s minimum z position: %d\n",
+	    pInfo->name, priv->min_z);
+	priv->max_z = xf86SetIntOption(pInfo->options, "MaxZ", priv->max_z);
+	xf86Msg(X_INFO, "%s maximum z position: %d\n",
+	    pInfo->name, priv->max_z);
+	priv->min_w = xf86SetIntOption(pInfo->options, "MinW", priv->min_w);
+	xf86Msg(X_INFO, "%s minimum w position: %d\n",
+	    pInfo->name, priv->min_w);
+	priv->max_w = xf86SetIntOption(pInfo->options, "MaxW", priv->max_w);
+	xf86Msg(X_INFO, "%s maximum w position: %d\n",
+	    pInfo->name, priv->max_w);
 
 	pInfo->device_control = wsProc;
 	pInfo->read_input = wsReadInput;
@@ -405,7 +426,7 @@
 	InputInfoPtr pInfo = (InputInfoPtr)pWS->public.devicePrivate;
 	WSDevicePtr priv = (WSDevicePtr)pInfo->private;
 	unsigned char map[NBUTTONS + 1];
-	int i, xmin, xmax, ymin, ymax;
+	int i, xmin, xmax, ymin, ymax, zmin, zmax, wmin, wmax;
 	Atom btn_labels[NBUTTONS] = {0};
 	Atom axes_labels[NAXES] = {0};
 
@@ -434,6 +455,11 @@
 		ymax = -1;
 	}
 
+	zmin = priv->min_z;
+	zmax = priv->max_z;
+	wmin = priv->min_w;
+	wmax = priv->max_w;
+
 	if (priv->swap_axes) {
 		int tmp;
 		tmp = xmin;
@@ -446,9 +472,13 @@
 	if ((priv->type == WSMOUSE_TYPE_TPANEL)) {
 		axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X);
 		axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y);
+		axes_labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_PRESSURE);
+		axes_labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_DISTANCE);
 	} else {
 		axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
 		axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
+		axes_labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Z);
+		axes_labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_WHEEL);
 	}
 	if (!InitValuatorClassDeviceStruct(pWS,
 		NAXES,
@@ -478,6 +508,24 @@
 	);
 	xf86InitValuatorDefaults(pWS, 1);
 
+	xf86InitValuatorAxisStruct(pWS, 2,
+	    axes_labels[2],
+	    zmin, zmax, 1, 0, 1
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
+	    , priv->type == WSMOUSE_TYPE_TPANEL  ? Absolute : Relative
+#endif
+	);
+	xf86InitValuatorDefaults(pWS, 2);
+
+	xf86InitValuatorAxisStruct(pWS, 3,
+	    axes_labels[3],
+	    wmin, wmax, 1, 0, 1
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
+	    , priv->type == WSMOUSE_TYPE_TPANEL ? Absolute : Relative
+#endif
+	);
+	xf86InitValuatorDefaults(pWS, 3);
+
 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12
 	xf86MotionHistoryAllocate(pInfo);
 	AssignTypeAndName(pWS, pInfo->atom, pInfo->name);
@@ -582,7 +630,7 @@
 	int n, c;
 	struct wscons_event *event = eventList;
 	unsigned char *pBuf;
-	int ax, ay;
+	int ax, ay, az, aw;
 
 	priv = pInfo->private;
 
@@ -602,7 +650,7 @@
 		int dx = 0, dy = 0, dz = 0, dw = 0;
 		int zbutton = 0, wbutton = 0;
 
-		ax = 0; ay = 0;
+		ax = 0; ay = 0; az = 0; aw = 0;
 		switch (event->type) {
 		case WSCONS_EVENT_MOUSE_UP:
 
@@ -642,14 +690,15 @@
 			dz = event->value;
 			break;
 		case WSCONS_EVENT_MOUSE_ABSOLUTE_Z:
-			/* ignore those */
-			++event;
-			continue;
+			az = event->value;
 			break;
 		case WSCONS_EVENT_MOUSE_DELTA_W:
 			DBG(4, ErrorF("Relative W %d\n", event->value));
 			dw = event->value;
 			break;
+		case WSCONS_EVENT_MOUSE_ABSOLUTE_W:
+			aw = event->value;
+			break;
 		default:
 			xf86Msg(X_WARNING, "%s: bad wsmouse event type=%d\n",
 			    pInfo->name, event->type);
@@ -720,6 +769,16 @@
 			DBG(3, ErrorF("postMotionEvent y %d\n", ay));
 			xf86PostMotionEvent(pInfo->dev, 1, 1, 1, ay);
 		}
+		if (az) {
+			/* absolute position event */
+			DBG(3, ErrorF("postMotionEvent Z %d\n", az));
+			xf86PostMotionEvent(pInfo->dev, 1, 2, 1, az);
+		}
+		if (aw) {
+			/* absolute position event */
+			DBG(3, ErrorF("postMotionEvent W %d\n", aw));
+			xf86PostMotionEvent(pInfo->dev, 1, 3, 1, aw);
+		}
 		++event;
 	}
 	return;
@@ -823,6 +882,13 @@
 
 	XISetDevicePropertyDeletable(device, prop_calibration, FALSE);
 
+	prop_pressure = MakeAtom(WS_PROP_PRESSURE,
+	    strlen(WS_PROP_PRESSURE), TRUE);
+	rc = XIChangeDeviceProperty(device, prop_pressure, XA_INTEGER, 32,
+	    PropModeReplace, 2, &priv->min_z, FALSE);
+	if (rc != Success)
+		return;
+
 	prop_swap = MakeAtom(WS_PROP_SWAP_AXES,
 	    strlen(WS_PROP_SWAP_AXES), TRUE);
 	rc = XIChangeDeviceProperty(device, prop_swap, XA_INTEGER, 8,
@@ -841,7 +907,8 @@
 	struct wsmouse_calibcoords coords;
 	int need_update = 0;
 	AxisInfoPtr ax = device->valuator->axes,
-		    ay = device->valuator->axes + 1;
+		    ay = device->valuator->axes + 1,
+		    az = device->valuator->axes + 2;
 
 	DBG(1, ErrorF("wsSetProperty %s\n", NameForAtom(atom)));
 
@@ -884,6 +951,26 @@
 				ay->max_value = priv->max_x;
 			}
 		}
+	} else if (atom == prop_pressure) {
+		if (val->format != 32 || val->type != XA_INTEGER)
+			return BadMatch;
+		if (val->size != 2 && val->size != 0)
+			return BadMatch;
+		if (!checkonly) {
+			if (val->size == 0) {
+				DBG(1, ErrorF(" uncalibrate pressure\n"));
+				priv->min_z = 0;
+				priv->max_z = -1;
+			} else {
+				priv->min_z = ((int *)(val->data))[0];
+				priv->max_z = ((int *)(val->data))[1];
+				DBG(1, ErrorF(" calibrate pressure %d %d\n",
+					priv->min_z, priv->max_z));
+			}
+			/* Update axes descriptors */
+			az->min_value = priv->min_z;
+			az->max_value = priv->max_z;
+		}
 	} else if (atom == prop_swap) {
 		if (val->format != 8 || val->type != XA_INTEGER ||
 		    val->size != 1)
Index: external/mit/xf86-input-ws/dist/man/ws.man
===================================================================
RCS file: /cvsroot/xsrc/external/mit/xf86-input-ws/dist/man/ws.man,v
retrieving revision 1.3
diff -u -r1.3 ws.man
--- external/mit/xf86-input-ws/dist/man/ws.man	2 Aug 2011 09:30:15 -0000	1.3
+++ external/mit/xf86-input-ws/dist/man/ws.man	25 Oct 2019 19:25:51 -0000
@@ -143,6 +143,9 @@
 1 boolean value (8 bits, 0 or 1). 1 swaps x/y axes. This property
 is present only for devices with absolute coordinates (ie
 tablets and touchscreens).
+.TP 7
+.BI "WS Pointer Pressure Calibration"
+2 32 bits values, in the order min-z, max-z.
 
 .SH "SEE ALSO"
 __xservername__(1), xinput(1), __xconfigfile__(__filemansuffix__),


Home | Main Index | Thread Index | Old Index