356 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			356 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;
 | 
						|
}
 |