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;
|
|
}
|