property.c revision 0309d3b3
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); 635b944e2aSmrg 645b944e2aSmrg if (XGetDeviceProperty(dpy, dev, property, 0, 1000, False, 655b944e2aSmrg AnyPropertyType, &act_type, &act_format, 665b944e2aSmrg &nitems, &bytes_after, &data) == Success) 675b944e2aSmrg { 68d3263506Smrg Atom float_atom = XInternAtom(dpy, "FLOAT", True); 695b944e2aSmrg 705b944e2aSmrg ptr = data; 71d3263506Smrg 7253719b08Smrg if (nitems == 0) 7353719b08Smrg printf("<no items>"); 7453719b08Smrg 75d3263506Smrg switch(act_format) 76d3263506Smrg { 77d3263506Smrg case 8: size = sizeof(char); break; 78d3263506Smrg case 16: size = sizeof(short); break; 79d3263506Smrg case 32: size = sizeof(long); break; 80d3263506Smrg } 815b944e2aSmrg 825b944e2aSmrg for (j = 0; j < nitems; j++) 835b944e2aSmrg { 845b944e2aSmrg switch(act_type) 855b944e2aSmrg { 865b944e2aSmrg case XA_INTEGER: 875b944e2aSmrg switch(act_format) 885b944e2aSmrg { 895b944e2aSmrg case 8: 90d3263506Smrg printf("%d", *((char*)ptr)); 915b944e2aSmrg break; 925b944e2aSmrg case 16: 93d3263506Smrg printf("%d", *((short*)ptr)); 945b944e2aSmrg break; 955b944e2aSmrg case 32: 96d3263506Smrg printf("%ld", *((long*)ptr)); 975b944e2aSmrg break; 985b944e2aSmrg } 995b944e2aSmrg break; 1000309d3b3Smrg case XA_CARDINAL: 1010309d3b3Smrg switch(act_format) 1020309d3b3Smrg { 1030309d3b3Smrg case 8: 1040309d3b3Smrg printf("%u", *((unsigned char*)ptr)); 1050309d3b3Smrg break; 1060309d3b3Smrg case 16: 1070309d3b3Smrg printf("%u", *((unsigned short*)ptr)); 1080309d3b3Smrg break; 1090309d3b3Smrg case 32: 1100309d3b3Smrg printf("%lu", *((unsigned long*)ptr)); 1110309d3b3Smrg break; 1120309d3b3Smrg } 1130309d3b3Smrg break; 1145b944e2aSmrg case XA_STRING: 115d3263506Smrg if (act_format != 8) 116d3263506Smrg { 117d3263506Smrg printf("Unknown string format.\n"); 118d3263506Smrg done = True; 119d3263506Smrg break; 120d3263506Smrg } 121d3263506Smrg printf("\"%s\"", ptr); 122d3263506Smrg j += strlen((char*)ptr); /* The loop's j++ jumps over the 123d3263506Smrg terminating 0 */ 124d3263506Smrg ptr += strlen((char*)ptr); /* ptr += size below jumps over 125d3263506Smrg the terminating 0 */ 1265b944e2aSmrg break; 1275b944e2aSmrg case XA_ATOM: 12853719b08Smrg { 12953719b08Smrg Atom a = *(Atom*)ptr; 13053719b08Smrg printf("\"%s\" (%d)", 13153719b08Smrg (a) ? XGetAtomName(dpy, a) : "None", 13253719b08Smrg (int)a); 13353719b08Smrg break; 13453719b08Smrg } 1355b944e2aSmrg default: 1365b944e2aSmrg if (float_atom != None && act_type == float_atom) 1375b944e2aSmrg { 138d3263506Smrg printf("%f", *((float*)ptr)); 1395b944e2aSmrg break; 1405b944e2aSmrg } 1415b944e2aSmrg 1420309d3b3Smrg printf("\t... of unknown type '%s'\n", 1435b944e2aSmrg XGetAtomName(dpy, act_type)); 144d3263506Smrg done = True; 1455b944e2aSmrg break; 1465b944e2aSmrg } 1475b944e2aSmrg 148d3263506Smrg ptr += size; 1495b944e2aSmrg 150d3263506Smrg if (done == True) 1515b944e2aSmrg break; 15253719b08Smrg if (j < nitems - 1) 15353719b08Smrg printf(", "); 1545b944e2aSmrg } 1555b944e2aSmrg printf("\n"); 1565b944e2aSmrg XFree(data); 1575b944e2aSmrg } else 1585b944e2aSmrg printf("\tFetch failure\n"); 1595b944e2aSmrg 1605b944e2aSmrg} 1615b944e2aSmrg 16253719b08Smrgstatic int 16353719b08Smrglist_props_xi1(Display *dpy, int argc, char** argv, char* name, char *desc) 1645b944e2aSmrg{ 1655b944e2aSmrg XDeviceInfo *info; 1665b944e2aSmrg XDevice *dev; 1675b944e2aSmrg int i; 1685b944e2aSmrg int nprops; 1695b944e2aSmrg Atom *props; 1705b944e2aSmrg 1715b944e2aSmrg if (argc == 0) 1725b944e2aSmrg { 1735b944e2aSmrg fprintf(stderr, "Usage: xinput %s %s\n", name, desc); 1745b944e2aSmrg return EXIT_FAILURE; 1755b944e2aSmrg } 1765b944e2aSmrg 1775b944e2aSmrg for (i = 0; i < argc; i++) 1785b944e2aSmrg { 1795b944e2aSmrg info = find_device_info(dpy, argv[i], False); 1805b944e2aSmrg if (!info) 1815b944e2aSmrg { 1820309d3b3Smrg fprintf(stderr, "unable to find device '%s'\n", argv[i]); 1835b944e2aSmrg continue; 1845b944e2aSmrg } 1855b944e2aSmrg 1865b944e2aSmrg dev = XOpenDevice(dpy, info->id); 1875b944e2aSmrg if (!dev) 1885b944e2aSmrg { 1895b944e2aSmrg fprintf(stderr, "unable to open device '%s'\n", info->name); 1905b944e2aSmrg continue; 1915b944e2aSmrg } 1925b944e2aSmrg 1935b944e2aSmrg props = XListDeviceProperties(dpy, dev, &nprops); 1945b944e2aSmrg if (!nprops) 1955b944e2aSmrg { 1965b944e2aSmrg printf("Device '%s' does not report any properties.\n", info->name); 1975b944e2aSmrg continue; 1985b944e2aSmrg } 1995b944e2aSmrg 2005b944e2aSmrg printf("Device '%s':\n", info->name); 2015b944e2aSmrg while(nprops--) 2025b944e2aSmrg { 2035b944e2aSmrg print_property(dpy, dev, props[nprops]); 2045b944e2aSmrg } 2055b944e2aSmrg 2065b944e2aSmrg XFree(props); 2075b944e2aSmrg XCloseDevice(dpy, dev); 2085b944e2aSmrg } 2095b944e2aSmrg return EXIT_SUCCESS; 2105b944e2aSmrg} 2115b944e2aSmrg 21253719b08Smrg 21353719b08Smrgint watch_props(Display *dpy, int argc, char** argv, char* n, char *desc) 2145b944e2aSmrg{ 2155b944e2aSmrg XDevice *dev; 21653719b08Smrg XDeviceInfo *info; 21753719b08Smrg XEvent ev; 21853719b08Smrg XDevicePropertyNotifyEvent *dpev; 2195b944e2aSmrg char *name; 22053719b08Smrg int type_prop; 22153719b08Smrg XEventClass cls_prop; 2225b944e2aSmrg 22353719b08Smrg if (list_props(dpy, argc, argv, n, desc) != EXIT_SUCCESS) 2245b944e2aSmrg return EXIT_FAILURE; 2255b944e2aSmrg 2265b944e2aSmrg info = find_device_info(dpy, argv[0], False); 2275b944e2aSmrg if (!info) 2285b944e2aSmrg { 2290309d3b3Smrg fprintf(stderr, "unable to find device '%s'\n", argv[0]); 2305b944e2aSmrg return EXIT_FAILURE; 2315b944e2aSmrg } 2325b944e2aSmrg 2335b944e2aSmrg dev = XOpenDevice(dpy, info->id); 2345b944e2aSmrg if (!dev) 2355b944e2aSmrg { 23653719b08Smrg fprintf(stderr, "unable to open device '%s'\n", info->name); 2375b944e2aSmrg return EXIT_FAILURE; 2385b944e2aSmrg } 2395b944e2aSmrg 24053719b08Smrg DevicePropertyNotify(dev, type_prop, cls_prop); 24153719b08Smrg XSelectExtensionEvent(dpy, DefaultRootWindow(dpy), &cls_prop, 1); 2425b944e2aSmrg 24353719b08Smrg while(1) 24453719b08Smrg { 24553719b08Smrg XNextEvent(dpy, &ev); 24653719b08Smrg 24753719b08Smrg dpev = (XDevicePropertyNotifyEvent*)&ev; 24853719b08Smrg if (dpev->type != type_prop) 24953719b08Smrg continue; 25053719b08Smrg 25153719b08Smrg name = XGetAtomName(dpy, dpev->atom); 25253719b08Smrg printf("Property '%s' changed.\n", name); 25353719b08Smrg print_property(dpy, dev, dpev->atom); 2545b944e2aSmrg } 2555b944e2aSmrg 25653719b08Smrg XCloseDevice(dpy, dev); 25753719b08Smrg} 2585b944e2aSmrg 25953719b08Smrgstatic int 26053719b08Smrgdelete_prop_xi1(Display *dpy, int argc, char** argv, char* n, char *desc) 26153719b08Smrg{ 26253719b08Smrg XDevice *dev; 26353719b08Smrg XDeviceInfo *info; 26453719b08Smrg char *name; 26553719b08Smrg Atom prop; 26653719b08Smrg 26753719b08Smrg info = find_device_info(dpy, argv[0], False); 26853719b08Smrg if (!info) 2695b944e2aSmrg { 2700309d3b3Smrg fprintf(stderr, "unable to find device '%s'\n", argv[0]); 2715b944e2aSmrg return EXIT_FAILURE; 2725b944e2aSmrg } 2735b944e2aSmrg 27453719b08Smrg dev = XOpenDevice(dpy, info->id); 27553719b08Smrg if (!dev) 2765b944e2aSmrg { 27753719b08Smrg fprintf(stderr, "unable to open device '%s'\n", info->name); 27853719b08Smrg return EXIT_FAILURE; 2795b944e2aSmrg } 2805b944e2aSmrg 28153719b08Smrg name = argv[1]; 28253719b08Smrg 28353719b08Smrg prop = parse_atom(dpy, name); 28453719b08Smrg 28553719b08Smrg XDeleteDeviceProperty(dpy, dev, prop); 2865b944e2aSmrg 2875b944e2aSmrg XCloseDevice(dpy, dev); 2885b944e2aSmrg return EXIT_SUCCESS; 2895b944e2aSmrg} 2905b944e2aSmrg 29153719b08Smrgstatic int 29253719b08Smrgdo_set_prop_xi1(Display *dpy, Atom type, int format, int argc, char **argv, char *n, char *desc) 2935b944e2aSmrg{ 29453719b08Smrg XDeviceInfo *info; 29553719b08Smrg XDevice *dev; 29653719b08Smrg Atom prop; 29753719b08Smrg Atom old_type; 29853719b08Smrg char *name; 29953719b08Smrg int i; 30053719b08Smrg Atom float_atom; 30153719b08Smrg int old_format, nelements = 0; 30253719b08Smrg unsigned long act_nitems, bytes_after; 30353719b08Smrg char *endptr; 30453719b08Smrg union { 30553719b08Smrg unsigned char *c; 30653719b08Smrg short *s; 30753719b08Smrg long *l; 30853719b08Smrg Atom *a; 30953719b08Smrg } data; 3105b944e2aSmrg 31153719b08Smrg if (argc < 3) 3125b944e2aSmrg { 3135b944e2aSmrg fprintf(stderr, "Usage: xinput %s %s\n", n, desc); 3145b944e2aSmrg return EXIT_FAILURE; 3155b944e2aSmrg } 3165b944e2aSmrg 3175b944e2aSmrg info = find_device_info(dpy, argv[0], False); 3185b944e2aSmrg if (!info) 3195b944e2aSmrg { 3200309d3b3Smrg fprintf(stderr, "unable to find device '%s'\n", argv[0]); 3215b944e2aSmrg return EXIT_FAILURE; 3225b944e2aSmrg } 3235b944e2aSmrg 3245b944e2aSmrg dev = XOpenDevice(dpy, info->id); 3255b944e2aSmrg if (!dev) 3265b944e2aSmrg { 3270309d3b3Smrg fprintf(stderr, "unable to open device '%s'\n", argv[0]); 3285b944e2aSmrg return EXIT_FAILURE; 3295b944e2aSmrg } 3305b944e2aSmrg 3315b944e2aSmrg name = argv[1]; 3325b944e2aSmrg 33353719b08Smrg prop = parse_atom(dpy, name); 33453719b08Smrg 33553719b08Smrg if (prop == None) { 3360309d3b3Smrg fprintf(stderr, "invalid property '%s'\n", name); 33753719b08Smrg return EXIT_FAILURE; 3385b944e2aSmrg } 3395b944e2aSmrg 34053719b08Smrg float_atom = XInternAtom(dpy, "FLOAT", False); 3415b944e2aSmrg 3425b944e2aSmrg nelements = argc - 2; 34353719b08Smrg if (type == None || format == 0) { 34453719b08Smrg if (XGetDeviceProperty(dpy, dev, prop, 0, 0, False, AnyPropertyType, 34553719b08Smrg &old_type, &old_format, &act_nitems, 34653719b08Smrg &bytes_after, &data.c) != Success) { 3470309d3b3Smrg fprintf(stderr, "failed to get property type and format for '%s'\n", 34853719b08Smrg name); 34953719b08Smrg return EXIT_FAILURE; 35053719b08Smrg } else { 35153719b08Smrg if (type == None) 35253719b08Smrg type = old_type; 35353719b08Smrg if (format == 0) 35453719b08Smrg format = old_format; 35553719b08Smrg } 3565b944e2aSmrg 35753719b08Smrg XFree(data.c); 3585b944e2aSmrg } 3595b944e2aSmrg 36053719b08Smrg if (type == None) { 3610309d3b3Smrg fprintf(stderr, "property '%s' doesn't exist, you need to specify " 36253719b08Smrg "its type and format\n", name); 36353719b08Smrg return EXIT_FAILURE; 3645b944e2aSmrg } 3655b944e2aSmrg 36653719b08Smrg data.c = calloc(nelements, sizeof(long)); 36753719b08Smrg 3685b944e2aSmrg for (i = 0; i < nelements; i++) 3695b944e2aSmrg { 3700309d3b3Smrg if (type == XA_INTEGER || type == XA_CARDINAL) { 37153719b08Smrg switch (format) 37253719b08Smrg { 37353719b08Smrg case 8: 37453719b08Smrg data.c[i] = atoi(argv[2 + i]); 37553719b08Smrg break; 37653719b08Smrg case 16: 37753719b08Smrg data.s[i] = atoi(argv[2 + i]); 37853719b08Smrg break; 37953719b08Smrg case 32: 38053719b08Smrg data.l[i] = atoi(argv[2 + i]); 38153719b08Smrg break; 38253719b08Smrg default: 3830309d3b3Smrg fprintf(stderr, "unexpected size for property '%s'", name); 38453719b08Smrg return EXIT_FAILURE; 38553719b08Smrg } 38653719b08Smrg } else if (type == float_atom) { 38753719b08Smrg if (format != 32) { 3880309d3b3Smrg fprintf(stderr, "unexpected format %d for property '%s'\n", 38953719b08Smrg format, name); 39053719b08Smrg return EXIT_FAILURE; 39153719b08Smrg } 39253719b08Smrg *(float *)(data.l + i) = strtod(argv[2 + i], &endptr); 39353719b08Smrg if (endptr == argv[2 + i]) { 3940309d3b3Smrg fprintf(stderr, "argument '%s' could not be parsed\n", argv[2 + i]); 39553719b08Smrg return EXIT_FAILURE; 39653719b08Smrg } 39753719b08Smrg } else if (type == XA_ATOM) { 39853719b08Smrg if (format != 32) { 3990309d3b3Smrg fprintf(stderr, "unexpected format %d for property '%s'\n", 40053719b08Smrg format, name); 40153719b08Smrg return EXIT_FAILURE; 40253719b08Smrg } 40353719b08Smrg data.a[i] = parse_atom(dpy, argv[2 + i]); 40453719b08Smrg } else { 4050309d3b3Smrg fprintf(stderr, "unexpected type for property '%s'\n", name); 40653719b08Smrg return EXIT_FAILURE; 40753719b08Smrg } 4085b944e2aSmrg } 4095b944e2aSmrg 41053719b08Smrg XChangeDeviceProperty(dpy, dev, prop, type, format, PropModeReplace, 41153719b08Smrg data.c, nelements); 41253719b08Smrg free(data.c); 4135b944e2aSmrg XCloseDevice(dpy, dev); 4145b944e2aSmrg return EXIT_SUCCESS; 4155b944e2aSmrg} 4165b944e2aSmrg 41753719b08Smrg#if HAVE_XI2 41853719b08Smrgstatic void 41953719b08Smrgprint_property_xi2(Display *dpy, int deviceid, Atom property) 4205b944e2aSmrg{ 42153719b08Smrg Atom act_type; 42253719b08Smrg char *name; 42353719b08Smrg int act_format; 42453719b08Smrg unsigned long nitems, bytes_after; 42553719b08Smrg unsigned char *data, *ptr; 42653719b08Smrg int j, done = False; 4275b944e2aSmrg 42853719b08Smrg name = XGetAtomName(dpy, property); 42953719b08Smrg printf("\t%s (%ld):\t", name, property); 4305b944e2aSmrg 43153719b08Smrg if (XIGetProperty(dpy, deviceid, property, 0, 1000, False, 43253719b08Smrg AnyPropertyType, &act_type, &act_format, 43353719b08Smrg &nitems, &bytes_after, &data) == Success) 4345b944e2aSmrg { 43553719b08Smrg Atom float_atom = XInternAtom(dpy, "FLOAT", True); 4365b944e2aSmrg 43753719b08Smrg ptr = data; 43853719b08Smrg 43953719b08Smrg if (nitems == 0) 44053719b08Smrg printf("<no items>"); 44153719b08Smrg 44253719b08Smrg for (j = 0; j < nitems; j++) 44353719b08Smrg { 44453719b08Smrg switch(act_type) 44553719b08Smrg { 44653719b08Smrg case XA_INTEGER: 44753719b08Smrg switch(act_format) 44853719b08Smrg { 44953719b08Smrg case 8: 45053719b08Smrg printf("%d", *((int8_t*)ptr)); 45153719b08Smrg break; 45253719b08Smrg case 16: 45353719b08Smrg printf("%d", *((int16_t*)ptr)); 45453719b08Smrg break; 45553719b08Smrg case 32: 45653719b08Smrg printf("%d", *((int32_t*)ptr)); 45753719b08Smrg break; 45853719b08Smrg } 45953719b08Smrg break; 4600309d3b3Smrg case XA_CARDINAL: 4610309d3b3Smrg switch(act_format) 4620309d3b3Smrg { 4630309d3b3Smrg case 8: 4640309d3b3Smrg printf("%u", *((uint8_t*)ptr)); 4650309d3b3Smrg break; 4660309d3b3Smrg case 16: 4670309d3b3Smrg printf("%u", *((uint16_t*)ptr)); 4680309d3b3Smrg break; 4690309d3b3Smrg case 32: 4700309d3b3Smrg printf("%u", *((uint32_t*)ptr)); 4710309d3b3Smrg break; 4720309d3b3Smrg } 4730309d3b3Smrg break; 47453719b08Smrg case XA_STRING: 47553719b08Smrg if (act_format != 8) 47653719b08Smrg { 47753719b08Smrg printf("Unknown string format.\n"); 47853719b08Smrg done = True; 47953719b08Smrg break; 48053719b08Smrg } 48153719b08Smrg printf("\"%s\"", ptr); 48253719b08Smrg j += strlen((char*)ptr); /* The loop's j++ jumps over the 48353719b08Smrg terminating 0 */ 48453719b08Smrg ptr += strlen((char*)ptr); /* ptr += size below jumps over 48553719b08Smrg the terminating 0 */ 48653719b08Smrg break; 48753719b08Smrg case XA_ATOM: 48853719b08Smrg { 489cea37944Smrg Atom a = *(uint32_t*)ptr; 490cea37944Smrg printf("\"%s\" (%ld)", 49153719b08Smrg (a) ? XGetAtomName(dpy, a) : "None", 492cea37944Smrg a); 49353719b08Smrg break; 49453719b08Smrg } 49553719b08Smrg break; 49653719b08Smrg default: 49753719b08Smrg if (float_atom != None && act_type == float_atom) 49853719b08Smrg { 49953719b08Smrg printf("%f", *((float*)ptr)); 50053719b08Smrg break; 50153719b08Smrg } 50253719b08Smrg 50353719b08Smrg printf("\t... of unknown type %s\n", 50453719b08Smrg XGetAtomName(dpy, act_type)); 50553719b08Smrg done = True; 50653719b08Smrg break; 50753719b08Smrg } 50853719b08Smrg 50953719b08Smrg ptr += act_format/8; 51053719b08Smrg 51153719b08Smrg if (done == True) 51253719b08Smrg break; 51353719b08Smrg if (j < nitems - 1) 51453719b08Smrg printf(", "); 51553719b08Smrg } 51653719b08Smrg printf("\n"); 51753719b08Smrg XFree(data); 51853719b08Smrg } else 51953719b08Smrg printf("\tFetch failure\n"); 52053719b08Smrg 52153719b08Smrg} 52253719b08Smrg 52353719b08Smrgstatic int 52453719b08Smrglist_props_xi2(Display *dpy, int argc, char** argv, char* name, char *desc) 52553719b08Smrg{ 52653719b08Smrg XIDeviceInfo *info; 52753719b08Smrg int i; 52853719b08Smrg int nprops; 52953719b08Smrg Atom *props; 53053719b08Smrg 53153719b08Smrg if (argc == 0) 5325b944e2aSmrg { 53353719b08Smrg fprintf(stderr, "Usage: xinput %s %s\n", name, desc); 5345b944e2aSmrg return EXIT_FAILURE; 5355b944e2aSmrg } 5365b944e2aSmrg 53753719b08Smrg for (i = 0; i < argc; i++) 5385b944e2aSmrg { 53953719b08Smrg info = xi2_find_device_info(dpy, argv[i]); 54053719b08Smrg if (!info) 54153719b08Smrg { 54253719b08Smrg fprintf(stderr, "unable to find device %s\n", argv[i]); 54353719b08Smrg continue; 54453719b08Smrg } 5455b944e2aSmrg 54653719b08Smrg props = XIListProperties(dpy, info->deviceid, &nprops); 54753719b08Smrg if (!nprops) 54853719b08Smrg { 54953719b08Smrg printf("Device '%s' does not report any properties.\n", info->name); 5505b944e2aSmrg continue; 55153719b08Smrg } 5525b944e2aSmrg 55353719b08Smrg printf("Device '%s':\n", info->name); 55453719b08Smrg while(nprops--) 55553719b08Smrg { 55653719b08Smrg print_property_xi2(dpy, info->deviceid, props[nprops]); 55753719b08Smrg } 5585b944e2aSmrg 55953719b08Smrg XFree(props); 56053719b08Smrg } 56153719b08Smrg return EXIT_SUCCESS; 5625b944e2aSmrg} 5635b944e2aSmrg 56453719b08Smrgstatic int 56553719b08Smrgdelete_prop_xi2(Display *dpy, int argc, char** argv, char* n, char *desc) 5665b944e2aSmrg{ 56753719b08Smrg XIDeviceInfo *info; 5685b944e2aSmrg char *name; 5695b944e2aSmrg Atom prop; 5705b944e2aSmrg 57153719b08Smrg info = xi2_find_device_info(dpy, argv[0]); 5725b944e2aSmrg if (!info) 5735b944e2aSmrg { 5745b944e2aSmrg fprintf(stderr, "unable to find device %s\n", argv[0]); 5755b944e2aSmrg return EXIT_FAILURE; 5765b944e2aSmrg } 5775b944e2aSmrg 5785b944e2aSmrg name = argv[1]; 5795b944e2aSmrg 58053719b08Smrg prop = parse_atom(dpy, name); 5815b944e2aSmrg 58253719b08Smrg XIDeleteProperty(dpy, info->deviceid, prop); 5835b944e2aSmrg 5845b944e2aSmrg return EXIT_SUCCESS; 5855b944e2aSmrg} 5865b944e2aSmrg 58753719b08Smrgstatic int 58853719b08Smrgdo_set_prop_xi2(Display *dpy, Atom type, int format, int argc, char **argv, char *n, char *desc) 5895b944e2aSmrg{ 59053719b08Smrg XIDeviceInfo *info; 59153719b08Smrg Atom prop; 59253719b08Smrg Atom old_type; 59353719b08Smrg char *name; 59453719b08Smrg int i; 59553719b08Smrg Atom float_atom; 59653719b08Smrg int old_format, nelements = 0; 59753719b08Smrg unsigned long act_nitems, bytes_after; 59853719b08Smrg char *endptr; 59953719b08Smrg union { 60053719b08Smrg unsigned char *c; 60153719b08Smrg int16_t *s; 60253719b08Smrg int32_t *l; 60353719b08Smrg } data; 6045b944e2aSmrg 6055b944e2aSmrg if (argc < 3) 6065b944e2aSmrg { 6075b944e2aSmrg fprintf(stderr, "Usage: xinput %s %s\n", n, desc); 6085b944e2aSmrg return EXIT_FAILURE; 6095b944e2aSmrg } 6105b944e2aSmrg 61153719b08Smrg info = xi2_find_device_info(dpy, argv[0]); 6125b944e2aSmrg if (!info) 6135b944e2aSmrg { 6145b944e2aSmrg fprintf(stderr, "unable to find device %s\n", argv[0]); 6155b944e2aSmrg return EXIT_FAILURE; 6165b944e2aSmrg } 6175b944e2aSmrg 61853719b08Smrg name = argv[1]; 61953719b08Smrg 62053719b08Smrg prop = parse_atom(dpy, name); 62153719b08Smrg 62253719b08Smrg if (prop == None) { 6230309d3b3Smrg fprintf(stderr, "invalid property '%s'\n", name); 6245b944e2aSmrg return EXIT_FAILURE; 6255b944e2aSmrg } 6265b944e2aSmrg 62753719b08Smrg float_atom = XInternAtom(dpy, "FLOAT", False); 6285b944e2aSmrg 62953719b08Smrg nelements = argc - 2; 63053719b08Smrg if (type == None || format == 0) { 63153719b08Smrg if (XIGetProperty(dpy, info->deviceid, prop, 0, 0, False, 63253719b08Smrg AnyPropertyType, &old_type, &old_format, &act_nitems, 63353719b08Smrg &bytes_after, &data.c) != Success) { 6340309d3b3Smrg fprintf(stderr, "failed to get property type and format for '%s'\n", 63553719b08Smrg name); 63653719b08Smrg return EXIT_FAILURE; 63753719b08Smrg } else { 63853719b08Smrg if (type == None) 63953719b08Smrg type = old_type; 64053719b08Smrg if (format == 0) 64153719b08Smrg format = old_format; 64253719b08Smrg } 64353719b08Smrg 64453719b08Smrg XFree(data.c); 6455b944e2aSmrg } 6465b944e2aSmrg 64753719b08Smrg if (type == None) { 6480309d3b3Smrg fprintf(stderr, "property '%s' doesn't exist, you need to specify " 64953719b08Smrg "its type and format\n", name); 65053719b08Smrg return EXIT_FAILURE; 65153719b08Smrg } 65253719b08Smrg 65353719b08Smrg data.c = calloc(nelements, sizeof(int32_t)); 6545b944e2aSmrg 6555b944e2aSmrg for (i = 0; i < nelements; i++) 6565b944e2aSmrg { 6570309d3b3Smrg if (type == XA_INTEGER || type == XA_CARDINAL) { 65853719b08Smrg switch (format) 65953719b08Smrg { 66053719b08Smrg case 8: 66153719b08Smrg data.c[i] = atoi(argv[2 + i]); 66253719b08Smrg break; 66353719b08Smrg case 16: 66453719b08Smrg data.s[i] = atoi(argv[2 + i]); 66553719b08Smrg break; 66653719b08Smrg case 32: 66753719b08Smrg data.l[i] = atoi(argv[2 + i]); 66853719b08Smrg break; 66953719b08Smrg default: 67053719b08Smrg fprintf(stderr, "unexpected size for property %s", name); 67153719b08Smrg return EXIT_FAILURE; 67253719b08Smrg } 67353719b08Smrg } else if (type == float_atom) { 67453719b08Smrg if (format != 32) { 6750309d3b3Smrg fprintf(stderr, "unexpected format %d for property '%s'\n", 67653719b08Smrg format, name); 67753719b08Smrg return EXIT_FAILURE; 67853719b08Smrg } 67953719b08Smrg *(float *)(data.l + i) = strtod(argv[2 + i], &endptr); 68053719b08Smrg if (endptr == argv[2 + i]) { 68153719b08Smrg fprintf(stderr, "argument %s could not be parsed\n", argv[2 + i]); 68253719b08Smrg return EXIT_FAILURE; 6835b944e2aSmrg } 68453719b08Smrg } else if (type == XA_ATOM) { 68553719b08Smrg if (format != 32) { 6860309d3b3Smrg fprintf(stderr, "unexpected format %d for property '%s'\n", 68753719b08Smrg format, name); 68853719b08Smrg return EXIT_FAILURE; 68953719b08Smrg } 69053719b08Smrg data.l[i] = parse_atom(dpy, argv[2 + i]); 69153719b08Smrg } else { 6920309d3b3Smrg fprintf(stderr, "unexpected type for property '%s'\n", name); 69353719b08Smrg return EXIT_FAILURE; 6945b944e2aSmrg } 69553719b08Smrg } 6965b944e2aSmrg 69753719b08Smrg XIChangeProperty(dpy, info->deviceid, prop, type, format, PropModeReplace, 69853719b08Smrg data.c, nelements); 69953719b08Smrg free(data.c); 70053719b08Smrg return EXIT_SUCCESS; 70153719b08Smrg} 70253719b08Smrg#endif 70353719b08Smrg 70453719b08Smrgint list_props(Display *display, int argc, char *argv[], char *name, 70553719b08Smrg char *desc) 70653719b08Smrg{ 70753719b08Smrg#ifdef HAVE_XI2 70853719b08Smrg if (xinput_version(display) == XI_2_Major) 70953719b08Smrg return list_props_xi2(display, argc, argv, name, desc); 71053719b08Smrg#endif 71153719b08Smrg return list_props_xi1(display, argc, argv, name, desc); 71253719b08Smrg 71353719b08Smrg} 71453719b08Smrg 71553719b08Smrgint delete_prop(Display *display, int argc, char *argv[], char *name, 71653719b08Smrg char *desc) 71753719b08Smrg{ 71853719b08Smrg#ifdef HAVE_XI2 71953719b08Smrg if (xinput_version(display) == XI_2_Major) 72053719b08Smrg return delete_prop_xi2(display, argc, argv, name, desc); 72153719b08Smrg#endif 72253719b08Smrg return delete_prop_xi1(display, argc, argv, name, desc); 72353719b08Smrg 72453719b08Smrg} 72553719b08Smrg 72653719b08Smrgstatic int 72753719b08Smrgdo_set_prop(Display *display, Atom type, int format, int argc, char *argv[], char *name, char *desc) 72853719b08Smrg{ 72953719b08Smrg#ifdef HAVE_XI2 73053719b08Smrg if (xinput_version(display) == XI_2_Major) 73153719b08Smrg return do_set_prop_xi2(display, type, format, argc, argv, name, desc); 73253719b08Smrg#endif 73353719b08Smrg return do_set_prop_xi1(display, type, format, argc, argv, name, desc); 73453719b08Smrg} 73553719b08Smrg 73653719b08Smrgint 73753719b08Smrgset_atom_prop(Display *dpy, int argc, char** argv, char* n, char *desc) 73853719b08Smrg{ 73953719b08Smrg return do_set_prop(dpy, XA_ATOM, 32, argc, argv, n, desc); 74053719b08Smrg} 74153719b08Smrg 74253719b08Smrgint 74353719b08Smrgset_int_prop(Display *dpy, int argc, char** argv, char* n, char *desc) 74453719b08Smrg{ 74553719b08Smrg int i; 74653719b08Smrg int format; 74753719b08Smrg 74853719b08Smrg if (argc < 3) 74953719b08Smrg { 75053719b08Smrg fprintf(stderr, "Usage: xinput %s %s\n", n, desc); 75153719b08Smrg return EXIT_FAILURE; 7525b944e2aSmrg } 7535b944e2aSmrg 75453719b08Smrg format = atoi(argv[2]); 75553719b08Smrg if (format != 8 && format != 16 && format != 32) 75653719b08Smrg { 75753719b08Smrg fprintf(stderr, "Invalid format %d\n", format); 75853719b08Smrg return EXIT_FAILURE; 75953719b08Smrg } 7605b944e2aSmrg 76153719b08Smrg for (i = 3; i < argc; i++) 76253719b08Smrg argv[i - 1] = argv[i]; 76353719b08Smrg 76453719b08Smrg return do_set_prop(dpy, XA_INTEGER, format, argc - 1, argv, n, desc); 7655b944e2aSmrg} 7665b944e2aSmrg 76753719b08Smrgint 76853719b08Smrgset_float_prop(Display *dpy, int argc, char** argv, char* n, char *desc) 76953719b08Smrg{ 77053719b08Smrg Atom float_atom = XInternAtom(dpy, "FLOAT", False); 77153719b08Smrg 77253719b08Smrg if (sizeof(float) != 4) 77353719b08Smrg { 77453719b08Smrg fprintf(stderr, "sane FP required\n"); 77553719b08Smrg return EXIT_FAILURE; 77653719b08Smrg } 77753719b08Smrg 77853719b08Smrg return do_set_prop(dpy, float_atom, 32, argc, argv, n, desc); 77953719b08Smrg} 7805b944e2aSmrg 78153719b08Smrgint set_prop(Display *display, int argc, char *argv[], char *name, 78253719b08Smrg char *desc) 78353719b08Smrg{ 78453719b08Smrg Atom type = None; 78553719b08Smrg int format = 0; 78653719b08Smrg int i = 0, j; 78753719b08Smrg 78853719b08Smrg while (i < argc) { 78953719b08Smrg char *option = strchr(argv[i], '='); 79053719b08Smrg /* skip non-option arguments */ 79153719b08Smrg if (strncmp(argv[i], "--", 2) || !option) { 79253719b08Smrg i++; 79353719b08Smrg continue; 79453719b08Smrg } 79553719b08Smrg 79653719b08Smrg if (!strncmp(argv[i], "--type=", strlen("--type="))) { 79753719b08Smrg if (!strcmp(option + 1, "int")) { 79853719b08Smrg type = XA_INTEGER; 79953719b08Smrg } else if (!strcmp(option + 1, "float")) { 80053719b08Smrg type = XInternAtom(display, "FLOAT", False); 80153719b08Smrg format = 32; 80253719b08Smrg } else if (!strcmp(option + 1, "atom")) { 80353719b08Smrg type = XA_ATOM; 80453719b08Smrg format = 32; 80553719b08Smrg } else { 80653719b08Smrg fprintf(stderr, "unknown property type %s\n", option + 1); 80753719b08Smrg return EXIT_FAILURE; 80853719b08Smrg } 80953719b08Smrg } else if (!strncmp(argv[i], "--format=", strlen("--format="))) { 81053719b08Smrg format = atoi(option + 1); 81153719b08Smrg if (format != 8 && format != 16 && format != 32) { 8120309d3b3Smrg fprintf(stderr, "invalid property format '%s'\n", option + 1); 81353719b08Smrg return EXIT_FAILURE; 81453719b08Smrg } 81553719b08Smrg } else { 8160309d3b3Smrg fprintf(stderr, "invalid option '%s'\n", argv[i]); 81753719b08Smrg return EXIT_FAILURE; 81853719b08Smrg } 81953719b08Smrg 82053719b08Smrg for (j = i; j + 1 < argc; j++) 82153719b08Smrg argv[j] = argv[j + 1]; 82253719b08Smrg argc--; 82353719b08Smrg } 82453719b08Smrg 82553719b08Smrg return do_set_prop(display, type, format, argc, argv, name, desc); 82653719b08Smrg} 8270309d3b3Smrg 8280309d3b3Smrgint disable(Display *display, int argc, char *argv[], char *name, char *desc) 8290309d3b3Smrg{ 8300309d3b3Smrg char *new_argv[3] = { argv[0], "Device Enabled", "0" }; 8310309d3b3Smrg return set_prop(display, 3, new_argv, name, desc); 8320309d3b3Smrg} 8330309d3b3Smrg 8340309d3b3Smrgint enable(Display *display, int argc, char *argv[], char *name, char *desc) 8350309d3b3Smrg{ 8360309d3b3Smrg char *new_argv[3] = { argv[0], "Device Enabled", "1" }; 8370309d3b3Smrg return set_prop(display, 3, new_argv, name, desc); 8380309d3b3Smrg} 839