1b85037dbSmrg/* 2b85037dbSmrg * Copyright © 2002-2005,2007 Peter Osterlund 3b85037dbSmrg * 4b85037dbSmrg * Permission to use, copy, modify, distribute, and sell this software 5b85037dbSmrg * and its documentation for any purpose is hereby granted without 6b85037dbSmrg * fee, provided that the above copyright notice appear in all copies 7b85037dbSmrg * and that both that copyright notice and this permission notice 8b85037dbSmrg * appear in supporting documentation, and that the name of Red Hat 9b85037dbSmrg * not be used in advertising or publicity pertaining to distribution 10b85037dbSmrg * of the software without specific, written prior permission. Red 11b85037dbSmrg * Hat makes no representations about the suitability of this software 12b85037dbSmrg * for any purpose. It is provided "as is" without express or implied 13b85037dbSmrg * warranty. 14b85037dbSmrg * 15b85037dbSmrg * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16b85037dbSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN 17b85037dbSmrg * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 18b85037dbSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 19b85037dbSmrg * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 20b85037dbSmrg * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 21b85037dbSmrg * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22b85037dbSmrg * 23b85037dbSmrg * Authors: 24b85037dbSmrg * Peter Osterlund (petero2@telia.com) 25b85037dbSmrg */ 26b85037dbSmrg 27b85037dbSmrg#ifdef HAVE_CONFIG_H 28b85037dbSmrg#include "config.h" 29b85037dbSmrg#endif 30b85037dbSmrg 31b85037dbSmrg#include <stdio.h> 32b85037dbSmrg#include <stdlib.h> 33b85037dbSmrg#include <sys/types.h> 34b85037dbSmrg#include <sys/ipc.h> 35b85037dbSmrg#include <sys/time.h> 36b85037dbSmrg#include <unistd.h> 37b85037dbSmrg#include <string.h> 38b85037dbSmrg#include <stddef.h> 39b85037dbSmrg#include <math.h> 4028515619Smrg#include <limits.h> 41b85037dbSmrg 42b85037dbSmrg#include <X11/Xdefs.h> 43b85037dbSmrg#include <X11/Xatom.h> 44b85037dbSmrg#include <X11/extensions/XI.h> 45b85037dbSmrg#include <X11/extensions/XInput.h> 46b85037dbSmrg#include "synaptics-properties.h" 47b85037dbSmrg 48b85037dbSmrg#ifndef XATOM_FLOAT 49b85037dbSmrg#define XATOM_FLOAT "FLOAT" 50b85037dbSmrg#endif 51b85037dbSmrg 5228515619Smrg#define SYN_MAX_BUTTONS 12 5328515619Smrg 5428515619Smrgunion flong { /* Xlibs 64-bit property handling madness */ 55b85037dbSmrg long l; 56b85037dbSmrg float f; 57b85037dbSmrg}; 58b85037dbSmrg 59b85037dbSmrgenum ParaType { 60b85037dbSmrg PT_INT, 61b85037dbSmrg PT_BOOL, 62b85037dbSmrg PT_DOUBLE 63b85037dbSmrg}; 64b85037dbSmrg 65b85037dbSmrgstruct Parameter { 6628515619Smrg char *name; /* Name of parameter */ 6728515619Smrg enum ParaType type; /* Type of parameter */ 6828515619Smrg double min_val; /* Minimum allowed value */ 6928515619Smrg double max_val; /* Maximum allowed value */ 7028515619Smrg char *prop_name; /* Property name */ 7128515619Smrg int prop_format; /* Property format (0 for floats) */ 7228515619Smrg int prop_offset; /* Offset inside property */ 73b85037dbSmrg}; 74b85037dbSmrg 75b85037dbSmrgstatic struct Parameter params[] = { 76b85037dbSmrg {"LeftEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_EDGES, 32, 0}, 77b85037dbSmrg {"RightEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_EDGES, 32, 1}, 78b85037dbSmrg {"TopEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_EDGES, 32, 2}, 79b85037dbSmrg {"BottomEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_EDGES, 32, 3}, 80b85037dbSmrg {"FingerLow", PT_INT, 0, 255, SYNAPTICS_PROP_FINGER, 32, 0}, 81b85037dbSmrg {"FingerHigh", PT_INT, 0, 255, SYNAPTICS_PROP_FINGER, 32, 1}, 82b85037dbSmrg {"MaxTapTime", PT_INT, 0, 1000, SYNAPTICS_PROP_TAP_TIME, 32, 0}, 83b85037dbSmrg {"MaxTapMove", PT_INT, 0, 2000, SYNAPTICS_PROP_TAP_MOVE, 32, 0}, 84b85037dbSmrg {"MaxDoubleTapTime", PT_INT, 0, 1000, SYNAPTICS_PROP_TAP_DURATIONS,32, 1}, 85b85037dbSmrg {"SingleTapTimeout", PT_INT, 0, 1000, SYNAPTICS_PROP_TAP_DURATIONS,32, 0}, 86b85037dbSmrg {"ClickTime", PT_INT, 0, 1000, SYNAPTICS_PROP_TAP_DURATIONS,32, 2}, 87b85037dbSmrg {"FastTaps", PT_BOOL, 0, 1, SYNAPTICS_PROP_TAP_FAST, 8, 0}, 88b85037dbSmrg {"EmulateMidButtonTime", PT_INT, 0, 1000, SYNAPTICS_PROP_MIDDLE_TIMEOUT,32, 0}, 89b85037dbSmrg {"EmulateTwoFingerMinZ", PT_INT, 0, 1000, SYNAPTICS_PROP_TWOFINGER_PRESSURE, 32, 0}, 90b85037dbSmrg {"EmulateTwoFingerMinW", PT_INT, 0, 15, SYNAPTICS_PROP_TWOFINGER_WIDTH, 32, 0}, 9128515619Smrg {"VertScrollDelta", PT_INT, -1000, 1000, SYNAPTICS_PROP_SCROLL_DISTANCE, 32, 0}, 9228515619Smrg {"HorizScrollDelta", PT_INT, -1000, 1000, SYNAPTICS_PROP_SCROLL_DISTANCE, 32, 1}, 93b85037dbSmrg {"VertEdgeScroll", PT_BOOL, 0, 1, SYNAPTICS_PROP_SCROLL_EDGE, 8, 0}, 94b85037dbSmrg {"HorizEdgeScroll", PT_BOOL, 0, 1, SYNAPTICS_PROP_SCROLL_EDGE, 8, 1}, 95b85037dbSmrg {"CornerCoasting", PT_BOOL, 0, 1, SYNAPTICS_PROP_SCROLL_EDGE, 8, 2}, 96b85037dbSmrg {"VertTwoFingerScroll", PT_BOOL, 0, 1, SYNAPTICS_PROP_SCROLL_TWOFINGER, 8, 0}, 97b85037dbSmrg {"HorizTwoFingerScroll", PT_BOOL, 0, 1, SYNAPTICS_PROP_SCROLL_TWOFINGER, 8, 1}, 98b85037dbSmrg {"MinSpeed", PT_DOUBLE, 0, 255.0, SYNAPTICS_PROP_SPEED, 0, /*float */ 0}, 99b85037dbSmrg {"MaxSpeed", PT_DOUBLE, 0, 255.0, SYNAPTICS_PROP_SPEED, 0, /*float */ 1}, 100b85037dbSmrg {"AccelFactor", PT_DOUBLE, 0, 1.0, SYNAPTICS_PROP_SPEED, 0, /*float */ 2}, 101b85037dbSmrg {"TouchpadOff", PT_INT, 0, 2, SYNAPTICS_PROP_OFF, 8, 0}, 102b85037dbSmrg {"LockedDrags", PT_BOOL, 0, 1, SYNAPTICS_PROP_LOCKED_DRAGS, 8, 0}, 103b85037dbSmrg {"LockedDragTimeout", PT_INT, 0, 30000, SYNAPTICS_PROP_LOCKED_DRAGS_TIMEOUT, 32, 0}, 104b85037dbSmrg {"RTCornerButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_TAP_ACTION, 8, 0}, 105b85037dbSmrg {"RBCornerButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_TAP_ACTION, 8, 1}, 106b85037dbSmrg {"LTCornerButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_TAP_ACTION, 8, 2}, 107b85037dbSmrg {"LBCornerButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_TAP_ACTION, 8, 3}, 108b85037dbSmrg {"TapButton1", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_TAP_ACTION, 8, 4}, 109b85037dbSmrg {"TapButton2", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_TAP_ACTION, 8, 5}, 110b85037dbSmrg {"TapButton3", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_TAP_ACTION, 8, 6}, 111b85037dbSmrg {"ClickFinger1", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_CLICK_ACTION, 8, 0}, 112b85037dbSmrg {"ClickFinger2", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_CLICK_ACTION, 8, 1}, 113b85037dbSmrg {"ClickFinger3", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_CLICK_ACTION, 8, 2}, 114b85037dbSmrg {"CircularScrolling", PT_BOOL, 0, 1, SYNAPTICS_PROP_CIRCULAR_SCROLLING, 8, 0}, 115b85037dbSmrg {"CircScrollDelta", PT_DOUBLE, .01, 3, SYNAPTICS_PROP_CIRCULAR_SCROLLING_DIST, 0 /* float */, 0}, 116b85037dbSmrg {"CircScrollTrigger", PT_INT, 0, 8, SYNAPTICS_PROP_CIRCULAR_SCROLLING_TRIGGER, 8, 0}, 117b85037dbSmrg {"PalmDetect", PT_BOOL, 0, 1, SYNAPTICS_PROP_PALM_DETECT, 8, 0}, 118b85037dbSmrg {"PalmMinWidth", PT_INT, 0, 15, SYNAPTICS_PROP_PALM_DIMENSIONS, 32, 0}, 119b85037dbSmrg {"PalmMinZ", PT_INT, 0, 255, SYNAPTICS_PROP_PALM_DIMENSIONS, 32, 1}, 12028515619Smrg {"CoastingSpeed", PT_DOUBLE, 0, 255, SYNAPTICS_PROP_COASTING_SPEED, 0 /* float*/, 0}, 121b85037dbSmrg {"CoastingFriction", PT_DOUBLE, 0, 255, SYNAPTICS_PROP_COASTING_SPEED, 0 /* float*/, 1}, 122b85037dbSmrg {"PressureMotionMinZ", PT_INT, 1, 255, SYNAPTICS_PROP_PRESSURE_MOTION, 32, 0}, 123b85037dbSmrg {"PressureMotionMaxZ", PT_INT, 1, 255, SYNAPTICS_PROP_PRESSURE_MOTION, 32, 1}, 124b85037dbSmrg {"PressureMotionMinFactor", PT_DOUBLE, 0, 10.0,SYNAPTICS_PROP_PRESSURE_MOTION_FACTOR, 0 /*float*/, 0}, 125b85037dbSmrg {"PressureMotionMaxFactor", PT_DOUBLE, 0, 10.0,SYNAPTICS_PROP_PRESSURE_MOTION_FACTOR, 0 /*float*/, 1}, 126b85037dbSmrg {"GrabEventDevice", PT_BOOL, 0, 1, SYNAPTICS_PROP_GRAB, 8, 0}, 127b85037dbSmrg {"TapAndDragGesture", PT_BOOL, 0, 1, SYNAPTICS_PROP_GESTURES, 8, 0}, 128b85037dbSmrg {"AreaLeftEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_AREA, 32, 0}, 129b85037dbSmrg {"AreaRightEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_AREA, 32, 1}, 130b85037dbSmrg {"AreaTopEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_AREA, 32, 2}, 131b85037dbSmrg {"AreaBottomEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_AREA, 32, 3}, 13228515619Smrg {"HorizHysteresis", PT_INT, 0, 10000, SYNAPTICS_PROP_NOISE_CANCELLATION, 32, 0}, 13328515619Smrg {"VertHysteresis", PT_INT, 0, 10000, SYNAPTICS_PROP_NOISE_CANCELLATION, 32, 1}, 13428515619Smrg {"ClickPad", PT_BOOL, 0, 1, SYNAPTICS_PROP_CLICKPAD, 8, 0}, 13528515619Smrg {"RightButtonAreaLeft", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 0}, 13628515619Smrg {"RightButtonAreaRight", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 1}, 13728515619Smrg {"RightButtonAreaTop", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 2}, 13828515619Smrg {"RightButtonAreaBottom", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 3}, 13928515619Smrg {"MiddleButtonAreaLeft", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 4}, 14028515619Smrg {"MiddleButtonAreaRight", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 5}, 14128515619Smrg {"MiddleButtonAreaTop", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 6}, 14228515619Smrg {"MiddleButtonAreaBottom", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 7}, 143b85037dbSmrg { NULL, 0, 0, 0, 0 } 144b85037dbSmrg}; 145b85037dbSmrg 146b85037dbSmrgstatic double 14728515619Smrgparse_cmd(char *cmd, struct Parameter **par) 148b85037dbSmrg{ 149302b15bdSmrg char *eqp = strchr(cmd, '='); 15028515619Smrg 151b85037dbSmrg *par = NULL; 152b85037dbSmrg 153b85037dbSmrg if (eqp) { 15428515619Smrg int j; 15528515619Smrg int found = 0; 15628515619Smrg 15728515619Smrg *eqp = 0; 15828515619Smrg for (j = 0; params[j].name; j++) { 15928515619Smrg if (strcasecmp(cmd, params[j].name) == 0) { 16028515619Smrg found = 1; 16128515619Smrg break; 16228515619Smrg } 16328515619Smrg } 16428515619Smrg if (found) { 16528515619Smrg double val = atof(&eqp[1]); 16628515619Smrg 16728515619Smrg *par = ¶ms[j]; 16828515619Smrg 16928515619Smrg if (val < (*par)->min_val) 17028515619Smrg val = (*par)->min_val; 17128515619Smrg if (val > (*par)->max_val) 17228515619Smrg val = (*par)->max_val; 17328515619Smrg 17428515619Smrg return val; 17528515619Smrg } 17628515619Smrg else { 17728515619Smrg printf("Unknown parameter %s\n", cmd); 17828515619Smrg } 179b85037dbSmrg } 18028515619Smrg else { 18128515619Smrg printf("Invalid command: %s\n", cmd); 182b85037dbSmrg } 183b85037dbSmrg 18428515619Smrg return 0; 185b85037dbSmrg} 186b85037dbSmrg 187b85037dbSmrg/** Init display connection or NULL on error */ 18828515619Smrgstatic Display * 189b85037dbSmrgdp_init() 190b85037dbSmrg{ 19128515619Smrg Display *dpy = NULL; 19228515619Smrg XExtensionVersion *v = NULL; 19328515619Smrg Atom touchpad_type = 0; 19428515619Smrg Atom synaptics_property = 0; 19528515619Smrg int error = 0; 196b85037dbSmrg 197b85037dbSmrg dpy = XOpenDisplay(NULL); 198b85037dbSmrg if (!dpy) { 19928515619Smrg fprintf(stderr, "Failed to connect to X Server.\n"); 20028515619Smrg error = 1; 20128515619Smrg goto unwind; 202b85037dbSmrg } 203b85037dbSmrg 204b85037dbSmrg v = XGetExtensionVersion(dpy, INAME); 205b85037dbSmrg if (!v->present || 20628515619Smrg (v->major_version * 1000 + v->minor_version) < 20728515619Smrg (XI_Add_DeviceProperties_Major * 1000 + 20828515619Smrg XI_Add_DeviceProperties_Minor)) { 20928515619Smrg fprintf(stderr, "X server supports X Input %d.%d. I need %d.%d.\n", 21028515619Smrg v->major_version, v->minor_version, 21128515619Smrg XI_Add_DeviceProperties_Major, XI_Add_DeviceProperties_Minor); 21228515619Smrg error = 1; 21328515619Smrg goto unwind; 214b85037dbSmrg } 215b85037dbSmrg 216b85037dbSmrg /* We know synaptics sets XI_TOUCHPAD for all the devices. */ 217b85037dbSmrg touchpad_type = XInternAtom(dpy, XI_TOUCHPAD, True); 218b85037dbSmrg if (!touchpad_type) { 21928515619Smrg fprintf(stderr, "XI_TOUCHPAD not initialised.\n"); 22028515619Smrg error = 1; 22128515619Smrg goto unwind; 222b85037dbSmrg } 223b85037dbSmrg 224b85037dbSmrg synaptics_property = XInternAtom(dpy, SYNAPTICS_PROP_EDGES, True); 225b85037dbSmrg if (!synaptics_property) { 22628515619Smrg fprintf(stderr, "Couldn't find synaptics properties. No synaptics " 22728515619Smrg "driver loaded?\n"); 22828515619Smrg error = 1; 22928515619Smrg goto unwind; 230b85037dbSmrg } 231b85037dbSmrg 23228515619Smrg unwind: 233b85037dbSmrg XFree(v); 23428515619Smrg if (error && dpy) { 23528515619Smrg XCloseDisplay(dpy); 23628515619Smrg dpy = NULL; 237b85037dbSmrg } 238b85037dbSmrg return dpy; 239b85037dbSmrg} 240b85037dbSmrg 241b85037dbSmrgstatic XDevice * 24228515619Smrgdp_get_device(Display * dpy) 243b85037dbSmrg{ 24428515619Smrg XDevice *dev = NULL; 24528515619Smrg XDeviceInfo *info = NULL; 24628515619Smrg int ndevices = 0; 24728515619Smrg Atom touchpad_type = 0; 24828515619Smrg Atom synaptics_property = 0; 24928515619Smrg Atom *properties = NULL; 25028515619Smrg int nprops = 0; 25128515619Smrg int error = 0; 252b85037dbSmrg 253b85037dbSmrg touchpad_type = XInternAtom(dpy, XI_TOUCHPAD, True); 254b85037dbSmrg synaptics_property = XInternAtom(dpy, SYNAPTICS_PROP_EDGES, True); 255b85037dbSmrg info = XListInputDevices(dpy, &ndevices); 256b85037dbSmrg 25728515619Smrg while (ndevices--) { 25828515619Smrg if (info[ndevices].type == touchpad_type) { 25928515619Smrg dev = XOpenDevice(dpy, info[ndevices].id); 26028515619Smrg if (!dev) { 26128515619Smrg fprintf(stderr, "Failed to open device '%s'.\n", 26228515619Smrg info[ndevices].name); 26328515619Smrg error = 1; 26428515619Smrg goto unwind; 26528515619Smrg } 26628515619Smrg 26728515619Smrg properties = XListDeviceProperties(dpy, dev, &nprops); 26828515619Smrg if (!properties || !nprops) { 26928515619Smrg fprintf(stderr, "No properties on device '%s'.\n", 27028515619Smrg info[ndevices].name); 27128515619Smrg error = 1; 27228515619Smrg goto unwind; 27328515619Smrg } 27428515619Smrg 27528515619Smrg while (nprops--) { 27628515619Smrg if (properties[nprops] == synaptics_property) 27728515619Smrg break; 27828515619Smrg } 27928515619Smrg if (!nprops) { 28028515619Smrg fprintf(stderr, "No synaptics properties on device '%s'.\n", 28128515619Smrg info[ndevices].name); 28228515619Smrg error = 1; 28328515619Smrg goto unwind; 28428515619Smrg } 28528515619Smrg 28628515619Smrg break; /* Yay, device is suitable */ 28728515619Smrg } 288b85037dbSmrg } 289b85037dbSmrg 29028515619Smrg unwind: 291b85037dbSmrg XFree(properties); 292b85037dbSmrg XFreeDeviceList(info); 293b85037dbSmrg if (!dev) 294b85037dbSmrg fprintf(stderr, "Unable to find a synaptics device.\n"); 29528515619Smrg else if (error && dev) { 29628515619Smrg XCloseDevice(dpy, dev); 29728515619Smrg dev = NULL; 298b85037dbSmrg } 299b85037dbSmrg return dev; 300b85037dbSmrg} 301b85037dbSmrg 302b85037dbSmrgstatic void 30328515619Smrgdp_set_variables(Display * dpy, XDevice * dev, int argc, char *argv[], 30428515619Smrg int first_cmd) 305b85037dbSmrg{ 306b85037dbSmrg int i; 307b85037dbSmrg double val; 308b85037dbSmrg struct Parameter *par; 309b85037dbSmrg Atom prop, type, float_type; 310b85037dbSmrg int format; 31128515619Smrg unsigned char *data; 312b85037dbSmrg unsigned long nitems, bytes_after; 313b85037dbSmrg 314b85037dbSmrg union flong *f; 315b85037dbSmrg long *n; 316b85037dbSmrg char *b; 317b85037dbSmrg 318b85037dbSmrg float_type = XInternAtom(dpy, XATOM_FLOAT, True); 319b85037dbSmrg if (!float_type) 32028515619Smrg fprintf(stderr, "Float properties not available.\n"); 321b85037dbSmrg 322b85037dbSmrg for (i = first_cmd; i < argc; i++) { 32328515619Smrg val = parse_cmd(argv[i], &par); 32428515619Smrg if (!par) 32528515619Smrg continue; 32628515619Smrg 32728515619Smrg prop = XInternAtom(dpy, par->prop_name, True); 32828515619Smrg if (!prop) { 32928515619Smrg fprintf(stderr, "Property for '%s' not available. Skipping.\n", 33028515619Smrg par->name); 33128515619Smrg continue; 33228515619Smrg 33328515619Smrg } 33428515619Smrg 33528515619Smrg XGetDeviceProperty(dpy, dev, prop, 0, 1000, False, AnyPropertyType, 33628515619Smrg &type, &format, &nitems, &bytes_after, &data); 33728515619Smrg 33828515619Smrg if (type == None) { 33928515619Smrg fprintf(stderr, "Property for '%s' not available. Skipping.\n", 34028515619Smrg par->name); 34128515619Smrg continue; 34228515619Smrg } 34328515619Smrg 34428515619Smrg switch (par->prop_format) { 34528515619Smrg case 8: 34628515619Smrg if (format != par->prop_format || type != XA_INTEGER) { 34728515619Smrg fprintf(stderr, " %-23s = format mismatch (%d)\n", 34828515619Smrg par->name, format); 34928515619Smrg break; 35028515619Smrg } 35128515619Smrg b = (char *) data; 35228515619Smrg b[par->prop_offset] = rint(val); 35328515619Smrg break; 35428515619Smrg case 32: 35528515619Smrg if (format != par->prop_format || 35628515619Smrg (type != XA_INTEGER && type != XA_CARDINAL)) { 35728515619Smrg fprintf(stderr, " %-23s = format mismatch (%d)\n", 35828515619Smrg par->name, format); 35928515619Smrg break; 36028515619Smrg } 36128515619Smrg n = (long *) data; 36228515619Smrg n[par->prop_offset] = rint(val); 36328515619Smrg break; 36428515619Smrg case 0: /* float */ 36528515619Smrg if (!float_type) 36628515619Smrg continue; 36728515619Smrg if (format != 32 || type != float_type) { 36828515619Smrg fprintf(stderr, " %-23s = format mismatch (%d)\n", 36928515619Smrg par->name, format); 37028515619Smrg break; 37128515619Smrg } 37228515619Smrg f = (union flong *) data; 37328515619Smrg f[par->prop_offset].f = val; 37428515619Smrg break; 37528515619Smrg } 37628515619Smrg 37728515619Smrg XChangeDeviceProperty(dpy, dev, prop, type, format, 37828515619Smrg PropModeReplace, data, nitems); 37928515619Smrg XFlush(dpy); 380b85037dbSmrg } 381b85037dbSmrg} 382b85037dbSmrg 383b85037dbSmrg/* FIXME: horribly inefficient. */ 384b85037dbSmrgstatic void 38528515619Smrgdp_show_settings(Display * dpy, XDevice * dev) 386b85037dbSmrg{ 387b85037dbSmrg int j; 388b85037dbSmrg Atom a, type, float_type; 389b85037dbSmrg int format; 390b85037dbSmrg unsigned long nitems, bytes_after; 39128515619Smrg unsigned char *data; 392b85037dbSmrg int len; 393b85037dbSmrg 394b85037dbSmrg union flong *f; 395b85037dbSmrg long *i; 396b85037dbSmrg char *b; 397b85037dbSmrg 398b85037dbSmrg float_type = XInternAtom(dpy, XATOM_FLOAT, True); 399b85037dbSmrg if (!float_type) 40028515619Smrg fprintf(stderr, "Float properties not available.\n"); 401b85037dbSmrg 402b85037dbSmrg printf("Parameter settings:\n"); 403b85037dbSmrg for (j = 0; params[j].name; j++) { 40428515619Smrg struct Parameter *par = ¶ms[j]; 40528515619Smrg 40628515619Smrg a = XInternAtom(dpy, par->prop_name, True); 40728515619Smrg if (!a) 40828515619Smrg continue; 40928515619Smrg 41028515619Smrg len = 41128515619Smrg 1 + 41228515619Smrg ((par->prop_offset * (par->prop_format ? par->prop_format : 32) / 41328515619Smrg 8)) / 4; 41428515619Smrg 41528515619Smrg XGetDeviceProperty(dpy, dev, a, 0, len, False, 41628515619Smrg AnyPropertyType, &type, &format, 41728515619Smrg &nitems, &bytes_after, &data); 41828515619Smrg if (type == None) 41928515619Smrg continue; 42028515619Smrg 42128515619Smrg switch (par->prop_format) { 42228515619Smrg case 8: 42328515619Smrg if (format != par->prop_format || type != XA_INTEGER) { 42428515619Smrg fprintf(stderr, " %-23s = format mismatch (%d)\n", 42528515619Smrg par->name, format); 42628515619Smrg break; 42728515619Smrg } 42828515619Smrg 42928515619Smrg b = (char *) data; 43028515619Smrg printf(" %-23s = %d\n", par->name, b[par->prop_offset]); 43128515619Smrg break; 43228515619Smrg case 32: 43328515619Smrg if (format != par->prop_format || 43428515619Smrg (type != XA_INTEGER && type != XA_CARDINAL)) { 43528515619Smrg fprintf(stderr, " %-23s = format mismatch (%d)\n", 43628515619Smrg par->name, format); 43728515619Smrg break; 43828515619Smrg } 43928515619Smrg 44028515619Smrg i = (long *) data; 44128515619Smrg printf(" %-23s = %ld\n", par->name, i[par->prop_offset]); 44228515619Smrg break; 44328515619Smrg case 0: /* Float */ 44428515619Smrg if (!float_type) 44528515619Smrg continue; 44628515619Smrg if (format != 32 || type != float_type) { 44728515619Smrg fprintf(stderr, " %-23s = format mismatch (%d)\n", 44828515619Smrg par->name, format); 44928515619Smrg break; 45028515619Smrg } 45128515619Smrg 45228515619Smrg f = (union flong *) data; 45328515619Smrg printf(" %-23s = %g\n", par->name, f[par->prop_offset].f); 45428515619Smrg break; 45528515619Smrg } 45628515619Smrg 45728515619Smrg XFree(data); 458b85037dbSmrg } 459b85037dbSmrg} 460b85037dbSmrg 461b85037dbSmrgstatic void 462b85037dbSmrgusage(void) 463b85037dbSmrg{ 46428515619Smrg fprintf(stderr, "Usage: synclient [-h] [-l] [-V] [-?] [var1=value1 [var2=value2] ...]\n"); 465b85037dbSmrg fprintf(stderr, " -l List current user settings\n"); 466b85037dbSmrg fprintf(stderr, " -V Print synclient version string and exit\n"); 467b85037dbSmrg fprintf(stderr, " -? Show this help message\n"); 468b85037dbSmrg fprintf(stderr, " var=value Set user parameter 'var' to 'value'.\n"); 469b85037dbSmrg exit(1); 470b85037dbSmrg} 471b85037dbSmrg 472b85037dbSmrgint 473b85037dbSmrgmain(int argc, char *argv[]) 474b85037dbSmrg{ 475b85037dbSmrg int c; 476b85037dbSmrg int dump_settings = 0; 477b85037dbSmrg int first_cmd; 478b85037dbSmrg 479b85037dbSmrg Display *dpy; 480b85037dbSmrg XDevice *dev; 481b85037dbSmrg 482b85037dbSmrg if (argc == 1) 483b85037dbSmrg dump_settings = 1; 484b85037dbSmrg 485b85037dbSmrg /* Parse command line parameters */ 48628515619Smrg while ((c = getopt(argc, argv, "lV?")) != -1) { 48728515619Smrg switch (c) { 48828515619Smrg case 'l': 48928515619Smrg dump_settings = 1; 49028515619Smrg break; 49128515619Smrg case 'V': 49228515619Smrg printf("%s\n", VERSION); 49328515619Smrg exit(0); 49428515619Smrg case '?': 49528515619Smrg default: 49628515619Smrg usage(); 49728515619Smrg } 498b85037dbSmrg } 499b85037dbSmrg 500b85037dbSmrg first_cmd = optind; 50128515619Smrg if (!dump_settings && first_cmd == argc) 50228515619Smrg usage(); 503b85037dbSmrg 504b85037dbSmrg dpy = dp_init(); 505b85037dbSmrg if (!dpy || !(dev = dp_get_device(dpy))) 506b85037dbSmrg return 1; 507b85037dbSmrg 508b85037dbSmrg dp_set_variables(dpy, dev, argc, argv, first_cmd); 509b85037dbSmrg if (dump_settings) 510b85037dbSmrg dp_show_settings(dpy, dev); 511b85037dbSmrg 512b85037dbSmrg XCloseDevice(dpy, dev); 513b85037dbSmrg XCloseDisplay(dpy); 514b85037dbSmrg 515b85037dbSmrg return 0; 516b85037dbSmrg} 517