summaryrefslogtreecommitdiff
path: root/src/ws.c
diff options
context:
space:
mode:
authorMatthieu Herrb <matthieu@openbsd.org>2009-11-25 18:10:26 +0000
committerMatthieu Herrb <matthieu@openbsd.org>2009-11-25 18:10:26 +0000
commit8f301ca04fca91fcba4d8f6f70200b4f9a006d66 (patch)
tree02d837cbb1b7fd97952f92aff9850e56b291936e /src/ws.c
parent4d60b61a606d333bc76b420ba80174be672d35c0 (diff)
Implement device properties for calibration data.
Setting the properties also write to the kernel table. The calibration code can now change the data without quitting X.
Diffstat (limited to 'src/ws.c')
-rw-r--r--src/ws.c130
1 files changed, 130 insertions, 0 deletions
diff --git a/src/ws.c b/src/ws.c
index d838244..f90482f 100644
--- a/src/ws.c
+++ b/src/ws.c
@@ -36,6 +36,16 @@
#include <mipointer.h>
#include <extinit.h>
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3
+#define HAVE_PROPERTIES 1
+#endif
+
+#ifdef HAVE_PROPERTIES
+#include <X11/Xatom.h>
+#include "ws-properties.h"
+#endif
+
+
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
#include <X11/Xatom.h>
#include <xserver-properties.h>
@@ -81,6 +91,13 @@ static Bool wsOpen(InputInfoPtr);
static void wsClose(InputInfoPtr);
static void wsControlProc(DeviceIntPtr , PtrCtrl *);
+#ifdef HAVE_PROPERTIES
+static void wsInitProperty(DeviceIntPtr);
+static int wsSetProperty(DeviceIntPtr, Atom, XIPropertyValuePtr, BOOL);
+
+static Atom prop_calibration = 0;
+static Atom prop_swap = 0;
+#endif
static XF86ModuleVersionInfo VersionRec = {
"ws",
@@ -471,6 +488,10 @@ wsDeviceInit(DeviceIntPtr pWS)
if (wsOpen(pInfo) != Success) {
return !Success;
}
+#ifdef HAVE_PROPERTIES
+ wsInitProperty(pWS);
+ XIRegisterPropertyHandler(pWS, wsSetProperty, NULL, NULL);
+#endif
return Success;
}
@@ -772,3 +793,112 @@ wsControlProc(DeviceIntPtr device, PtrCtrl *ctrl)
priv->den = ctrl->den;
priv->threshold = ctrl->threshold;
}
+
+#ifdef HAVE_PROPERTIES
+static void
+wsInitProperty(DeviceIntPtr device)
+{
+ InputInfoPtr pInfo = device->public.devicePrivate;
+ WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+ int rc;
+
+ DBG(1, ErrorF("wsInitProperty\n"));
+ if (priv->type != WSMOUSE_TYPE_TPANEL)
+ return;
+
+ prop_calibration = MakeAtom(WS_PROP_CALIBRATION,
+ strlen(WS_PROP_CALIBRATION), TRUE);
+ rc = XIChangeDeviceProperty(device, prop_calibration, XA_INTEGER, 32,
+ PropModeReplace, 4, &priv->min_x, FALSE);
+ if (rc != Success)
+ return;
+
+ XISetDevicePropertyDeletable(device, prop_calibration, FALSE);
+
+ prop_swap = MakeAtom(WS_PROP_SWAP_AXES,
+ strlen(WS_PROP_SWAP_AXES), TRUE);
+ rc = XIChangeDeviceProperty(device, prop_swap, XA_INTEGER, 8,
+ PropModeReplace, 1, &priv->swap_axes, FALSE);
+ if (rc != Success)
+ return;
+ return;
+}
+
+static int
+wsSetProperty(DeviceIntPtr device, Atom atom, XIPropertyValuePtr val,
+ BOOL checkonly)
+{
+ InputInfoPtr pInfo = device->public.devicePrivate;
+ WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+ struct wsmouse_calibcoords coords;
+ int need_update = 0;
+
+ DBG(1, ErrorF("wsSetProperty\n"));
+
+ /* Ignore non panel devices */
+ if (priv->type != WSMOUSE_TYPE_TPANEL)
+ return Success;
+
+ if (atom == prop_calibration) {
+ if (val->format != 32 || val->type != XA_INTEGER)
+ return BadMatch;
+ if (val->size != 4 && val->size != 0)
+ return BadMatch;
+ if (!checkonly) {
+ if (val->size == 0) {
+ DBG(1, ErrorF(" uncalibrate\n"));
+ priv->min_x = 0;
+ priv->max_x = -1;
+ priv->min_y = 0;
+ priv->max_y = -1;
+ } else {
+ priv->min_x = ((int *)(val->data))[0];
+ priv->max_x = ((int *)(val->data))[1];
+ priv->min_y = ((int *)(val->data))[2];
+ priv->max_y = ((int *)(val->data))[3];
+ DBG(1, ErrorF(" calibrate %d %d %d %d\n",
+ priv->min_x, priv->max_x,
+ priv->min_y, priv->max_y));
+ need_update++;
+ }
+ /* Update axes descriptors */
+ InitValuatorAxisStruct(device, 0,
+ priv->min_x, priv->max_x, 1, 0, 1);
+ InitValuatorAxisStruct(device, 1,
+ priv->min_y, priv->max_y, 1, 0, 1);
+ }
+ } else if (atom == prop_swap) {
+ if (val->format != 8 || val->type != XA_INTEGER ||
+ val->size != 1)
+ return BadMatch;
+ if (!checkonly) {
+ priv->swap_axes = *((BOOL *)val->data);
+ DBG(1, ErrorF("swap_axes %d\n", priv->swap_axes));
+ need_update++;
+ }
+ } else {
+ return BadMatch;
+ }
+ if (need_update) {
+ /* Update the saved values to be restored on device off */
+ priv->coords.minx = priv->min_x;
+ priv->coords.maxx = priv->max_x;
+ priv->coords.miny = priv->min_y;
+ priv->coords.maxy = priv->max_y;
+ priv->coords.swapxy = priv->swap_axes;
+
+ /* Update the kernel calibration table */
+ coords.minx = priv->min_x;
+ coords.maxx = priv->max_x;
+ coords.miny = priv->min_y;
+ coords.maxy = priv->max_y;
+ coords.swapxy = priv->swap_axes;
+ coords.samplelen = priv->raw;
+ if (ioctl(pInfo->fd, WSMOUSEIO_SCALIBCOORDS, &coords) != 0) {
+ xf86Msg(X_ERROR, "SCALIBCOORDS failed %s\n",
+ strerror(errno));
+ }
+ }
+ return Success;
+}
+#endif