property.c revision 5b944e2a
15b944e2aSmrg/* 25b944e2aSmrg * Copyright 2007 Peter Hutterer 35b944e2aSmrg * 45b944e2aSmrg * Permission to use, copy, modify, distribute, and sell this software and its 55b944e2aSmrg * documentation for any purpose is hereby granted without fee, provided that 65b944e2aSmrg * the above copyright notice appear in all copies and that both that 75b944e2aSmrg * copyright notice and this permission notice appear in supporting 85b944e2aSmrg * documentation. 95b944e2aSmrg * 105b944e2aSmrg * The above copyright notice and this permission notice shall be included 115b944e2aSmrg * in all copies or substantial portions of the Software. 125b944e2aSmrg * 135b944e2aSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 145b944e2aSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 155b944e2aSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 165b944e2aSmrg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR 175b944e2aSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 185b944e2aSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 195b944e2aSmrg * OTHER DEALINGS IN THE SOFTWARE. 205b944e2aSmrg * 215b944e2aSmrg * Except as contained in this notice, the name of the author shall 225b944e2aSmrg * not be used in advertising or otherwise to promote the sale, use or 235b944e2aSmrg * other dealings in this Software without prior written authorization 245b944e2aSmrg * from the author. 255b944e2aSmrg * 265b944e2aSmrg */ 275b944e2aSmrg 285b944e2aSmrg#include <ctype.h> 295b944e2aSmrg#include <string.h> 305b944e2aSmrg#include <stdlib.h> 315b944e2aSmrg#include <stdint.h> 325b944e2aSmrg#include <X11/Xatom.h> 335b944e2aSmrg#include <X11/extensions/XIproto.h> 345b944e2aSmrg 355b944e2aSmrg#include "xinput.h" 365b944e2aSmrg 375b944e2aSmrgstatic void 385b944e2aSmrgprint_property(Display *dpy, XDevice* dev, Atom property) 395b944e2aSmrg{ 405b944e2aSmrg Atom act_type; 415b944e2aSmrg char *name; 425b944e2aSmrg int act_format; 435b944e2aSmrg unsigned long nitems, bytes_after; 445b944e2aSmrg unsigned char *data, *ptr; 455b944e2aSmrg int j; 465b944e2aSmrg 475b944e2aSmrg name = XGetAtomName(dpy, property); 485b944e2aSmrg printf("\t%s (%ld):\t", name, property); 495b944e2aSmrg 505b944e2aSmrg if (XGetDeviceProperty(dpy, dev, property, 0, 1000, False, 515b944e2aSmrg AnyPropertyType, &act_type, &act_format, 525b944e2aSmrg &nitems, &bytes_after, &data) == Success) 535b944e2aSmrg { 545b944e2aSmrg int float_atom = XInternAtom(dpy, "FLOAT", False); 555b944e2aSmrg 565b944e2aSmrg ptr = data; 575b944e2aSmrg printf("\t"); 585b944e2aSmrg 595b944e2aSmrg for (j = 0; j < nitems; j++) 605b944e2aSmrg { 615b944e2aSmrg switch(act_type) 625b944e2aSmrg { 635b944e2aSmrg case XA_INTEGER: 645b944e2aSmrg switch(act_format) 655b944e2aSmrg { 665b944e2aSmrg case 8: 675b944e2aSmrg printf("%d", *((int8_t*)ptr)); 685b944e2aSmrg break; 695b944e2aSmrg case 16: 705b944e2aSmrg printf("%d", *((int16_t*)ptr)); 715b944e2aSmrg break; 725b944e2aSmrg case 32: 735b944e2aSmrg printf("%d", *((int32_t*)ptr)); 745b944e2aSmrg break; 755b944e2aSmrg } 765b944e2aSmrg break; 775b944e2aSmrg case XA_STRING: 785b944e2aSmrg printf("\t%s", ptr); 795b944e2aSmrg break; 805b944e2aSmrg case XA_ATOM: 815b944e2aSmrg printf("\t%s", XGetAtomName(dpy, *(Atom*)ptr)); 825b944e2aSmrg break; 835b944e2aSmrg default: 845b944e2aSmrg if (float_atom != None && act_type == float_atom) 855b944e2aSmrg { 865b944e2aSmrg printf("\t%f\n", *((float*)ptr)); 875b944e2aSmrg break; 885b944e2aSmrg } 895b944e2aSmrg 905b944e2aSmrg printf("\t\t... of unknown type %s\n", 915b944e2aSmrg XGetAtomName(dpy, act_type)); 925b944e2aSmrg break; 935b944e2aSmrg } 945b944e2aSmrg 955b944e2aSmrg ptr += act_format/8; 965b944e2aSmrg 975b944e2aSmrg if (j < nitems - 1) 985b944e2aSmrg printf(", "); 995b944e2aSmrg if (act_type == XA_STRING) 1005b944e2aSmrg break; 1015b944e2aSmrg } 1025b944e2aSmrg printf("\n"); 1035b944e2aSmrg XFree(data); 1045b944e2aSmrg } else 1055b944e2aSmrg printf("\tFetch failure\n"); 1065b944e2aSmrg 1075b944e2aSmrg} 1085b944e2aSmrg 1095b944e2aSmrgint list_props(Display *dpy, int argc, char** argv, char* name, char *desc) 1105b944e2aSmrg{ 1115b944e2aSmrg XDeviceInfo *info; 1125b944e2aSmrg XDevice *dev; 1135b944e2aSmrg int i; 1145b944e2aSmrg int nprops; 1155b944e2aSmrg Atom *props; 1165b944e2aSmrg 1175b944e2aSmrg if (argc == 0) 1185b944e2aSmrg { 1195b944e2aSmrg fprintf(stderr, "Usage: xinput %s %s\n", name, desc); 1205b944e2aSmrg return EXIT_FAILURE; 1215b944e2aSmrg } 1225b944e2aSmrg 1235b944e2aSmrg for (i = 0; i < argc; i++) 1245b944e2aSmrg { 1255b944e2aSmrg info = find_device_info(dpy, argv[i], False); 1265b944e2aSmrg if (!info) 1275b944e2aSmrg { 1285b944e2aSmrg fprintf(stderr, "unable to find device %s\n", argv[i]); 1295b944e2aSmrg continue; 1305b944e2aSmrg } 1315b944e2aSmrg 1325b944e2aSmrg dev = XOpenDevice(dpy, info->id); 1335b944e2aSmrg if (!dev) 1345b944e2aSmrg { 1355b944e2aSmrg fprintf(stderr, "unable to open device '%s'\n", info->name); 1365b944e2aSmrg continue; 1375b944e2aSmrg } 1385b944e2aSmrg 1395b944e2aSmrg props = XListDeviceProperties(dpy, dev, &nprops); 1405b944e2aSmrg if (!nprops) 1415b944e2aSmrg { 1425b944e2aSmrg printf("Device '%s' does not report any properties.\n", info->name); 1435b944e2aSmrg continue; 1445b944e2aSmrg } 1455b944e2aSmrg 1465b944e2aSmrg printf("Device '%s':\n", info->name); 1475b944e2aSmrg while(nprops--) 1485b944e2aSmrg { 1495b944e2aSmrg print_property(dpy, dev, props[nprops]); 1505b944e2aSmrg } 1515b944e2aSmrg 1525b944e2aSmrg XFree(props); 1535b944e2aSmrg XCloseDevice(dpy, dev); 1545b944e2aSmrg } 1555b944e2aSmrg return EXIT_SUCCESS; 1565b944e2aSmrg} 1575b944e2aSmrg 1585b944e2aSmrgint 1595b944e2aSmrgset_int_prop(Display *dpy, int argc, char** argv, char* n, char *desc) 1605b944e2aSmrg{ 1615b944e2aSmrg XDeviceInfo *info; 1625b944e2aSmrg XDevice *dev; 1635b944e2aSmrg Atom prop; 1645b944e2aSmrg char *name; 1655b944e2aSmrg int i; 1665b944e2aSmrg Bool is_atom = True; 1675b944e2aSmrg char *data; 1685b944e2aSmrg int format, nelements = 0; 1695b944e2aSmrg 1705b944e2aSmrg if (argc < 3) 1715b944e2aSmrg { 1725b944e2aSmrg fprintf(stderr, "Usage: xinput %s %s\n", n, desc); 1735b944e2aSmrg return EXIT_FAILURE; 1745b944e2aSmrg } 1755b944e2aSmrg 1765b944e2aSmrg info = find_device_info(dpy, argv[0], False); 1775b944e2aSmrg if (!info) 1785b944e2aSmrg { 1795b944e2aSmrg fprintf(stderr, "unable to find device %s\n", argv[0]); 1805b944e2aSmrg return EXIT_FAILURE; 1815b944e2aSmrg } 1825b944e2aSmrg 1835b944e2aSmrg dev = XOpenDevice(dpy, info->id); 1845b944e2aSmrg if (!dev) 1855b944e2aSmrg { 1865b944e2aSmrg fprintf(stderr, "unable to open device %s\n", argv[0]); 1875b944e2aSmrg return EXIT_FAILURE; 1885b944e2aSmrg } 1895b944e2aSmrg 1905b944e2aSmrg name = argv[1]; 1915b944e2aSmrg 1925b944e2aSmrg for(i = 0; i < strlen(name); i++) { 1935b944e2aSmrg if (!isdigit(name[i])) { 1945b944e2aSmrg is_atom = False; 1955b944e2aSmrg break; 1965b944e2aSmrg } 1975b944e2aSmrg } 1985b944e2aSmrg 1995b944e2aSmrg if (!is_atom) 2005b944e2aSmrg prop = XInternAtom(dpy, name, False); 2015b944e2aSmrg else 2025b944e2aSmrg prop = atoi(name); 2035b944e2aSmrg 2045b944e2aSmrg nelements = argc - 3; 2055b944e2aSmrg format = atoi(argv[2]); 2065b944e2aSmrg if (format != 8 && format != 16 && format != 32) 2075b944e2aSmrg { 2085b944e2aSmrg fprintf(stderr, "Invalid format %d\n", format); 2095b944e2aSmrg return EXIT_FAILURE; 2105b944e2aSmrg } 2115b944e2aSmrg 2125b944e2aSmrg data = calloc(nelements, format/8); 2135b944e2aSmrg for (i = 0; i < nelements; i++) 2145b944e2aSmrg { 2155b944e2aSmrg switch(format) 2165b944e2aSmrg { 2175b944e2aSmrg case 8: 2185b944e2aSmrg *(((int8_t*)data) + i) = atoi(argv[3 + i]); 2195b944e2aSmrg break; 2205b944e2aSmrg case 16: 2215b944e2aSmrg *(((int16_t*)data) + i) = atoi(argv[3 + i]); 2225b944e2aSmrg break; 2235b944e2aSmrg case 32: 2245b944e2aSmrg *(((int32_t*)data) + i) = atoi(argv[3 + i]); 2255b944e2aSmrg break; 2265b944e2aSmrg } 2275b944e2aSmrg } 2285b944e2aSmrg 2295b944e2aSmrg XChangeDeviceProperty(dpy, dev, prop, XA_INTEGER, format, PropModeReplace, 2305b944e2aSmrg (unsigned char*)data, nelements); 2315b944e2aSmrg 2325b944e2aSmrg free(data); 2335b944e2aSmrg XCloseDevice(dpy, dev); 2345b944e2aSmrg return EXIT_SUCCESS; 2355b944e2aSmrg} 2365b944e2aSmrg 2375b944e2aSmrgint 2385b944e2aSmrgset_float_prop(Display *dpy, int argc, char** argv, char* n, char *desc) 2395b944e2aSmrg{ 2405b944e2aSmrg XDeviceInfo *info; 2415b944e2aSmrg XDevice *dev; 2425b944e2aSmrg Atom prop, float_atom; 2435b944e2aSmrg char *name; 2445b944e2aSmrg int i; 2455b944e2aSmrg Bool is_atom = True; 2465b944e2aSmrg float *data; 2475b944e2aSmrg int nelements = 0; 2485b944e2aSmrg char* endptr; 2495b944e2aSmrg 2505b944e2aSmrg if (argc < 2) 2515b944e2aSmrg { 2525b944e2aSmrg fprintf(stderr, "Usage: xinput %s %s\n", n, desc); 2535b944e2aSmrg return EXIT_FAILURE; 2545b944e2aSmrg } 2555b944e2aSmrg 2565b944e2aSmrg info = find_device_info(dpy, argv[0], False); 2575b944e2aSmrg if (!info) 2585b944e2aSmrg { 2595b944e2aSmrg fprintf(stderr, "unable to find device %s\n", argv[0]); 2605b944e2aSmrg return EXIT_FAILURE; 2615b944e2aSmrg } 2625b944e2aSmrg 2635b944e2aSmrg dev = XOpenDevice(dpy, info->id); 2645b944e2aSmrg if (!dev) 2655b944e2aSmrg { 2665b944e2aSmrg fprintf(stderr, "unable to open device %s\n", argv[0]); 2675b944e2aSmrg return EXIT_FAILURE; 2685b944e2aSmrg } 2695b944e2aSmrg 2705b944e2aSmrg name = argv[1]; 2715b944e2aSmrg 2725b944e2aSmrg for(i = 0; i < strlen(name); i++) { 2735b944e2aSmrg if (!isdigit(name[i])) { 2745b944e2aSmrg is_atom = False; 2755b944e2aSmrg break; 2765b944e2aSmrg } 2775b944e2aSmrg } 2785b944e2aSmrg 2795b944e2aSmrg if (!is_atom) 2805b944e2aSmrg prop = XInternAtom(dpy, name, False); 2815b944e2aSmrg else 2825b944e2aSmrg prop = atoi(name); 2835b944e2aSmrg 2845b944e2aSmrg nelements = argc - 2; 2855b944e2aSmrg 2865b944e2aSmrg float_atom = XInternAtom(dpy, "FLOAT", False); 2875b944e2aSmrg 2885b944e2aSmrg if (float_atom == (Atom)0) 2895b944e2aSmrg { 2905b944e2aSmrg fprintf(stderr, "no FLOAT atom present in server\n"); 2915b944e2aSmrg return EXIT_FAILURE; 2925b944e2aSmrg } 2935b944e2aSmrg 2945b944e2aSmrg if (sizeof(float) != 4) 2955b944e2aSmrg { 2965b944e2aSmrg fprintf(stderr, "sane FP required\n"); 2975b944e2aSmrg return EXIT_FAILURE; 2985b944e2aSmrg } 2995b944e2aSmrg 3005b944e2aSmrg data = calloc(nelements, 4); 3015b944e2aSmrg for (i = 0; i < nelements; i++) 3025b944e2aSmrg { 3035b944e2aSmrg *(data + i) = strtod(argv[2 + i], &endptr); 3045b944e2aSmrg if(endptr == argv[2 + i]){ 3055b944e2aSmrg fprintf(stderr, "argument %s could not be parsed\n", argv[2 + i]); 3065b944e2aSmrg return EXIT_FAILURE; 3075b944e2aSmrg } 3085b944e2aSmrg } 3095b944e2aSmrg 3105b944e2aSmrg XChangeDeviceProperty(dpy, dev, prop, float_atom, 32, PropModeReplace, 3115b944e2aSmrg (unsigned char*)data, nelements); 3125b944e2aSmrg 3135b944e2aSmrg free(data); 3145b944e2aSmrg XCloseDevice(dpy, dev); 3155b944e2aSmrg return EXIT_SUCCESS; 3165b944e2aSmrg} 3175b944e2aSmrg 3185b944e2aSmrg 3195b944e2aSmrgint watch_props(Display *dpy, int argc, char** argv, char* n, char *desc) 3205b944e2aSmrg{ 3215b944e2aSmrg XDevice *dev; 3225b944e2aSmrg XDeviceInfo *info; 3235b944e2aSmrg XEvent ev; 3245b944e2aSmrg XDevicePropertyNotifyEvent *dpev; 3255b944e2aSmrg char *name; 3265b944e2aSmrg int type_prop; 3275b944e2aSmrg XEventClass cls_prop; 3285b944e2aSmrg 3295b944e2aSmrg if (list_props(dpy, argc, argv, n, desc) != EXIT_SUCCESS) 3305b944e2aSmrg return EXIT_FAILURE; 3315b944e2aSmrg 3325b944e2aSmrg info = find_device_info(dpy, argv[0], False); 3335b944e2aSmrg if (!info) 3345b944e2aSmrg { 3355b944e2aSmrg fprintf(stderr, "unable to find device %s\n", argv[0]); 3365b944e2aSmrg return EXIT_FAILURE; 3375b944e2aSmrg } 3385b944e2aSmrg 3395b944e2aSmrg dev = XOpenDevice(dpy, info->id); 3405b944e2aSmrg if (!dev) 3415b944e2aSmrg { 3425b944e2aSmrg fprintf(stderr, "unable to open device '%s'\n", info->name); 3435b944e2aSmrg return EXIT_FAILURE; 3445b944e2aSmrg } 3455b944e2aSmrg 3465b944e2aSmrg DevicePropertyNotify(dev, type_prop, cls_prop); 3475b944e2aSmrg XSelectExtensionEvent(dpy, DefaultRootWindow(dpy), &cls_prop, 1); 3485b944e2aSmrg 3495b944e2aSmrg while(1) 3505b944e2aSmrg { 3515b944e2aSmrg XNextEvent(dpy, &ev); 3525b944e2aSmrg 3535b944e2aSmrg dpev = (XDevicePropertyNotifyEvent*)&ev; 3545b944e2aSmrg if (dpev->type != type_prop) 3555b944e2aSmrg continue; 3565b944e2aSmrg 3575b944e2aSmrg name = XGetAtomName(dpy, dpev->atom); 3585b944e2aSmrg printf("Property '%s' changed.\n", name); 3595b944e2aSmrg print_property(dpy, dev, dpev->atom); 3605b944e2aSmrg } 3615b944e2aSmrg 3625b944e2aSmrg XCloseDevice(dpy, dev); 3635b944e2aSmrg} 3645b944e2aSmrg 3655b944e2aSmrgint delete_prop(Display *dpy, int argc, char** argv, char* n, char *desc) 3665b944e2aSmrg{ 3675b944e2aSmrg XDevice *dev; 3685b944e2aSmrg XDeviceInfo *info; 3695b944e2aSmrg char *name; 3705b944e2aSmrg int i; 3715b944e2aSmrg Bool is_atom = True; 3725b944e2aSmrg Atom prop; 3735b944e2aSmrg 3745b944e2aSmrg info = find_device_info(dpy, argv[0], False); 3755b944e2aSmrg if (!info) 3765b944e2aSmrg { 3775b944e2aSmrg fprintf(stderr, "unable to find device %s\n", argv[0]); 3785b944e2aSmrg return EXIT_FAILURE; 3795b944e2aSmrg } 3805b944e2aSmrg 3815b944e2aSmrg dev = XOpenDevice(dpy, info->id); 3825b944e2aSmrg if (!dev) 3835b944e2aSmrg { 3845b944e2aSmrg fprintf(stderr, "unable to open device '%s'\n", info->name); 3855b944e2aSmrg return EXIT_FAILURE; 3865b944e2aSmrg } 3875b944e2aSmrg 3885b944e2aSmrg name = argv[1]; 3895b944e2aSmrg 3905b944e2aSmrg for(i = 0; i < strlen(name); i++) { 3915b944e2aSmrg if (!isdigit(name[i])) { 3925b944e2aSmrg is_atom = False; 3935b944e2aSmrg break; 3945b944e2aSmrg } 3955b944e2aSmrg } 3965b944e2aSmrg 3975b944e2aSmrg if (!is_atom) 3985b944e2aSmrg prop = XInternAtom(dpy, name, False); 3995b944e2aSmrg else 4005b944e2aSmrg prop = atoi(name); 4015b944e2aSmrg 4025b944e2aSmrg XDeleteDeviceProperty(dpy, dev, prop); 4035b944e2aSmrg 4045b944e2aSmrg XCloseDevice(dpy, dev); 4055b944e2aSmrg return EXIT_SUCCESS; 4065b944e2aSmrg} 4075b944e2aSmrg 4085b944e2aSmrgint 4095b944e2aSmrgset_atom_prop(Display *dpy, int argc, char** argv, char* n, char *desc) 4105b944e2aSmrg{ 4115b944e2aSmrg XDeviceInfo *info; 4125b944e2aSmrg XDevice *dev; 4135b944e2aSmrg Atom prop; 4145b944e2aSmrg char *name; 4155b944e2aSmrg int i, j; 4165b944e2aSmrg Bool is_atom = True; 4175b944e2aSmrg Atom *data; 4185b944e2aSmrg int nelements = 0; 4195b944e2aSmrg 4205b944e2aSmrg if (argc < 3) 4215b944e2aSmrg { 4225b944e2aSmrg fprintf(stderr, "Usage: xinput %s %s\n", n, desc); 4235b944e2aSmrg return EXIT_FAILURE; 4245b944e2aSmrg } 4255b944e2aSmrg 4265b944e2aSmrg info = find_device_info(dpy, argv[0], False); 4275b944e2aSmrg if (!info) 4285b944e2aSmrg { 4295b944e2aSmrg fprintf(stderr, "unable to find device %s\n", argv[0]); 4305b944e2aSmrg return EXIT_FAILURE; 4315b944e2aSmrg } 4325b944e2aSmrg 4335b944e2aSmrg dev = XOpenDevice(dpy, info->id); 4345b944e2aSmrg if (!dev) 4355b944e2aSmrg { 4365b944e2aSmrg fprintf(stderr, "unable to open device %s\n", argv[0]); 4375b944e2aSmrg return EXIT_FAILURE; 4385b944e2aSmrg } 4395b944e2aSmrg 4405b944e2aSmrg name = argv[1]; 4415b944e2aSmrg 4425b944e2aSmrg for(i = 0; i < strlen(name); i++) { 4435b944e2aSmrg if (!isdigit(name[i])) { 4445b944e2aSmrg is_atom = False; 4455b944e2aSmrg break; 4465b944e2aSmrg } 4475b944e2aSmrg } 4485b944e2aSmrg 4495b944e2aSmrg if (!is_atom) 4505b944e2aSmrg prop = XInternAtom(dpy, name, False); 4515b944e2aSmrg else 4525b944e2aSmrg prop = atoi(name); 4535b944e2aSmrg 4545b944e2aSmrg nelements = argc - 2; 4555b944e2aSmrg data = calloc(nelements, sizeof(Atom)); 4565b944e2aSmrg for (i = 0; i < nelements; i++) 4575b944e2aSmrg { 4585b944e2aSmrg is_atom = True; 4595b944e2aSmrg name = argv[2 + i]; 4605b944e2aSmrg for(j = 0; j < strlen(name); j++) { 4615b944e2aSmrg if (!isdigit(name[j])) { 4625b944e2aSmrg is_atom = False; 4635b944e2aSmrg break; 4645b944e2aSmrg } 4655b944e2aSmrg } 4665b944e2aSmrg 4675b944e2aSmrg if (!is_atom) 4685b944e2aSmrg data[i] = XInternAtom(dpy, name, False); 4695b944e2aSmrg else 4705b944e2aSmrg { 4715b944e2aSmrg data[i] = atoi(name); 4725b944e2aSmrg XFree(XGetAtomName(dpy, data[i])); 4735b944e2aSmrg } 4745b944e2aSmrg } 4755b944e2aSmrg 4765b944e2aSmrg XChangeDeviceProperty(dpy, dev, prop, XA_ATOM, 32, PropModeReplace, 4775b944e2aSmrg (unsigned char*)data, nelements); 4785b944e2aSmrg 4795b944e2aSmrg free(data); 4805b944e2aSmrg XCloseDevice(dpy, dev); 4815b944e2aSmrg return EXIT_SUCCESS; 4825b944e2aSmrg} 4835b944e2aSmrg 4845b944e2aSmrg 485