property.c revision a570218a
15b944e2aSmrg/* 20309d3b3Smrg * Copyright © 2007 Peter Hutterer 30309d3b3Smrg * Copyright © 2009 Red Hat, Inc. 45b944e2aSmrg * 50309d3b3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 60309d3b3Smrg * copy of this software and associated documentation files (the "Software"), 70309d3b3Smrg * to deal in the Software without restriction, including without limitation 80309d3b3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 90309d3b3Smrg * and/or sell copies of the Software, and to permit persons to whom the 100309d3b3Smrg * Software is furnished to do so, subject to the following conditions: 115b944e2aSmrg * 120309d3b3Smrg * The above copyright notice and this permission notice (including the next 130309d3b3Smrg * paragraph) shall be included in all copies or substantial portions of the 140309d3b3Smrg * Software. 155b944e2aSmrg * 160309d3b3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 170309d3b3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 180309d3b3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 190309d3b3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 200309d3b3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 210309d3b3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 220309d3b3Smrg * DEALINGS IN THE SOFTWARE. 235b944e2aSmrg */ 245b944e2aSmrg 255b944e2aSmrg#include <ctype.h> 265b944e2aSmrg#include <string.h> 275b944e2aSmrg#include <stdlib.h> 285b944e2aSmrg#include <stdint.h> 295b944e2aSmrg#include <X11/Xatom.h> 305b944e2aSmrg#include <X11/extensions/XIproto.h> 315b944e2aSmrg 325b944e2aSmrg#include "xinput.h" 335b944e2aSmrg 3453719b08Smrgstatic Atom parse_atom(Display *dpy, char *name) { 3553719b08Smrg Bool is_atom = True; 3653719b08Smrg int i; 3753719b08Smrg 3853719b08Smrg for (i = 0; name[i] != '\0'; i++) { 3953719b08Smrg if (!isdigit(name[i])) { 4053719b08Smrg is_atom = False; 4153719b08Smrg break; 4253719b08Smrg } 4353719b08Smrg } 4453719b08Smrg 4553719b08Smrg if (is_atom) 4653719b08Smrg return atoi(name); 4753719b08Smrg else 4853719b08Smrg return XInternAtom(dpy, name, False); 4953719b08Smrg} 5053719b08Smrg 515b944e2aSmrgstatic void 525b944e2aSmrgprint_property(Display *dpy, XDevice* dev, Atom property) 535b944e2aSmrg{ 545b944e2aSmrg Atom act_type; 555b944e2aSmrg char *name; 565b944e2aSmrg int act_format; 575b944e2aSmrg unsigned long nitems, bytes_after; 585b944e2aSmrg unsigned char *data, *ptr; 590309d3b3Smrg int j, done = False, size = 0; 605b944e2aSmrg 615b944e2aSmrg name = XGetAtomName(dpy, property); 625b944e2aSmrg printf("\t%s (%ld):\t", name, property); 6333734831Smrg XFree(name); 645b944e2aSmrg 655b944e2aSmrg if (XGetDeviceProperty(dpy, dev, property, 0, 1000, False, 665b944e2aSmrg AnyPropertyType, &act_type, &act_format, 675b944e2aSmrg &nitems, &bytes_after, &data) == Success) 685b944e2aSmrg { 69d3263506Smrg Atom float_atom = XInternAtom(dpy, "FLOAT", True); 705b944e2aSmrg 715b944e2aSmrg ptr = data; 72d3263506Smrg 7353719b08Smrg if (nitems == 0) 7453719b08Smrg printf("<no items>"); 7553719b08Smrg 76d3263506Smrg switch(act_format) 77d3263506Smrg { 78d3263506Smrg case 8: size = sizeof(char); break; 79d3263506Smrg case 16: size = sizeof(short); break; 80d3263506Smrg case 32: size = sizeof(long); break; 81d3263506Smrg } 825b944e2aSmrg 835b944e2aSmrg for (j = 0; j < nitems; j++) 845b944e2aSmrg { 855b944e2aSmrg switch(act_type) 865b944e2aSmrg { 875b944e2aSmrg case XA_INTEGER: 885b944e2aSmrg switch(act_format) 895b944e2aSmrg { 905b944e2aSmrg case 8: 91d3263506Smrg printf("%d", *((char*)ptr)); 925b944e2aSmrg break; 935b944e2aSmrg case 16: 94d3263506Smrg printf("%d", *((short*)ptr)); 955b944e2aSmrg break; 965b944e2aSmrg case 32: 97d3263506Smrg printf("%ld", *((long*)ptr)); 985b944e2aSmrg break; 995b944e2aSmrg } 1005b944e2aSmrg break; 1010309d3b3Smrg case XA_CARDINAL: 1020309d3b3Smrg switch(act_format) 1030309d3b3Smrg { 1040309d3b3Smrg case 8: 1050309d3b3Smrg printf("%u", *((unsigned char*)ptr)); 1060309d3b3Smrg break; 1070309d3b3Smrg case 16: 1080309d3b3Smrg printf("%u", *((unsigned short*)ptr)); 1090309d3b3Smrg break; 1100309d3b3Smrg case 32: 1110309d3b3Smrg printf("%lu", *((unsigned long*)ptr)); 1120309d3b3Smrg break; 1130309d3b3Smrg } 1140309d3b3Smrg break; 1155b944e2aSmrg case XA_STRING: 116d3263506Smrg if (act_format != 8) 117d3263506Smrg { 118d3263506Smrg printf("Unknown string format.\n"); 119d3263506Smrg done = True; 120d3263506Smrg break; 121d3263506Smrg } 122d3263506Smrg printf("\"%s\"", ptr); 123d3263506Smrg j += strlen((char*)ptr); /* The loop's j++ jumps over the 124d3263506Smrg terminating 0 */ 125d3263506Smrg ptr += strlen((char*)ptr); /* ptr += size below jumps over 126d3263506Smrg the terminating 0 */ 1275b944e2aSmrg break; 1285b944e2aSmrg case XA_ATOM: 12953719b08Smrg { 13053719b08Smrg Atom a = *(Atom*)ptr; 13133734831Smrg name = (a) ? XGetAtomName(dpy, a) : NULL; 13233734831Smrg printf("\"%s\" (%d)", name ? name : "None", (int)a); 13333734831Smrg XFree(name); 13453719b08Smrg break; 13553719b08Smrg } 1365b944e2aSmrg default: 1375b944e2aSmrg if (float_atom != None && act_type == float_atom) 1385b944e2aSmrg { 139d3263506Smrg printf("%f", *((float*)ptr)); 1405b944e2aSmrg break; 1415b944e2aSmrg } 1425b944e2aSmrg 14333734831Smrg name = XGetAtomName(dpy, act_type); 14433734831Smrg printf("\t... of unknown type '%s'\n", name); 14533734831Smrg XFree(name); 146d3263506Smrg done = True; 1475b944e2aSmrg break; 1485b944e2aSmrg } 1495b944e2aSmrg 150d3263506Smrg ptr += size; 1515b944e2aSmrg 152d3263506Smrg if (done == True) 1535b944e2aSmrg break; 15453719b08Smrg if (j < nitems - 1) 15553719b08Smrg printf(", "); 1565b944e2aSmrg } 1575b944e2aSmrg printf("\n"); 1585b944e2aSmrg XFree(data); 1595b944e2aSmrg } else 1605b944e2aSmrg printf("\tFetch failure\n"); 1615b944e2aSmrg 1625b944e2aSmrg} 1635b944e2aSmrg 16453719b08Smrgstatic int 16553719b08Smrglist_props_xi1(Display *dpy, int argc, char** argv, char* name, char *desc) 1665b944e2aSmrg{ 1675b944e2aSmrg XDeviceInfo *info; 1685b944e2aSmrg XDevice *dev; 1695b944e2aSmrg int i; 1705b944e2aSmrg int nprops; 1715b944e2aSmrg Atom *props; 172e73734d1Smrg int rc = EXIT_SUCCESS; 1735b944e2aSmrg 1745b944e2aSmrg if (argc == 0) 1755b944e2aSmrg { 1765b944e2aSmrg fprintf(stderr, "Usage: xinput %s %s\n", name, desc); 1775b944e2aSmrg return EXIT_FAILURE; 1785b944e2aSmrg } 1795b944e2aSmrg 1805b944e2aSmrg for (i = 0; i < argc; i++) 1815b944e2aSmrg { 1825b944e2aSmrg info = find_device_info(dpy, argv[i], False); 1835b944e2aSmrg if (!info) 1845b944e2aSmrg { 1850309d3b3Smrg fprintf(stderr, "unable to find device '%s'\n", argv[i]); 186e73734d1Smrg rc = EXIT_FAILURE; 1875b944e2aSmrg continue; 1885b944e2aSmrg } 1895b944e2aSmrg 1905b944e2aSmrg dev = XOpenDevice(dpy, info->id); 1915b944e2aSmrg if (!dev) 1925b944e2aSmrg { 1935b944e2aSmrg fprintf(stderr, "unable to open device '%s'\n", info->name); 194e73734d1Smrg rc = EXIT_FAILURE; 1955b944e2aSmrg continue; 1965b944e2aSmrg } 1975b944e2aSmrg 1985b944e2aSmrg props = XListDeviceProperties(dpy, dev, &nprops); 1995b944e2aSmrg if (!nprops) 2005b944e2aSmrg { 2015b944e2aSmrg printf("Device '%s' does not report any properties.\n", info->name); 2025b944e2aSmrg continue; 2035b944e2aSmrg } 2045b944e2aSmrg 2055b944e2aSmrg printf("Device '%s':\n", info->name); 2065b944e2aSmrg while(nprops--) 2075b944e2aSmrg { 2085b944e2aSmrg print_property(dpy, dev, props[nprops]); 2095b944e2aSmrg } 2105b944e2aSmrg 2115b944e2aSmrg XFree(props); 2125b944e2aSmrg XCloseDevice(dpy, dev); 2135b944e2aSmrg } 214e73734d1Smrg return rc; 2155b944e2aSmrg} 2165b944e2aSmrg 21753719b08Smrg 21853719b08Smrgint watch_props(Display *dpy, int argc, char** argv, char* n, char *desc) 2195b944e2aSmrg{ 2205b944e2aSmrg XDevice *dev; 22153719b08Smrg XDeviceInfo *info; 22253719b08Smrg XEvent ev; 22353719b08Smrg XDevicePropertyNotifyEvent *dpev; 2245b944e2aSmrg char *name; 22553719b08Smrg int type_prop; 22653719b08Smrg XEventClass cls_prop; 2275b944e2aSmrg 22853719b08Smrg if (list_props(dpy, argc, argv, n, desc) != EXIT_SUCCESS) 2295b944e2aSmrg return EXIT_FAILURE; 2305b944e2aSmrg 2315b944e2aSmrg info = find_device_info(dpy, argv[0], False); 2325b944e2aSmrg if (!info) 2335b944e2aSmrg { 2340309d3b3Smrg fprintf(stderr, "unable to find device '%s'\n", argv[0]); 2355b944e2aSmrg return EXIT_FAILURE; 2365b944e2aSmrg } 2375b944e2aSmrg 2385b944e2aSmrg dev = XOpenDevice(dpy, info->id); 2395b944e2aSmrg if (!dev) 2405b944e2aSmrg { 24153719b08Smrg fprintf(stderr, "unable to open device '%s'\n", info->name); 2425b944e2aSmrg return EXIT_FAILURE; 2435b944e2aSmrg } 2445b944e2aSmrg 24553719b08Smrg DevicePropertyNotify(dev, type_prop, cls_prop); 24653719b08Smrg XSelectExtensionEvent(dpy, DefaultRootWindow(dpy), &cls_prop, 1); 2475b944e2aSmrg 24853719b08Smrg while(1) 24953719b08Smrg { 25053719b08Smrg XNextEvent(dpy, &ev); 25153719b08Smrg 25253719b08Smrg dpev = (XDevicePropertyNotifyEvent*)&ev; 25353719b08Smrg if (dpev->type != type_prop) 25453719b08Smrg continue; 25553719b08Smrg 25653719b08Smrg name = XGetAtomName(dpy, dpev->atom); 25753719b08Smrg printf("Property '%s' changed.\n", name); 25833734831Smrg XFree(name); 25953719b08Smrg print_property(dpy, dev, dpev->atom); 2605b944e2aSmrg } 2615b944e2aSmrg 26253719b08Smrg XCloseDevice(dpy, dev); 26353719b08Smrg} 2645b944e2aSmrg 26553719b08Smrgstatic int 26653719b08Smrgdelete_prop_xi1(Display *dpy, int argc, char** argv, char* n, char *desc) 26753719b08Smrg{ 26853719b08Smrg XDevice *dev; 26953719b08Smrg XDeviceInfo *info; 27053719b08Smrg char *name; 27153719b08Smrg Atom prop; 27253719b08Smrg 27353719b08Smrg info = find_device_info(dpy, argv[0], False); 27453719b08Smrg if (!info) 2755b944e2aSmrg { 2760309d3b3Smrg fprintf(stderr, "unable to find device '%s'\n", argv[0]); 2775b944e2aSmrg return EXIT_FAILURE; 2785b944e2aSmrg } 2795b944e2aSmrg 28053719b08Smrg dev = XOpenDevice(dpy, info->id); 28153719b08Smrg if (!dev) 2825b944e2aSmrg { 28353719b08Smrg fprintf(stderr, "unable to open device '%s'\n", info->name); 28453719b08Smrg return EXIT_FAILURE; 2855b944e2aSmrg } 2865b944e2aSmrg 28753719b08Smrg name = argv[1]; 28853719b08Smrg 28953719b08Smrg prop = parse_atom(dpy, name); 29053719b08Smrg 29153719b08Smrg XDeleteDeviceProperty(dpy, dev, prop); 2925b944e2aSmrg 2935b944e2aSmrg XCloseDevice(dpy, dev); 2945b944e2aSmrg return EXIT_SUCCESS; 2955b944e2aSmrg} 2965b944e2aSmrg 29753719b08Smrgstatic int 29853719b08Smrgdo_set_prop_xi1(Display *dpy, Atom type, int format, int argc, char **argv, char *n, char *desc) 2995b944e2aSmrg{ 30053719b08Smrg XDeviceInfo *info; 30153719b08Smrg XDevice *dev; 30253719b08Smrg Atom prop; 30353719b08Smrg Atom old_type; 30453719b08Smrg char *name; 30553719b08Smrg int i; 30653719b08Smrg Atom float_atom; 30753719b08Smrg int old_format, nelements = 0; 30853719b08Smrg unsigned long act_nitems, bytes_after; 30953719b08Smrg char *endptr; 31053719b08Smrg union { 31153719b08Smrg unsigned char *c; 31253719b08Smrg short *s; 31353719b08Smrg long *l; 31453719b08Smrg Atom *a; 31553719b08Smrg } data; 3165b944e2aSmrg 31753719b08Smrg if (argc < 3) 3185b944e2aSmrg { 3195b944e2aSmrg fprintf(stderr, "Usage: xinput %s %s\n", n, desc); 3205b944e2aSmrg return EXIT_FAILURE; 3215b944e2aSmrg } 3225b944e2aSmrg 3235b944e2aSmrg info = find_device_info(dpy, argv[0], False); 3245b944e2aSmrg if (!info) 3255b944e2aSmrg { 3260309d3b3Smrg fprintf(stderr, "unable to find device '%s'\n", argv[0]); 3275b944e2aSmrg return EXIT_FAILURE; 3285b944e2aSmrg } 3295b944e2aSmrg 3305b944e2aSmrg dev = XOpenDevice(dpy, info->id); 3315b944e2aSmrg if (!dev) 3325b944e2aSmrg { 3330309d3b3Smrg fprintf(stderr, "unable to open device '%s'\n", argv[0]); 3345b944e2aSmrg return EXIT_FAILURE; 3355b944e2aSmrg } 3365b944e2aSmrg 3375b944e2aSmrg name = argv[1]; 3385b944e2aSmrg 33953719b08Smrg prop = parse_atom(dpy, name); 34053719b08Smrg 34153719b08Smrg if (prop == None) { 3420309d3b3Smrg fprintf(stderr, "invalid property '%s'\n", name); 34353719b08Smrg return EXIT_FAILURE; 3445b944e2aSmrg } 3455b944e2aSmrg 34653719b08Smrg float_atom = XInternAtom(dpy, "FLOAT", False); 3475b944e2aSmrg 3485b944e2aSmrg nelements = argc - 2; 34953719b08Smrg if (type == None || format == 0) { 35053719b08Smrg if (XGetDeviceProperty(dpy, dev, prop, 0, 0, False, AnyPropertyType, 35153719b08Smrg &old_type, &old_format, &act_nitems, 35253719b08Smrg &bytes_after, &data.c) != Success) { 3530309d3b3Smrg fprintf(stderr, "failed to get property type and format for '%s'\n", 35453719b08Smrg name); 35553719b08Smrg return EXIT_FAILURE; 35653719b08Smrg } else { 35753719b08Smrg if (type == None) 35853719b08Smrg type = old_type; 35953719b08Smrg if (format == 0) 36053719b08Smrg format = old_format; 36153719b08Smrg } 3625b944e2aSmrg 36353719b08Smrg XFree(data.c); 3645b944e2aSmrg } 3655b944e2aSmrg 36653719b08Smrg if (type == None) { 3670309d3b3Smrg fprintf(stderr, "property '%s' doesn't exist, you need to specify " 36853719b08Smrg "its type and format\n", name); 36953719b08Smrg return EXIT_FAILURE; 3705b944e2aSmrg } 3715b944e2aSmrg 37253719b08Smrg data.c = calloc(nelements, sizeof(long)); 37353719b08Smrg 3745b944e2aSmrg for (i = 0; i < nelements; i++) 3755b944e2aSmrg { 3760309d3b3Smrg if (type == XA_INTEGER || type == XA_CARDINAL) { 37753719b08Smrg switch (format) 37853719b08Smrg { 37953719b08Smrg case 8: 38053719b08Smrg data.c[i] = atoi(argv[2 + i]); 38153719b08Smrg break; 38253719b08Smrg case 16: 38353719b08Smrg data.s[i] = atoi(argv[2 + i]); 38453719b08Smrg break; 38553719b08Smrg case 32: 38653719b08Smrg data.l[i] = atoi(argv[2 + i]); 38753719b08Smrg break; 38853719b08Smrg default: 3890309d3b3Smrg fprintf(stderr, "unexpected size for property '%s'", name); 39053719b08Smrg return EXIT_FAILURE; 39153719b08Smrg } 39253719b08Smrg } else if (type == float_atom) { 39353719b08Smrg if (format != 32) { 3940309d3b3Smrg fprintf(stderr, "unexpected format %d for property '%s'\n", 39553719b08Smrg format, name); 39653719b08Smrg return EXIT_FAILURE; 39753719b08Smrg } 39853719b08Smrg *(float *)(data.l + i) = strtod(argv[2 + i], &endptr); 39953719b08Smrg if (endptr == argv[2 + i]) { 4000309d3b3Smrg fprintf(stderr, "argument '%s' could not be parsed\n", argv[2 + i]); 40153719b08Smrg return EXIT_FAILURE; 40253719b08Smrg } 40353719b08Smrg } else if (type == XA_ATOM) { 40453719b08Smrg if (format != 32) { 4050309d3b3Smrg fprintf(stderr, "unexpected format %d for property '%s'\n", 40653719b08Smrg format, name); 40753719b08Smrg return EXIT_FAILURE; 40853719b08Smrg } 40953719b08Smrg data.a[i] = parse_atom(dpy, argv[2 + i]); 41053719b08Smrg } else { 4110309d3b3Smrg fprintf(stderr, "unexpected type for property '%s'\n", name); 41253719b08Smrg return EXIT_FAILURE; 41353719b08Smrg } 4145b944e2aSmrg } 4155b944e2aSmrg 41653719b08Smrg XChangeDeviceProperty(dpy, dev, prop, type, format, PropModeReplace, 41753719b08Smrg data.c, nelements); 41853719b08Smrg free(data.c); 4195b944e2aSmrg XCloseDevice(dpy, dev); 4205b944e2aSmrg return EXIT_SUCCESS; 4215b944e2aSmrg} 4225b944e2aSmrg 42353719b08Smrg#if HAVE_XI2 42453719b08Smrgstatic void 42553719b08Smrgprint_property_xi2(Display *dpy, int deviceid, Atom property) 4265b944e2aSmrg{ 42753719b08Smrg Atom act_type; 42853719b08Smrg char *name; 42953719b08Smrg int act_format; 43053719b08Smrg unsigned long nitems, bytes_after; 43153719b08Smrg unsigned char *data, *ptr; 43253719b08Smrg int j, done = False; 4335b944e2aSmrg 43453719b08Smrg name = XGetAtomName(dpy, property); 43553719b08Smrg printf("\t%s (%ld):\t", name, property); 43633734831Smrg XFree(name); 4375b944e2aSmrg 43853719b08Smrg if (XIGetProperty(dpy, deviceid, property, 0, 1000, False, 43953719b08Smrg AnyPropertyType, &act_type, &act_format, 44053719b08Smrg &nitems, &bytes_after, &data) == Success) 4415b944e2aSmrg { 44253719b08Smrg Atom float_atom = XInternAtom(dpy, "FLOAT", True); 4435b944e2aSmrg 44453719b08Smrg ptr = data; 44553719b08Smrg 44653719b08Smrg if (nitems == 0) 44753719b08Smrg printf("<no items>"); 44853719b08Smrg 44953719b08Smrg for (j = 0; j < nitems; j++) 45053719b08Smrg { 45153719b08Smrg switch(act_type) 45253719b08Smrg { 45353719b08Smrg case XA_INTEGER: 45453719b08Smrg switch(act_format) 45553719b08Smrg { 45653719b08Smrg case 8: 45753719b08Smrg printf("%d", *((int8_t*)ptr)); 45853719b08Smrg break; 45953719b08Smrg case 16: 46053719b08Smrg printf("%d", *((int16_t*)ptr)); 46153719b08Smrg break; 46253719b08Smrg case 32: 46353719b08Smrg printf("%d", *((int32_t*)ptr)); 46453719b08Smrg break; 46553719b08Smrg } 46653719b08Smrg break; 4670309d3b3Smrg case XA_CARDINAL: 4680309d3b3Smrg switch(act_format) 4690309d3b3Smrg { 4700309d3b3Smrg case 8: 4710309d3b3Smrg printf("%u", *((uint8_t*)ptr)); 4720309d3b3Smrg break; 4730309d3b3Smrg case 16: 4740309d3b3Smrg printf("%u", *((uint16_t*)ptr)); 4750309d3b3Smrg break; 4760309d3b3Smrg case 32: 4770309d3b3Smrg printf("%u", *((uint32_t*)ptr)); 4780309d3b3Smrg break; 4790309d3b3Smrg } 4800309d3b3Smrg break; 48153719b08Smrg case XA_STRING: 48253719b08Smrg if (act_format != 8) 48353719b08Smrg { 48453719b08Smrg printf("Unknown string format.\n"); 48553719b08Smrg done = True; 48653719b08Smrg break; 48753719b08Smrg } 48853719b08Smrg printf("\"%s\"", ptr); 48953719b08Smrg j += strlen((char*)ptr); /* The loop's j++ jumps over the 49053719b08Smrg terminating 0 */ 49153719b08Smrg ptr += strlen((char*)ptr); /* ptr += size below jumps over 49253719b08Smrg the terminating 0 */ 49353719b08Smrg break; 49453719b08Smrg case XA_ATOM: 49553719b08Smrg { 496cea37944Smrg Atom a = *(uint32_t*)ptr; 49733734831Smrg name = (a) ? XGetAtomName(dpy, a) : NULL; 49833734831Smrg printf("\"%s\" (%ld)", name ? name : "None", a); 49933734831Smrg XFree(name); 50053719b08Smrg break; 50153719b08Smrg } 50253719b08Smrg break; 50353719b08Smrg default: 50453719b08Smrg if (float_atom != None && act_type == float_atom) 50553719b08Smrg { 50653719b08Smrg printf("%f", *((float*)ptr)); 50753719b08Smrg break; 50853719b08Smrg } 50953719b08Smrg 51033734831Smrg name = XGetAtomName(dpy, act_type); 51133734831Smrg printf("\t... of unknown type %s\n", name); 51233734831Smrg XFree(name); 51353719b08Smrg done = True; 51453719b08Smrg break; 51553719b08Smrg } 51653719b08Smrg 51753719b08Smrg ptr += act_format/8; 51853719b08Smrg 51953719b08Smrg if (done == True) 52053719b08Smrg break; 52153719b08Smrg if (j < nitems - 1) 52253719b08Smrg printf(", "); 52353719b08Smrg } 52453719b08Smrg printf("\n"); 52553719b08Smrg XFree(data); 52653719b08Smrg } else 52753719b08Smrg printf("\tFetch failure\n"); 52853719b08Smrg 52953719b08Smrg} 53053719b08Smrg 53153719b08Smrgstatic int 53253719b08Smrglist_props_xi2(Display *dpy, int argc, char** argv, char* name, char *desc) 53353719b08Smrg{ 53453719b08Smrg XIDeviceInfo *info; 53553719b08Smrg int i; 53653719b08Smrg int nprops; 53753719b08Smrg Atom *props; 538e73734d1Smrg int rc = EXIT_SUCCESS; 53953719b08Smrg 54053719b08Smrg if (argc == 0) 5415b944e2aSmrg { 54253719b08Smrg fprintf(stderr, "Usage: xinput %s %s\n", name, desc); 5435b944e2aSmrg return EXIT_FAILURE; 5445b944e2aSmrg } 5455b944e2aSmrg 54653719b08Smrg for (i = 0; i < argc; i++) 5475b944e2aSmrg { 54853719b08Smrg info = xi2_find_device_info(dpy, argv[i]); 54953719b08Smrg if (!info) 55053719b08Smrg { 55153719b08Smrg fprintf(stderr, "unable to find device %s\n", argv[i]); 552e73734d1Smrg rc = EXIT_FAILURE; 55353719b08Smrg continue; 55453719b08Smrg } 5555b944e2aSmrg 55653719b08Smrg props = XIListProperties(dpy, info->deviceid, &nprops); 55753719b08Smrg if (!nprops) 55853719b08Smrg { 55953719b08Smrg printf("Device '%s' does not report any properties.\n", info->name); 5605b944e2aSmrg continue; 56153719b08Smrg } 5625b944e2aSmrg 56353719b08Smrg printf("Device '%s':\n", info->name); 56453719b08Smrg while(nprops--) 56553719b08Smrg { 56653719b08Smrg print_property_xi2(dpy, info->deviceid, props[nprops]); 56753719b08Smrg } 5685b944e2aSmrg 56953719b08Smrg XFree(props); 57053719b08Smrg } 571e73734d1Smrg return rc; 5725b944e2aSmrg} 5735b944e2aSmrg 57453719b08Smrgstatic int 57553719b08Smrgdelete_prop_xi2(Display *dpy, int argc, char** argv, char* n, char *desc) 5765b944e2aSmrg{ 57753719b08Smrg XIDeviceInfo *info; 5785b944e2aSmrg char *name; 5795b944e2aSmrg Atom prop; 5805b944e2aSmrg 58153719b08Smrg info = xi2_find_device_info(dpy, argv[0]); 5825b944e2aSmrg if (!info) 5835b944e2aSmrg { 5845b944e2aSmrg fprintf(stderr, "unable to find device %s\n", argv[0]); 5855b944e2aSmrg return EXIT_FAILURE; 5865b944e2aSmrg } 5875b944e2aSmrg 5885b944e2aSmrg name = argv[1]; 5895b944e2aSmrg 59053719b08Smrg prop = parse_atom(dpy, name); 5915b944e2aSmrg 59253719b08Smrg XIDeleteProperty(dpy, info->deviceid, prop); 5935b944e2aSmrg 5945b944e2aSmrg return EXIT_SUCCESS; 5955b944e2aSmrg} 5965b944e2aSmrg 59753719b08Smrgstatic int 59853719b08Smrgdo_set_prop_xi2(Display *dpy, Atom type, int format, int argc, char **argv, char *n, char *desc) 5995b944e2aSmrg{ 60053719b08Smrg XIDeviceInfo *info; 60153719b08Smrg Atom prop; 60253719b08Smrg Atom old_type; 60353719b08Smrg char *name; 60453719b08Smrg int i; 60553719b08Smrg Atom float_atom; 60653719b08Smrg int old_format, nelements = 0; 60753719b08Smrg unsigned long act_nitems, bytes_after; 60853719b08Smrg char *endptr; 60953719b08Smrg union { 61053719b08Smrg unsigned char *c; 61153719b08Smrg int16_t *s; 61253719b08Smrg int32_t *l; 613a570218aSmrg } data = { NULL }; 614a570218aSmrg int rc = EXIT_FAILURE; 6155b944e2aSmrg 6165b944e2aSmrg if (argc < 3) 6175b944e2aSmrg { 6185b944e2aSmrg fprintf(stderr, "Usage: xinput %s %s\n", n, desc); 619a570218aSmrg goto out; 6205b944e2aSmrg } 6215b944e2aSmrg 62253719b08Smrg info = xi2_find_device_info(dpy, argv[0]); 6235b944e2aSmrg if (!info) 6245b944e2aSmrg { 6255b944e2aSmrg fprintf(stderr, "unable to find device %s\n", argv[0]); 626a570218aSmrg goto out; 6275b944e2aSmrg } 6285b944e2aSmrg 62953719b08Smrg name = argv[1]; 63053719b08Smrg 63153719b08Smrg prop = parse_atom(dpy, name); 63253719b08Smrg 63353719b08Smrg if (prop == None) { 6340309d3b3Smrg fprintf(stderr, "invalid property '%s'\n", name); 635a570218aSmrg goto out; 6365b944e2aSmrg } 6375b944e2aSmrg 63853719b08Smrg float_atom = XInternAtom(dpy, "FLOAT", False); 6395b944e2aSmrg 64053719b08Smrg nelements = argc - 2; 64153719b08Smrg if (type == None || format == 0) { 64253719b08Smrg if (XIGetProperty(dpy, info->deviceid, prop, 0, 0, False, 64353719b08Smrg AnyPropertyType, &old_type, &old_format, &act_nitems, 64453719b08Smrg &bytes_after, &data.c) != Success) { 6450309d3b3Smrg fprintf(stderr, "failed to get property type and format for '%s'\n", 64653719b08Smrg name); 647a570218aSmrg goto out; 64853719b08Smrg } else { 64953719b08Smrg if (type == None) 65053719b08Smrg type = old_type; 65153719b08Smrg if (format == 0) 65253719b08Smrg format = old_format; 65353719b08Smrg } 65453719b08Smrg 65553719b08Smrg XFree(data.c); 6565b944e2aSmrg } 6575b944e2aSmrg 65853719b08Smrg if (type == None) { 6590309d3b3Smrg fprintf(stderr, "property '%s' doesn't exist, you need to specify " 66053719b08Smrg "its type and format\n", name); 661a570218aSmrg goto out; 66253719b08Smrg } 66353719b08Smrg 66453719b08Smrg data.c = calloc(nelements, sizeof(int32_t)); 6655b944e2aSmrg 6665b944e2aSmrg for (i = 0; i < nelements; i++) 6675b944e2aSmrg { 6680309d3b3Smrg if (type == XA_INTEGER || type == XA_CARDINAL) { 66953719b08Smrg switch (format) 67053719b08Smrg { 67153719b08Smrg case 8: 67253719b08Smrg data.c[i] = atoi(argv[2 + i]); 67353719b08Smrg break; 67453719b08Smrg case 16: 67553719b08Smrg data.s[i] = atoi(argv[2 + i]); 67653719b08Smrg break; 67753719b08Smrg case 32: 67853719b08Smrg data.l[i] = atoi(argv[2 + i]); 67953719b08Smrg break; 68053719b08Smrg default: 68153719b08Smrg fprintf(stderr, "unexpected size for property %s", name); 682a570218aSmrg goto out; 68353719b08Smrg } 68453719b08Smrg } else if (type == float_atom) { 68553719b08Smrg if (format != 32) { 6860309d3b3Smrg fprintf(stderr, "unexpected format %d for property '%s'\n", 68753719b08Smrg format, name); 688a570218aSmrg goto out; 68953719b08Smrg } 69053719b08Smrg *(float *)(data.l + i) = strtod(argv[2 + i], &endptr); 69153719b08Smrg if (endptr == argv[2 + i]) { 69253719b08Smrg fprintf(stderr, "argument %s could not be parsed\n", argv[2 + i]); 693a570218aSmrg goto out; 6945b944e2aSmrg } 69553719b08Smrg } else if (type == XA_ATOM) { 69653719b08Smrg if (format != 32) { 6970309d3b3Smrg fprintf(stderr, "unexpected format %d for property '%s'\n", 69853719b08Smrg format, name); 699a570218aSmrg goto out; 70053719b08Smrg } 70153719b08Smrg data.l[i] = parse_atom(dpy, argv[2 + i]); 70253719b08Smrg } else { 7030309d3b3Smrg fprintf(stderr, "unexpected type for property '%s'\n", name); 704a570218aSmrg goto out; 7055b944e2aSmrg } 70653719b08Smrg } 7075b944e2aSmrg 70853719b08Smrg XIChangeProperty(dpy, info->deviceid, prop, type, format, PropModeReplace, 70953719b08Smrg data.c, nelements); 710a570218aSmrg rc = EXIT_SUCCESS; 711a570218aSmrgout: 71253719b08Smrg free(data.c); 713a570218aSmrg return rc; 71453719b08Smrg} 71553719b08Smrg#endif 71653719b08Smrg 71753719b08Smrgint list_props(Display *display, int argc, char *argv[], char *name, 71853719b08Smrg char *desc) 71953719b08Smrg{ 720a570218aSmrg#if HAVE_XI2 72153719b08Smrg if (xinput_version(display) == XI_2_Major) 72253719b08Smrg return list_props_xi2(display, argc, argv, name, desc); 72353719b08Smrg#endif 72453719b08Smrg return list_props_xi1(display, argc, argv, name, desc); 72553719b08Smrg 72653719b08Smrg} 72753719b08Smrg 72853719b08Smrgint delete_prop(Display *display, int argc, char *argv[], char *name, 72953719b08Smrg char *desc) 73053719b08Smrg{ 731a570218aSmrg#if HAVE_XI2 73253719b08Smrg if (xinput_version(display) == XI_2_Major) 73353719b08Smrg return delete_prop_xi2(display, argc, argv, name, desc); 73453719b08Smrg#endif 73553719b08Smrg return delete_prop_xi1(display, argc, argv, name, desc); 73653719b08Smrg 73753719b08Smrg} 73853719b08Smrg 73953719b08Smrgstatic int 74053719b08Smrgdo_set_prop(Display *display, Atom type, int format, int argc, char *argv[], char *name, char *desc) 74153719b08Smrg{ 742a570218aSmrg#if HAVE_XI2 74353719b08Smrg if (xinput_version(display) == XI_2_Major) 74453719b08Smrg return do_set_prop_xi2(display, type, format, argc, argv, name, desc); 74553719b08Smrg#endif 74653719b08Smrg return do_set_prop_xi1(display, type, format, argc, argv, name, desc); 74753719b08Smrg} 74853719b08Smrg 74953719b08Smrgint 75053719b08Smrgset_atom_prop(Display *dpy, int argc, char** argv, char* n, char *desc) 75153719b08Smrg{ 75253719b08Smrg return do_set_prop(dpy, XA_ATOM, 32, argc, argv, n, desc); 75353719b08Smrg} 75453719b08Smrg 75553719b08Smrgint 75653719b08Smrgset_int_prop(Display *dpy, int argc, char** argv, char* n, char *desc) 75753719b08Smrg{ 75853719b08Smrg int i; 75953719b08Smrg int format; 76053719b08Smrg 76153719b08Smrg if (argc < 3) 76253719b08Smrg { 76353719b08Smrg fprintf(stderr, "Usage: xinput %s %s\n", n, desc); 76453719b08Smrg return EXIT_FAILURE; 7655b944e2aSmrg } 7665b944e2aSmrg 76753719b08Smrg format = atoi(argv[2]); 76853719b08Smrg if (format != 8 && format != 16 && format != 32) 76953719b08Smrg { 77053719b08Smrg fprintf(stderr, "Invalid format %d\n", format); 77153719b08Smrg return EXIT_FAILURE; 77253719b08Smrg } 7735b944e2aSmrg 77453719b08Smrg for (i = 3; i < argc; i++) 77553719b08Smrg argv[i - 1] = argv[i]; 77653719b08Smrg 77753719b08Smrg return do_set_prop(dpy, XA_INTEGER, format, argc - 1, argv, n, desc); 7785b944e2aSmrg} 7795b944e2aSmrg 78053719b08Smrgint 78153719b08Smrgset_float_prop(Display *dpy, int argc, char** argv, char* n, char *desc) 78253719b08Smrg{ 78353719b08Smrg Atom float_atom = XInternAtom(dpy, "FLOAT", False); 78453719b08Smrg 78553719b08Smrg if (sizeof(float) != 4) 78653719b08Smrg { 78753719b08Smrg fprintf(stderr, "sane FP required\n"); 78853719b08Smrg return EXIT_FAILURE; 78953719b08Smrg } 79053719b08Smrg 79153719b08Smrg return do_set_prop(dpy, float_atom, 32, argc, argv, n, desc); 79253719b08Smrg} 7935b944e2aSmrg 79453719b08Smrgint set_prop(Display *display, int argc, char *argv[], char *name, 79553719b08Smrg char *desc) 79653719b08Smrg{ 79753719b08Smrg Atom type = None; 79853719b08Smrg int format = 0; 79953719b08Smrg int i = 0, j; 80053719b08Smrg 80153719b08Smrg while (i < argc) { 80253719b08Smrg char *option = strchr(argv[i], '='); 80353719b08Smrg /* skip non-option arguments */ 80453719b08Smrg if (strncmp(argv[i], "--", 2) || !option) { 80553719b08Smrg i++; 80653719b08Smrg continue; 80753719b08Smrg } 80853719b08Smrg 80953719b08Smrg if (!strncmp(argv[i], "--type=", strlen("--type="))) { 81053719b08Smrg if (!strcmp(option + 1, "int")) { 81153719b08Smrg type = XA_INTEGER; 81253719b08Smrg } else if (!strcmp(option + 1, "float")) { 81353719b08Smrg type = XInternAtom(display, "FLOAT", False); 81453719b08Smrg format = 32; 81553719b08Smrg } else if (!strcmp(option + 1, "atom")) { 81653719b08Smrg type = XA_ATOM; 81753719b08Smrg format = 32; 81853719b08Smrg } else { 81953719b08Smrg fprintf(stderr, "unknown property type %s\n", option + 1); 82053719b08Smrg return EXIT_FAILURE; 82153719b08Smrg } 82253719b08Smrg } else if (!strncmp(argv[i], "--format=", strlen("--format="))) { 82353719b08Smrg format = atoi(option + 1); 82453719b08Smrg if (format != 8 && format != 16 && format != 32) { 8250309d3b3Smrg fprintf(stderr, "invalid property format '%s'\n", option + 1); 82653719b08Smrg return EXIT_FAILURE; 82753719b08Smrg } 82853719b08Smrg } else { 8290309d3b3Smrg fprintf(stderr, "invalid option '%s'\n", argv[i]); 83053719b08Smrg return EXIT_FAILURE; 83153719b08Smrg } 83253719b08Smrg 83353719b08Smrg for (j = i; j + 1 < argc; j++) 83453719b08Smrg argv[j] = argv[j + 1]; 83553719b08Smrg argc--; 83653719b08Smrg } 83753719b08Smrg 83853719b08Smrg return do_set_prop(display, type, format, argc, argv, name, desc); 83953719b08Smrg} 8400309d3b3Smrg 8410309d3b3Smrgint disable(Display *display, int argc, char *argv[], char *name, char *desc) 8420309d3b3Smrg{ 843e73734d1Smrg char *new_argv[3] = { NULL, "Device Enabled", "0" }; 844e73734d1Smrg 845e73734d1Smrg if (argc != 1) { 846e73734d1Smrg fprintf(stderr, "Usage: xinput %s %s\n", name, desc); 847e73734d1Smrg return EXIT_FAILURE; 848e73734d1Smrg } 849e73734d1Smrg 850e73734d1Smrg new_argv[0] = argv[0]; 851e73734d1Smrg 8520309d3b3Smrg return set_prop(display, 3, new_argv, name, desc); 8530309d3b3Smrg} 8540309d3b3Smrg 8550309d3b3Smrgint enable(Display *display, int argc, char *argv[], char *name, char *desc) 8560309d3b3Smrg{ 857e73734d1Smrg char *new_argv[3] = { NULL, "Device Enabled", "1" }; 858e73734d1Smrg 859e73734d1Smrg if (argc != 1) { 860e73734d1Smrg fprintf(stderr, "Usage: xinput %s %s\n", name, desc); 861e73734d1Smrg return EXIT_FAILURE; 862e73734d1Smrg } 863e73734d1Smrg 864e73734d1Smrg new_argv[0] = argv[0]; 865e73734d1Smrg 8660309d3b3Smrg return set_prop(display, 3, new_argv, name, desc); 8670309d3b3Smrg} 868