diff options
author | Matthieu Herrb <matthieu@openbsd.org> | 2009-11-25 18:10:26 +0000 |
---|---|---|
committer | Matthieu Herrb <matthieu@openbsd.org> | 2009-11-25 18:10:26 +0000 |
commit | 8f301ca04fca91fcba4d8f6f70200b4f9a006d66 (patch) | |
tree | 02d837cbb1b7fd97952f92aff9850e56b291936e /src | |
parent | 4d60b61a606d333bc76b420ba80174be672d35c0 (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')
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/ws.c | 130 |
2 files changed, 132 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 50ece5d..1ed52fa 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -19,4 +19,6 @@ AM_CFLAGS = $(XORG_CFLAGS) @DRIVER_NAME@_drv_la_LDFLAGS= -module -avoid-version @DRIVER_NAME@_drv_ladir= @inputdir@ +INCLUDES=-I$(top_srcdir)/include/ + @DRIVER_NAME@_drv_la_SOURCES = @DRIVER_NAME@.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 |