319 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			319 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * Copyright 2001,2002 Red Hat Inc., Durham, North Carolina.
 | |
|  *
 | |
|  * All Rights Reserved.
 | |
|  *
 | |
|  * Permission is hereby granted, free of charge, to any person obtaining
 | |
|  * a copy of this software and associated documentation files (the
 | |
|  * "Software"), to deal in the Software without restriction, including
 | |
|  * without limitation on the rights to use, copy, modify, merge,
 | |
|  * publish, distribute, sublicense, and/or sell copies of the Software,
 | |
|  * and to permit persons to whom the Software is furnished to do so,
 | |
|  * subject to the following conditions:
 | |
|  *
 | |
|  * The above copyright notice and this permission notice (including the
 | |
|  * next paragraph) shall be included in all copies or substantial
 | |
|  * portions of the Software.
 | |
|  *
 | |
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | |
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | |
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | |
|  * NON-INFRINGEMENT.  IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
 | |
|  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 | |
|  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | |
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | |
|  * SOFTWARE.
 | |
|  */
 | |
| 
 | |
| /*
 | |
|  * Authors:
 | |
|  *   Rickard E. (Rik) Faith <faith@redhat.com>
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| #include <X11/Xlib.h>
 | |
| #include <X11/XKBlib.h>
 | |
| #include <X11/extensions/XInput.h>
 | |
| #include <X11/extensions/XKB.h>
 | |
| #include <X11/extensions/XKBstr.h>
 | |
| #include <X11/extensions/dmxext.h>
 | |
| #include <sys/time.h>
 | |
| 
 | |
| static const char *core(DMXInputAttributes *iinf)
 | |
| {
 | |
|     if (iinf->isCore)         return "core";
 | |
|     else if (iinf->sendsCore) return "extension (sends core events)";
 | |
|     else                      return "extension";
 | |
| }
 | |
| 
 | |
| static void printdmxinfo(Display *display, int id)
 | |
| {
 | |
|     int                  event_base;
 | |
|     int                  error_base;
 | |
|     int                  major_version, minor_version, patch_version;
 | |
|     DMXInputAttributes   iinf;
 | |
|     Display              *backend;
 | |
|     char                 *backendname = NULL;
 | |
| 
 | |
|     if (!DMXQueryExtension(display, &event_base, &error_base)) return;
 | |
|     if (!DMXQueryVersion(display, &major_version, &minor_version,
 | |
|                          &patch_version)) return;
 | |
|     if (major_version == 1 && minor_version == 0) return; /* too old */
 | |
|     if (!DMXGetInputAttributes(display, id, &iinf)) return;
 | |
| 
 | |
|     printf("   DMX Information: ");
 | |
|     if (iinf.detached) printf("detached ");
 | |
|     else               printf("active   ");
 | |
|     switch (iinf.inputType) {
 | |
|     case DMXLocalInputType:
 | |
|         printf("local, %s", core(&iinf));
 | |
|         break;
 | |
|     case DMXConsoleInputType:
 | |
|         printf("console %s, %s", iinf.name, core(&iinf));
 | |
|         break;
 | |
|     case DMXBackendInputType:
 | |
|         if (iinf.physicalId >= 0) {
 | |
|             if ((backend = XOpenDisplay(iinf.name))) {
 | |
|                 XExtensionVersion *ext = XGetExtensionVersion(backend, INAME);
 | |
|                 if (ext && ext != (XExtensionVersion *)NoSuchExtension) {
 | |
|                     int count, i;
 | |
|                     XDeviceInfo *devInfo = XListInputDevices(backend, &count);
 | |
|                     if (devInfo) {
 | |
|                         for (i = 0; i < count; i++) {
 | |
|                             if ((unsigned)iinf.physicalId == devInfo[i].id
 | |
|                                 && devInfo[i].name) {
 | |
|                                 backendname = strdup(devInfo[i].name);
 | |
|                                 break;
 | |
|                             }
 | |
|                         }
 | |
|                         XFreeDeviceList(devInfo);
 | |
|                     }
 | |
|                 }
 | |
|                 XCloseDisplay(backend);
 | |
|             }
 | |
|         }
 | |
|         printf("backend o%d/%s",iinf.physicalScreen,  iinf.name);
 | |
|         if (iinf.physicalId >= 0) printf("/id%d", iinf.physicalId);
 | |
|         if (backendname) {
 | |
|             printf("=%s", backendname);
 | |
|             free(backendname);
 | |
|         }
 | |
|         printf(" %s", core(&iinf));
 | |
|         break;
 | |
|     }
 | |
|     printf("\n");
 | |
| }
 | |
| 
 | |
| int main(int argc, char **argv)
 | |
