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