/** * Toggle touchpad enabled/disabled state, decided by value. */ static void toggle_touchpad(Bool enable) { unsigned char data; if (pad_disabled && enable) { data = previous_state; pad_disabled = False; if (verbose) printf("Enable\n"); } else if (!pad_disabled && !enable && previous_state != disable_state && previous_state != TouchpadOff) { store_current_touchpad_state(); pad_disabled = True; data = disable_state; if (verbose) printf("Disable\n"); } else return; /* This potentially overwrites a different client's setting, but ... */ XChangeDeviceProperty(display, dev, touchpad_off_prop, XA_INTEGER, 8, PropModeReplace, &data, 1); XFlush(display); }
void synaptics_disable_3fingers_tap(Grabber* self, XDevice* dev) { Atom prop, type; double val; int format; unsigned long nitems, bytes_after; unsigned char* data = NULL; prop = XInternAtom(self->dpy, SYNAPTICS_PROP_TAP_ACTION, True); /* get current configuration */ XGetDeviceProperty(self->dpy, dev, prop, 0, 1000, False, AnyPropertyType, &type, &format, &nitems, &bytes_after, &data); char* b = (char*) data; int offset = 6; // the position of 3TAP_FINGER inside config /* change configuration if needed */ if (b[offset] != 0) { b[offset] = 0;//rint(val); XChangeDeviceProperty(self->dpy, dev, prop, type, format, PropModeReplace, data, nitems); XFlush(self->dpy); } }
int uncalibrate(XDevice *device) { Atom type; int format; unsigned long nitems, nbytes; long values[4] = { 0, 32767, 0, 32767 }; /* uncalibrated */ Bool swap = 0; unsigned char *retval; /* Save old values */ XGetDeviceProperty(display, device, prop_calibration, 0, 4, False, XA_INTEGER, &type, &format, &nitems, &nbytes, &retval); if (type != XA_INTEGER) { fprintf(stderr, "Device property \"%s\": invalid type %s\n", WS_PROP_CALIBRATION, XGetAtomName(display, type)); return -1; } if (nitems != 4 && nitems != 0) { fprintf(stderr, "Device property \"%s\": " "invalid number of items %ld\n", WS_PROP_CALIBRATION, nitems); return -1; } old_calib.minx = *(long *)retval; old_calib.maxx = *((long *)retval + 1); old_calib.miny = *((long *)retval + 2); old_calib.maxy = *((long *)retval + 3); XFree(retval); XGetDeviceProperty(display, device, prop_swap, 0, 1, False, XA_INTEGER, &type, &format, &nitems, &nbytes, &retval); old_swap = *(Bool *)retval; XFree(retval); /* Force uncalibrated state */ XChangeDeviceProperty(display, device, prop_calibration, XA_INTEGER, 32, PropModeReplace, (unsigned char *)values, 4); XChangeDeviceProperty(display, device, prop_swap, XA_INTEGER, 8, PropModeReplace, (unsigned char *)&swap, 1); return 0; }
gboolean device_set_property (XDevice *xdevice, const char *device_name, PropertyHelper *property) { int rc, i; Atom prop; Atom realtype; int realformat; unsigned long nitems, bytes_after; unsigned char *data; prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), property->name, False); if (!prop) return FALSE; gdk_error_trap_push (); rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, prop, 0, property->nitems, False, AnyPropertyType, &realtype, &realformat, &nitems, &bytes_after, &data); if (rc != Success || realtype != property->type || realformat != property->format || nitems < property->nitems) { gdk_error_trap_pop_ignored (); g_warning ("Error reading property \"%s\" for \"%s\"", property->name, device_name); return FALSE; } for (i = 0; i < nitems; i++) { switch (property->format) { case 8: data[i] = property->data.c[i]; break; case 32: ((long*)data)[i] = property->data.i[i]; break; } } XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, prop, realtype, realformat, PropModeReplace, data, nitems); XFree (data); if (gdk_error_trap_pop ()) { g_warning ("Error in setting \"%s\" for \"%s\"", property->name, device_name); return FALSE; } return TRUE; }
void cleanup_exit(XDevice *device) { long values[4]; values[0] = old_calib.minx; values[1] = old_calib.maxx; values[2] = old_calib.miny; values[3] = old_calib.maxy; XChangeDeviceProperty(display, device, prop_calibration, XA_INTEGER, 32, PropModeReplace, (unsigned char *)values, 4); XChangeDeviceProperty(display, device, prop_swap, XA_INTEGER, 8, PropModeReplace, (unsigned char *)&old_swap, 1); XCloseDevice(display, device); XUngrabServer(display); XUngrabKeyboard(display, CurrentTime); XCloseDisplay(display); exit(1); }
void executeCommand(Display *dpy, XDeviceInfo *info, const char *command, unsigned char data) { if (!info) { fprintf(stderr, "unable to find the device\n"); return; } XDevice *dev = XOpenDevice(dpy, info->id); if (!dev) { fprintf(stderr, "unable to open the device\n"); return; } Atom prop = XInternAtom(dpy, command, False); XChangeDeviceProperty(dpy, dev, prop, XA_INTEGER, 8, PropModeReplace, &data, 1); XCloseDevice(dpy, dev); }
int main(int argc, char *argv[], char *env[]) { char *display_name = NULL; char *device_name = NULL; char *output_name = NULL; XSetWindowAttributes xswa; int i = 0; double a, a1, a2, b, b1, b2, xerr, yerr; int xi_opcode, event, error; XExtensionVersion *version; XDeviceInfo *info; XDevice *device; long calib_data[4]; unsigned long mask; unsigned char swap; int keep_cursor = 0, ch; /* Crosshair placement */ int cpx[] = { 0, 0, 1, 1, 1 }; int cpy[] = { 0, 1, 0, 0, 1 }; while ((ch = getopt(argc, argv, "cD:d:o:v")) != -1) { switch (ch) { case 'c': keep_cursor++; break; case 'D': display_name = optarg; break; case 'd': device_name = optarg; break; case 'o': output_name = optarg; break; case 'v': verbose = True; break; default: usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (argc != 0) usage(); /* connect to X server */ if ((display = XOpenDisplay(display_name)) == NULL) { fprintf(stderr, "%s: cannot connect to X server %s\n", __progname, XDisplayName(display_name)); exit(1); } screen = DefaultScreen(display); root = RootWindow(display, screen); /* get screen size from display structure macro */ xpos = 0; ypos = 0; width = DisplayWidth(display, screen); height = DisplayHeight(display, screen); if (XRRQueryExtension(display, &event, &error)) { int major, minor; if (XRRQueryVersion(display, &major, &minor) != True) { fprintf(stderr, "Error querying XRandR version"); } else { printf("XRandR extension version %d.%d present\n", major, minor); has_xrandr = True; if (major > 1 || (major == 1 && minor >=2)) has_xrandr_1_2 = True; if (major > 1 || (major == 1 && minor >=3)) has_xrandr_1_3 = True; } } if (output_name != NULL) { if (has_xrandr_1_2) { get_xrandr_config(display, root, output_name, &xpos, &ypos, &width, &height); } else { fprintf(stderr, "%s: can not specify an output " "whithout XRandr 1.2 or later", __progname); exit(2); } } if (!XQueryExtension(display, INAME, &xi_opcode, &event, &error)) { fprintf(stderr, "%s: X Input extension not available.\n", __progname); exit(1); } version = XGetExtensionVersion(display, INAME); if (version == NULL || version == (XExtensionVersion *)NoSuchExtension) { fprintf(stderr, "Cannot query X Input version.\n"); exit(1); } XFree(version); prop_calibration = XInternAtom(display, WS_PROP_CALIBRATION, True); if (prop_calibration == None) { fprintf(stderr, "Unable to find the \"%s\" device property.\n" "There are probably no calibrable devices " "on this system.\n", WS_PROP_CALIBRATION); exit(1); } prop_swap = XInternAtom(display, WS_PROP_SWAP_AXES, True); if (prop_swap == None) { fprintf(stderr, "Unable to find the \"%s\" device property\n", WS_PROP_SWAP_AXES); exit(1); } info = find_device_info(device_name); if (info == NULL) { fprintf(stderr, "Unable to find the %s device\n", device_name ? device_name : "default"); exit(1); } /* setup window attributes */ xswa.override_redirect = True; xswa.background_pixel = BlackPixel(display, screen); xswa.event_mask = ExposureMask | KeyPressMask; mask = CWOverrideRedirect | CWBackPixel | CWEventMask; if (!keep_cursor) { xswa.cursor = create_empty_cursor(); mask |= CWCursor; } win = XCreateWindow(display, RootWindow(display, screen), xpos, ypos, width, height, 0, CopyFromParent, InputOutput, CopyFromParent, mask, &xswa); render_init(); XMapWindow(display, win); XGrabKeyboard(display, win, False, GrabModeAsync, GrabModeAsync, CurrentTime); XGrabServer(display); XClearWindow(display, win); if (verbose) printf("Calibrating %s\n", info->name); device = XOpenDevice(display, info->id); if (!device) { fprintf(stderr, "Unable to open the X input device \"%s\"\n", info->name); return 0; } if (!register_events(info, device, 0)) exit(1); uncalibrate(device); calib: XftDrawRect(draw, &bg, 0, 0, width, height); for (i = 0; i < 5; i++) { draw_graphics(cpx[i], cpy[i], i); XFlush(display); if (!get_events(i)) break; XftDrawRect(draw, &bg, 0, 0, width, height); } if (interrupted) cleanup_exit(device); /* Check if X and Y should be swapped */ if (fabs(x[0] - x[1]) > fabs(y[0] - y[1])) { calib.swapxy = 1; for (i = 0; i < 5; i++) { int t = x[i]; x[i] = y[i]; y[i] = t; } } /* get touch pad resolution to screen resolution ratio */ a1 = (double) (x[4] - x[0]) / (double) (cx[4] - cx[0]); a2 = (double) (x[3] - x[1]) / (double) (cx[3] - cx[1]); /* get the minimum pad position on the X-axis */ b1 = x[0] - a1 * cx[0]; b2 = x[1] - a2 * cx[1]; /* use the average ratio and average minimum position */ a = (a1 + a2) / 2.0; b = (b1 + b2) / 2.0; xerr = a * width / 2 + b - x[2]; if (fabs(xerr) > fabs(a * width * .01)) { fprintf(stderr, "Calibration problem: X axis error (%.2f) too high, try again\n", fabs(xerr)); goto err; } calib.minx = (int) (b + 0.5); calib.maxx = (int) (a * width + b + 0.5); /* get touch pad resolution to screen resolution ratio */ a1 = (double) (y[4] - y[0]) / (double) (cy[4] - cy[0]); a2 = (double) (y[3] - y[1]) / (double) (cy[3] - cy[1]); /* get the minimum pad position on the Y-axis */ b1 = y[0] - a1 * cy[0]; b2 = y[1] - a2 * cy[1]; /* use the average ratio and average minimum position */ a = (a1 + a2) / 2.0; b = (b1 + b2) / 2.0; yerr = a * height / 2 + b - y[2]; if (fabs(yerr) > fabs(a * height * 0.01)) { fprintf(stderr, "Calibration problem: Y axis error (%.2f) too high, try again\n", fabs(yerr)); goto err; } calib.miny = (int) (b + 0.5); calib.maxy = (int) (a * height + b + 0.5); XFlush(display); calib.resx = width; calib.resy = height; /* Send new values to the X server */ calib_data[0] = calib.minx; calib_data[1] = calib.maxx; calib_data[2] = calib.miny; calib_data[3] = calib.maxy; XChangeDeviceProperty(display, device, prop_calibration, XA_INTEGER, 32, PropModeReplace, (unsigned char *)calib_data, 4); swap = calib.swapxy; XChangeDeviceProperty(display, device, prop_swap, XA_INTEGER, 8, PropModeReplace, (unsigned char *)&swap, 1); XCloseDevice(display, device); XCloseDisplay(display); /* And print them for storage in wsconsctl.conf */ printf("mouse.scale=%d,%d,%d,%d,%d,%d,%d\n", calib.minx, calib.maxx, calib.miny, calib.maxy, calib.swapxy, calib.resx, calib.resy); return 0; err: draw_text(error_message, &errorColor); XFlush(display); sleep(2); goto calib; }
static void dp_set_variables(Display *dpy, XDevice* dev, int argc, char *argv[], int first_cmd) { int i; double val; struct Parameter *par; Atom prop, type, float_type; int format; unsigned char* data; unsigned long nitems, bytes_after; union flong *f; long *n; char *b; float_type = XInternAtom(dpy, XATOM_FLOAT, True); if (!float_type) fprintf(stderr, "Float properties not available.\n"); for (i = first_cmd; i < argc; i++) { val = parse_cmd(argv[i], &par); if (!par) continue; prop = XInternAtom(dpy, par->prop_name, True); if (!prop) { fprintf(stderr, "Property for '%s' not available. Skipping.\n", par->name); continue; } XGetDeviceProperty(dpy, dev, prop, 0, 1000, False, AnyPropertyType, &type, &format, &nitems, &bytes_after, &data); switch(par->prop_format) { case 8: if (format != par->prop_format || type != XA_INTEGER) { fprintf(stderr, " %-23s = format mismatch (%d)\n", par->name, format); break; } b = (char*)data; b[par->prop_offset] = rint(val); break; case 32: if (format != par->prop_format || type != XA_INTEGER) { fprintf(stderr, " %-23s = format mismatch (%d)\n", par->name, format); break; } n = (long*)data; n[par->prop_offset] = rint(val); break; case 0: /* float */ if (!float_type) continue; if (format != 32 || type != float_type) { fprintf(stderr, " %-23s = format mismatch (%d)\n", par->name, format); break; } f = (union flong*)data; f[par->prop_offset].f = val; break; } XChangeDeviceProperty(dpy, dev, prop, type, format, PropModeReplace, data, nitems); XFlush(dpy); } }
// Set Integer property on X bool CalibratorEvdev::xinput_do_set_int_prop( const char * name, Display *display, int format, int argc, const int *argv ) { #ifndef HAVE_XI_PROP return false; #else Atom prop; Atom old_type; int i; int old_format; unsigned long act_nitems, bytes_after; union { unsigned char *c; short *s; long *l; Atom *a; } data; if (argc < 1) { fprintf(stderr, "Wrong usage of xinput_do_set_prop, need at least 1 arguments\n"); return false; } prop = xinput_parse_atom(display, name); if (prop == None) { fprintf(stderr, "invalid property %s\n", name); return false; } if ( format == 0) { if (XGetDeviceProperty(display, dev, prop, 0, 0, False, AnyPropertyType, &old_type, &old_format, &act_nitems, &bytes_after, &data.c) != Success) { fprintf(stderr, "failed to get property type and format for %s\n", name); return false; } else { format = old_format; } XFree(data.c); } data.c = (unsigned char*)calloc(argc, sizeof(long)); for (i = 0; i < argc; i++) { switch (format) { case 8: data.c[i] = argv[i]; case 16: data.s[i] = argv[i]; break; case 32: data.l[i] = argv[i]; break; default: fprintf(stderr, "unexpected size for property %s\n", name); return false; } } XChangeDeviceProperty(display, dev, prop, XA_INTEGER, format, PropModeReplace, data.c, argc); free(data.c); return true; #endif // HAVE_XI_PROP }
static int do_set_prop_xi1(Display *dpy, Atom type, int format, int argc, char **argv, char *n, char *desc) { XDeviceInfo *info; XDevice *dev; Atom prop; Atom old_type; char *name; int i; Atom float_atom; int old_format, nelements = 0; unsigned long act_nitems, bytes_after; char *endptr; union { unsigned char *c; short *s; long *l; Atom *a; } data; if (argc < 3) { fprintf(stderr, "Usage: xinput %s %s\n", n, desc); return EXIT_FAILURE; } info = find_device_info(dpy, argv[0], False); if (!info) { fprintf(stderr, "unable to find device %s\n", argv[0]); return EXIT_FAILURE; } dev = XOpenDevice(dpy, info->id); if (!dev) { fprintf(stderr, "unable to open device %s\n", argv[0]); return EXIT_FAILURE; } name = argv[1]; prop = parse_atom(dpy, name); if (prop == None) { fprintf(stderr, "invalid property %s\n", name); return EXIT_FAILURE; } float_atom = XInternAtom(dpy, "FLOAT", False); nelements = argc - 2; if (type == None || format == 0) { if (XGetDeviceProperty(dpy, dev, prop, 0, 0, False, AnyPropertyType, &old_type, &old_format, &act_nitems, &bytes_after, &data.c) != Success) { fprintf(stderr, "failed to get property type and format for %s\n", name); return EXIT_FAILURE; } else { if (type == None) type = old_type; if (format == 0) format = old_format; } XFree(data.c); } if (type == None) { fprintf(stderr, "property %s doesn't exist, you need to specify " "its type and format\n", name); return EXIT_FAILURE; } data.c = calloc(nelements, sizeof(long)); for (i = 0; i < nelements; i++) { if (type == XA_INTEGER) { switch (format) { case 8: data.c[i] = atoi(argv[2 + i]); break; case 16: data.s[i] = atoi(argv[2 + i]); break; case 32: data.l[i] = atoi(argv[2 + i]); break; default: fprintf(stderr, "unexpected size for property %s", name); return EXIT_FAILURE; } } else if (type == float_atom) { if (format != 32) { fprintf(stderr, "unexpected format %d for property %s\n", format, name); return EXIT_FAILURE; } *(float *)(data.l + i) = strtod(argv[2 + i], &endptr); if (endptr == argv[2 + i]) { fprintf(stderr, "argument %s could not be parsed\n", argv[2 + i]); return EXIT_FAILURE; } } else if (type == XA_ATOM) { if (format != 32) { fprintf(stderr, "unexpected format %d for property %s\n", format, name); return EXIT_FAILURE; } data.a[i] = parse_atom(dpy, argv[2 + i]); } else { fprintf(stderr, "unexpected type for property %s\n", name); return EXIT_FAILURE; } } XChangeDeviceProperty(dpy, dev, prop, type, format, PropModeReplace, data.c, nelements); free(data.c); XCloseDevice(dpy, dev); return EXIT_SUCCESS; }
void setCalibration(int id, int minX, int maxX, int minY, int maxY, int axesSwap, int screenWidth, int screenHeight, int outputX, int outputY, int outputWidth, int outputHeight, int rotation) { float matrix[] = { 1., 0., 0., /* [0] [1] [2] */ 0., 1., 0., /* [3] [4] [5] */ 0., 0., 1. }; /* [6] [7] [8] */ int matrixMode = 0; /* Check if transformation matrix is supported */ long l; if((sizeof l) == 4 || (sizeof l) == 8) { /* We only support matrix mode on systems where longs are 32 or 64 bits long */ Atom retType; int retFormat; unsigned long retItems, retBytesAfter; unsigned char * data = NULL; if(XIGetProperty(display, id, XInternAtom(display, "Coordinate Transformation Matrix", 0), 0, 9 * 32, False, floatAtom, &retType, &retFormat, &retItems, &retBytesAfter, &data) != Success) { data = NULL; } if(data != NULL && retItems == 9) { matrixMode = 1; } if(data != NULL) { XFree(data); } } unsigned char flipHoriz = 0, flipVerti = 0; if(matrixMode) { if(debugMode) printf("Use matrix method\n"); /* Output rotation */ if(rotation & RR_Rotate_180) { matrix[0] = -1.; matrix[4] = -1; matrix[2] = 1.; matrix[5] = 1.; } else if(rotation & RR_Rotate_90) { matrix[0] = 0.; matrix[1] = -1.; matrix[3] = 1.; matrix[4] = 0.; matrix[2] = 1.; } else if(rotation & RR_Rotate_270) { matrix[0] = 0.; matrix[1] = 1.; matrix[3] = -1.; matrix[4] = 0.; matrix[5] = 1.; } /* Output Reflection */ if(rotation & RR_Reflect_X) { matrix[0]*= -1.; matrix[1]*= -1.; matrix[2]*= -1.; matrix[2]+= 1.; } if(rotation & RR_Reflect_Y) { matrix[3]*= -1.; matrix[4]*= -1.; matrix[5]*= -1.; matrix[5]+= 1.; } /* Output Size */ float widthRel = outputWidth / (float) screenWidth; float heightRel = outputHeight / (float) screenHeight; matrix[0] *= widthRel; matrix[1] *= widthRel; matrix[2] *= widthRel; matrix[3] *= heightRel; matrix[4] *= heightRel; matrix[5] *= heightRel; /* Output Position */ matrix[2] += outputX / (float) screenWidth; matrix[5] += outputY / (float) screenHeight; } else { if(debugMode) printf("Use legacy method\n"); /* No support for transformations, so use legacy method */ if(rotation & RR_Rotate_180) { flipHoriz = !flipHoriz; flipVerti = !flipVerti; } else if(rotation & RR_Rotate_90) { flipVerti = !flipVerti; axesSwap = !axesSwap; } else if(rotation & RR_Rotate_270) { flipHoriz = !flipHoriz; axesSwap = !axesSwap; } /* Output Reflection */ if(rotation & RR_Reflect_X) { flipHoriz = !flipHoriz; } if(rotation & RR_Reflect_Y) { flipVerti = !flipVerti; } if(axesSwap) { swap(&maxX, &maxY); swap(&minX, &minY); } int leftSpace, rightSpace, topSpace, bottomSpace; leftSpace = outputX; rightSpace = screenWidth - outputX - outputWidth; topSpace = outputY; bottomSpace = screenHeight - outputY - outputHeight; if(flipHoriz) swap(&leftSpace, &rightSpace); if(flipVerti) swap(&topSpace, &bottomSpace); float fctX = ((float) (maxX - minX)) / ((float) outputWidth); float fctY = ((float) (maxY - minY)) / ((float) outputHeight); minX = minX - (int) (leftSpace * fctX); maxX = maxX + (int) (rightSpace * fctX); minY = minY - (int) (topSpace * fctY); maxY = maxY + (int) (bottomSpace * fctY); } XDevice *dev = XOpenDevice(display, id); if(dev) { if(matrixMode) { if((sizeof l) == 4) { XChangeDeviceProperty(display, dev, XInternAtom(display, "Coordinate Transformation Matrix", 0), floatAtom, 32, PropModeReplace, (unsigned char*) matrix, 9); } else if((sizeof l) == 8) { /* Xlib needs the floats long-aligned, so let's align them. */ float matrix2[] = { matrix[0], 0., matrix[1], 0., matrix[2], 0., matrix[3], 0., matrix[4], 0., matrix[5], 0., matrix[6], 0., matrix[7], 0., matrix[8], 0. }; XChangeDeviceProperty(display, dev, XInternAtom(display, "Coordinate Transformation Matrix", 0), floatAtom, 32, PropModeReplace, (unsigned char*) matrix2, 9); } } long calib[] = { minX, maxX, minY, maxY }; //TODO instead of long, use platform 32 bit type XChangeDeviceProperty(display, dev, XInternAtom(display, "Evdev Axis Calibration", 0), XA_INTEGER, 32, PropModeReplace, (unsigned char*) calib, 4); unsigned char flipData[] = {flipHoriz, flipVerti}; XChangeDeviceProperty(display, dev, XInternAtom(display, "Evdev Axis Inversion", 0), XA_INTEGER, 8, PropModeReplace, flipData, 2); unsigned char cAxesSwap = (unsigned char) axesSwap; XChangeDeviceProperty(display, dev, XInternAtom(display, "Evdev Axes Swap", 0), XA_INTEGER, 8, PropModeReplace, &cAxesSwap, 1); XCloseDevice(display, dev); } }