absolute coordinate mouse support

Alex Williamson alex.williamson at hp.com
Wed Sep 21 12:40:28 PDT 2005


On Wed, 2005-09-21 at 15:16 -0400, Adam Jackson wrote:
> On Wednesday 21 September 2005 14:07, Alex Williamson wrote:
> > On Wed, 2005-09-21 at 13:50 -0400, James Cloos wrote:
> > > >>>>> "Alex" == Alex Williamson <alex.williamson at hp.com> writes:
> > >
> > > Alex> an tell me to switch to something besides the X "mouse" driver
> > >
> > > Perhaps evdev does what you want.
> >
> >    Yes, I was just looking into that, thanks for mentioning it.  The
> > evdev driver apparently ignores absolute data at the moment, but I think
> > I can add that without too much problem.  Probably missing just because
> > absolute coordinate devices aren't nearly as common.
> 
> There's an open bug for some absolute pointer support in evdev, it's one of 
> the blockers on #968 and I'd like to see it merged.

  Thanks for the pointer, I've grabbed the 6.8.2-2 patch from that bug
and have been adding support.  Not being an X hacker, I'm sure it's
hideous, but it's a start and it works.  Patch attached below if anyone
cares to comment on it.  I'll attach it to the bug after I fiddle with
it a little more.

[snip]
> Unfortunately I don't know any good way to detect what sort of device is being 
> examined.  We could probably add a flag for this to the evdev protocol, but 
> we'd still need an option to set this for older kernels.

   I don't think it's necessary to care what kind of device you're
talking to.  All we care about is that EV_ABS data is coming in and we
need to post it as a motion event.  There already appear to be all the
flags we need.  Thanks,

	Alex

-- 
Alex Williamson                             HP Linux & Open Source Lab


--- evdev.c.orig	2005-09-21 11:53:17.000000000 -0600
+++ evdev.c	2005-09-21 13:28:01.000000000 -0600
@@ -66,6 +66,19 @@
 static int wheel_left_button = 6;
 static int wheel_right_button = 7;
 
+typedef struct _EvDevRec {
+    int min_x;
+    int max_x;
+    int old_x;
+    int min_y;
+    int max_y;
+    int old_y;
+    int screen_num;
+    int screen_width;
+    int screen_height;
+
+} EvDevRec, *EvDevPtr;
+
 static void
 PostButtonClicks(InputInfoPtr pInfo, int button, int count)
 {
@@ -80,10 +93,12 @@
 static void
 EvdevReadInput(InputInfoPtr pInfo)
 {
+    EvDevPtr pEv;
     struct input_event ev;
     int len, value;
     int dx, dy;
 
+    pEv = (EvDevPtr)pInfo->private;
     dx = 0;
     dy = 0;
 
@@ -127,6 +142,20 @@
             break;
 
         case EV_ABS:
+            switch (ev.code) {
+            case ABS_X:
+                pEv->old_x = xf86ScaleAxis(value, 0, pEv->screen_width,
+                                           pEv->min_x, pEv->max_x);
+        	xf86PostMotionEvent(pInfo->dev, 1, 0, 2, pEv->old_x, pEv->old_y);
+		
+                break;
+
+            case ABS_Y:
+                pEv->old_y = xf86ScaleAxis(value, 0, pEv->screen_height,
+                                           pEv->min_y, pEv->max_y);
+        	xf86PostMotionEvent(pInfo->dev, 1, 0, 2, pEv->old_x, pEv->old_y);
+                break;
+            }
             break;
 
         case EV_KEY:
@@ -464,8 +493,14 @@
 EvdevInit(DeviceIntPtr device)
 {
     InputInfoPtr pInfo;
+    EvDevPtr pEv;
 
     pInfo = device->public.devicePrivate;
+    pEv = (EvDevPtr)pInfo->private;
+
+    pEv->screen_num = 0; /* FIXME */
+    pEv->screen_width = screenInfo.screens[pEv->screen_num]->width;
+    pEv->screen_height = screenInfo.screens[pEv->screen_num]->height;
 
     /* FIXME: This doesn't add buttons for keyboards with
      * scrollwheels. */
@@ -536,7 +571,9 @@
 {
     char key_bitmask[(KEY_MAX + 7) / 8];
     char rel_bitmask[(REL_MAX + 7) / 8];
-    int i, has_axes, has_buttons, has_keys;
+    char abs_bitmask[(ABS_MAX + 7) / 8];
+    int i, has_axes, has_buttons, has_keys, nValues[5];
+    EvDevPtr pEv;
 
     if (ioctl(pInfo->fd, 
               EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) < 0) {
@@ -544,6 +581,12 @@
         return;
     }
 
+    if (ioctl(pInfo->fd, 
+              EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) < 0) {
+        xf86Msg(X_ERROR, "ioctl EVIOCGBIT failed: %s\n", strerror(errno));
+        return;
+    }
+
     if (ioctl(pInfo->fd,
               EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) < 0) {
         xf86Msg(X_ERROR, "ioctl EVIOCGBIT failed: %s\n", strerror(errno));
@@ -559,6 +602,25 @@
 	has_axes = TRUE;
     }
       
+    if (TestBit(ABS_X, abs_bitmask) && TestBit(ABS_Y, abs_bitmask)) {
+	pEv = (EvDevPtr)pInfo->private;
+
+	if (ioctl(pInfo->fd, EVIOCGABS(ABS_X), nValues) == 0) {
+            pEv->min_x = nValues[1];
+            pEv->max_x = nValues[2];
+        }
+
+	if (ioctl(pInfo->fd, EVIOCGABS(ABS_Y), nValues) == 0) {
+            pEv->min_y = nValues[1];
+            pEv->max_y = nValues[2];
+        }
+
+        xf86Msg(X_INFO, "%s: Found x (%d-%d) and y (%d-%d) absolute axes\n",
+                pInfo->name,pEv->min_x, pEv->max_x,
+                pEv->min_y, pEv->max_y);
+	has_axes = TRUE;
+    }
+      
 
     if (TestBit(BTN_LEFT, key_bitmask)) {
         xf86Msg(X_INFO, "%s: Found mouse buttons\n", pInfo->name);
@@ -601,6 +663,7 @@
     InputInfoPtr pInfo;
     MessageType deviceFrom = X_CONFIG;
     const char *device;
+    EvDevPtr pEv;
 
     if (!(pInfo = xf86AllocateInput(drv, 0)))
 	return NULL;
@@ -623,6 +686,10 @@
     pInfo->always_core_feedback = 0;
     pInfo->conf_idev = dev;
 
+    if (!(pEv = xcalloc(sizeof(EvDevRec), 1)))
+        return pInfo;
+    pInfo->private = pEv;
+
     xf86CollectInputOptions(pInfo, NULL, NULL);
     xf86ProcessCommonOptions(pInfo, pInfo->options); 
 





More information about the xorg mailing list