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