| {
 | |
|     Display              *display = NULL;
 | |
|     int                  device   = -1;
 | |
|     int                  newmouse = -1;
 | |
|     int                  newkbd   = -1;
 | |
|     int                  count;
 | |
|     int                  i, j;
 | |
|     XDeviceInfo          *devInfo;
 | |
|     XExtensionVersion    *ext;
 | |
| 
 | |
|     if (argc == 2 || argc == 3 || argc == 4 || argc == 5) {
 | |
|         if (!(display = XOpenDisplay(argv[1]))) {
 | |
|             printf("Cannot open display %s\n", argv[1]);
 | |
|             return -1;
 | |
|         }
 | |
|         if (argc >= 3) device   = strtol(argv[2], NULL, 0);
 | |
|         if (argc >= 4) newmouse = strtol(argv[3], NULL, 0);
 | |
|         if (argc >= 5) newkbd   = strtol(argv[4], NULL, 0);
 | |
|     } else {
 | |
|         printf("Usage: %s display [device] [newmouse] [newkbd]\n", argv[0]);
 | |
|         return -1;
 | |
|     }
 | |
| 
 | |
|     if (!display && !(display = XOpenDisplay(NULL))) {
 | |
|         printf("Cannot open default display\n");
 | |
|         return -1;
 | |
|     }
 | |
| 
 | |
|     ext = XGetExtensionVersion(display, INAME);
 | |
|     if (!ext || ext == (XExtensionVersion *)NoSuchExtension) {
 | |
|         printf("No XInputExtension\n");
 | |
|         return -1;
 | |
|     }
 | |
|     printf("%s version %d.%d\n",
 | |
|            INAME, ext->major_version, ext->minor_version);
 | |
| 
 | |
|     if (!(devInfo = XListInputDevices(display, &count)) || !count) {
 | |
|         printf("Cannot list devices\n");
 | |
|         return -1;
 | |
|     }
 | |
| 
 | |
|     for (i = 0; i < count; i++) {
 | |
|         XAnyClassPtr any;
 | |
|         const char   *kind   = "Unknown";
 | |
|         int          has_key = 0;
 | |
|         
 | |
|         switch (devInfo[i].use) {
 | |
|         case IsXPointer:         kind = "XPointer";         break;
 | |
|         case IsXKeyboard:        kind = "XKeyboard";        break;
 | |
|         case IsXExtensionDevice: kind = "XExtensionDevice"; break;
 | |
|         }
 | |
|         printf("%2lu %-20.20s %-16.16s",
 | |
|                (long unsigned)devInfo[i].id,
 | |
|                devInfo[i].name ? devInfo[i].name : "", kind);
 | |
| 
 | |
|         for (j = 0, any = devInfo[i].inputclassinfo;
 | |
|              j < devInfo[i].num_classes;
 | |
|              any = (XAnyClassPtr)((char *)any + any->length), j++) {
 | |
|             const char   *class = "unk";
 | |
|             switch (any->class) {
 | |
|             case KeyClass:       class = "key"; ++has_key; break;
 | |
|             case ButtonClass:    class = "btn"; break;
 | |
|             case ValuatorClass:  class = "val"; break;
 | |
|             case FeedbackClass:  class = "fdb"; break;
 | |
|             case ProximityClass: class = "prx"; break;
 | |
|             case FocusClass:     class = "foc"; break;
 | |
|             case OtherClass:     class = "oth"; break;
 | |
|             }
 | |
|             printf(" %s", class);
 | |
|         }
 | |
|         printf("\n");
 | |
|         printdmxinfo(display, i);
 | |
| 
 | |
|         if (has_key) {
 | |
|             XkbDescPtr           xkb;
 | |
|             if ((xkb = XkbGetKeyboard(display,
 | |
|                                       XkbAllComponentsMask,
 | |
|                                       devInfo[i].id))) {
 | |
|                 printf("   Xkb Information:\n");
 | |
|                 printf("      Device id = %d\n", xkb->device_spec);
 | |
|                 printf("      Min keycode = 0x%02x\n", xkb->min_key_code);
 | |
|                 printf("      Max keycode = 0x%02x\n", xkb->max_key_code);
 | |
| #define PRINTNAME(x)                                                     \
 | |
|     printf("      %s = %s\n",                                            \
 | |
|            #x, xkb->names->x ? XGetAtomName(display, xkb->names->x) : "")
 | |
|                 PRINTNAME(keycodes);
 | |
|                 PRINTNAME(geometry);
 | |
|                 PRINTNAME(symbols);
 | |
|                 PRINTNAME(types);
 | |
|                 PRINTNAME(compat);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (newmouse >= 0) {
 | |
|         XDevice     *dev;
 | |
| 
 | |
|         printf("Trying to make device %d core mouse\n", newmouse);
 | |
|         dev = XOpenDevice(display, devInfo[newmouse].id);
 | |
|         printf("Status = %d\n",
 | |
|                XChangePointerDevice(display, dev, 0, 1));
 | |
|         return 0;
 | |
|     }
 | |
| 
 | |
|     if (newkbd >= 0) {
 | |
|         XDevice     *dev;
 | |
| 
 | |
|         printf("Trying to make device %d core keyboard\n", newkbd);
 | |
|         dev = XOpenDevice(display, devInfo[newkbd].id);
 | |
|         printf("Status = %d\n",
 | |
|                XChangeKeyboardDevice(display, dev));
 | |
|         return 0;
 | |
|     }
 | |
|             
 | |
| 
 | |
|     if (device >=0){
 | |
| #define MAX_EVENTS 100
 | |
|         int         cnt = 0;
 | |
|         XDevice     *dev;
 | |
|         XEventClass event_list[MAX_EVENTS];
 | |
|         int         event_type[MAX_EVENTS];
 | |
|         const char  *names[MAX_EVENTS];
 | |
|         int         total = 0;
 | |
| 
 | |
| #define ADD(type)                                     \
 | |
|         if (cnt >= MAX_EVENTS) abort();               \
 | |
|         names[cnt] = #type;                           \
 | |
|         type(dev, event_type[cnt], event_list[cnt]);  \
 | |
|         if (event_type[cnt]) ++cnt
 | |
|         
 | |
| 
 | |
|         dev = XOpenDevice(display, devInfo[device].id);
 | |
|         ADD(DeviceKeyPress);
 | |
|         ADD(DeviceKeyRelease);
 | |
|         ADD(DeviceButtonPress);
 | |
|         ADD(DeviceButtonRelease);
 | |
|         ADD(DeviceMotionNotify);
 | |
|         ADD(DeviceFocusIn);
 | |
|         ADD(DeviceFocusOut);
 | |
|         ADD(ProximityIn);
 | |
|         ADD(ProximityOut);
 | |
|         ADD(DeviceStateNotify);
 | |
|         ADD(DeviceMappingNotify);
 | |
|         ADD(ChangeDeviceNotify);
 | |
|         
 | |
|         for (i = 0; i < cnt; i++) {
 | |
|             printf("Waiting for %s events of type %d (%lu) on 0x%08lx\n",
 | |
|                    names[i],
 | |
|                    event_type[i], (unsigned long)event_list[i],
 | |
|                    (long unsigned)DefaultRootWindow(display));
 | |
|         }
 | |
|         XSelectExtensionEvent(display, DefaultRootWindow(display),
 | |
|                               event_list, cnt);
 | |
|         
 | |
|         for (;;) {
 | |
|             XEvent event;
 | |
|             XNextEvent(display, &event);
 | |
|             for (i = 0; i < cnt; i++) {
 | |
|                 XDeviceMotionEvent *e = (XDeviceMotionEvent *)&event;
 | |
|                 XDeviceButtonEvent *b = (XDeviceButtonEvent *)&event;
 | |
|                 if (event.type == event_type[i]) {
 | |
|                     printf("%s id=%lu (%d @ %d,%d; s=0x%04x, d=%d, t=%lu)"
 | |
|                            " axes_count=%d first=%d %d %d %d %d %d %d\n",
 | |
|                            names[i],
 | |
|                            (long unsigned)e->deviceid,
 | |
|                            e->type,
 | |
|                            e->x, e->y,
 | |
|                            e->device_state,
 | |
|                            b->button,
 | |
|                            (long unsigned)b->time,
 | |
|                            e->axes_count,
 | |
|                            e->first_axis,
 | |
|                            e->axis_data[0],
 | |
|                            e->axis_data[1],
 | |
|                            e->axis_data[2],
 | |
|                            e->axis_data[3],
 | |
|                            e->axis_data[4],
 | |
|                            e->axis_data[5]);
 | |
|                 }
 | |
|             }
 | |
|             ++total;
 | |
| #if 0
 | |
|                                 /* Used to check motion history for
 | |
|                                  * extension devices. */
 | |
|             if (!(total % 10)) {
 | |
|                 XDeviceTimeCoord *tc;
 | |
|                 int              n, m, a;
 | |
|                 struct timeval   tv;
 | |
|                 unsigned long    ms;
 | |
|                 gettimeofday(&tv, NULL);
 | |
|                 ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
 | |
|                 tc = XGetDeviceMotionEvents(display, dev, ms-1000, ms,
 | |
|                                             &n, &m, &a);
 | |
|                 printf("Got %d events of mode %s with %d axes\n",
 | |
|                        n, m == Absolute ? "Absolute" : "Relative", a);
 | |
|                 for (i = 0; i < n && i < 10; i++) {
 | |
|                     printf("  %d: %lu %d %d\n",
 | |
|                            i, tc[i].time, tc[i].data[0], tc[i].data[1]);
 | |
|                 }
 | |
|                 XFreeDeviceMotionEvents(tc);
 | |
|             }
 | |
| #endif                
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     XCloseDisplay(display);
 | |
|     return 0;
 | |
| }
 |