property.c revision 5b944e2a
1/* 2 * Copyright 2007 Peter Hutterer 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that 7 * copyright notice and this permission notice appear in supporting 8 * documentation. 9 * 10 * The above copyright notice and this permission notice shall be included 11 * in all copies or substantial portions of the Software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 * OTHER DEALINGS IN THE SOFTWARE. 20 * 21 * Except as contained in this notice, the name of the author shall 22 * not be used in advertising or otherwise to promote the sale, use or 23 * other dealings in this Software without prior written authorization 24 * from the author. 25 * 26 */ 27 28#include <ctype.h> 29#include <string.h> 30#include <stdlib.h> 31#include <stdint.h> 32#include <X11/Xatom.h> 33#include <X11/extensions/XIproto.h> 34 35#include "xinput.h" 36 37static void 38print_property(Display *dpy, XDevice* dev, Atom property) 39{ 40 Atom act_type; 41 char *name; 42 int act_format; 43 unsigned long nitems, bytes_after; 44 unsigned char *data, *ptr; 45 int j; 46 47 name = XGetAtomName(dpy, property); 48 printf("\t%s (%ld):\t", name, property); 49 50 if (XGetDeviceProperty(dpy, dev, property, 0, 1000, False, 51 AnyPropertyType, &act_type, &act_format, 52 &nitems, &bytes_after, &data) == Success) 53 { 54 int float_atom = XInternAtom(dpy, "FLOAT", False); 55 56 ptr = data; 57 printf("\t"); 58 59 for (j = 0; j < nitems; j++) 60 { 61 switch(act_type) 62 { 63 case XA_INTEGER: 64 switch(act_format) 65 { 66 case 8: 67 printf("%d", *((int8_t*)ptr)); 68 break; 69 case 16: 70 printf("%d", *((int16_t*)ptr)); 71 break; 72 case 32: 73 printf("%d", *((int32_t*)ptr)); 74 break; 75 } 76 break; 77 case XA_STRING: 78 printf("\t%s", ptr); 79 break; 80 case XA_ATOM: 81 printf("\t%s", XGetAtomName(dpy, *(Atom*)ptr)); 82 break; 83 default: 84 if (float_atom != None && act_type == float_atom) 85 { 86 printf("\t%f\n", *((float*)ptr)); 87 break; 88 } 89 90 printf("\t\t... of unknown type %s\n", 91 XGetAtomName(dpy, act_type)); 92 break; 93 } 94 95 ptr += act_format/8; 96 97 if (j < nitems - 1) 98 printf(", "); 99 if (act_type == XA_STRING) 100 break; 101 } 102 printf("\n"); 103 XFree(data); 104 } else 105 printf("\tFetch failure\n"); 106 107} 108 109int list_props(Display *dpy, int argc, char** argv, char* name, char *desc) 110{ 111 XDeviceInfo *info; 112 XDevice *dev; 113 int i; 114 int nprops; 115 Atom *props; 116 117 if (argc == 0) 118 { 119 fprintf(stderr, "Usage: xinput %s %s\n", name, desc); 120 return EXIT_FAILURE; 121 } 122 123 for (i = 0; i < argc; i++) 124 { 125 info = find_device_info(dpy, argv[i], False); 126 if (!info) 127 { 128 fprintf(stderr, "unable to find device %s\n", argv[i]); 129 continue; 130 } 131 132 dev = XOpenDevice(dpy, info->id); 133 if (!dev) 134 { 135 fprintf(stderr, "unable to open device '%s'\n", info->name); 136 continue; 137 } 138 139 props = XListDeviceProperties(dpy, dev, &nprops); 140 if (!nprops) 141 { 142 printf("Device '%s' does not report any properties.\n", info->name); 143 continue; 144 } 145 146 printf("Device '%s':\n", info->name); 147 while(nprops--) 148 { 149 print_property(dpy, dev, props[nprops]); 150 } 151 152 XFree(props); 153 XCloseDevice(dpy, dev); 154 } 155 return EXIT_SUCCESS; 156} 157 158int 159set_int_prop(Display *dpy, int argc, char** argv, char* n, char *desc) 160{ 161 XDeviceInfo *info; 162 XDevice *dev; 163 Atom prop; 164 char *name; 165 int i; 166 Bool is_atom = True; 167 char *data; 168 int format, nelements = 0; 169 170 if (argc < 3) 171 { 172 fprintf(stderr, "Usage: xinput %s %s\n", n, desc); 173 return EXIT_FAILURE; 174 } 175 176 info = find_device_info(dpy, argv[0], False); 177 if (!info) 178 { 179 fprintf(stderr, "unable to find device %s\n", argv[0]); 180 return EXIT_FAILURE; 181 } 182 183 dev = XOpenDevice(dpy, info->id); 184 if (!dev) 185 { 186 fprintf(stderr, "unable to open device %s\n", argv[0]); 187 return EXIT_FAILURE; 188 } 189 190 name = argv[1]; 191 192 for(i = 0; i < strlen(name); i++) { 193 if (!isdigit(name[i])) { 194 is_atom = False; 195 break; 196 } 197 } 198 199 if (!is_atom) 200 prop = XInternAtom(dpy, name, False); 201 else 202 prop = atoi(name); 203 204 nelements = argc - 3; 205 format = atoi(argv[2]); 206 if (format != 8 && format != 16 && format != 32) 207 { 208 fprintf(stderr, "Invalid format %d\n", format); 209 return EXIT_FAILURE; 210 } 211 212 data = calloc(nelements, format/8); 213 for (i = 0; i < nelements; i++) 214 { 215 switch(format) 216 { 217 case 8: 218 *(((int8_t*)data) + i) = atoi(argv[3 + i]); 219 break; 220 case 16: 221 *(((int16_t*)data) + i) = atoi(argv[3 + i]); 222 break; 223 case 32: 224 *(((int32_t*)data) + i) = atoi(argv[3 + i]); 225 break; 226 } 227 } 228 229 XChangeDeviceProperty(dpy, dev, prop, XA_INTEGER, format, PropModeReplace, 230 (unsigned char*)data, nelements); 231 232 free(data); 233 XCloseDevice(dpy, dev); 234 return EXIT_SUCCESS; 235} 236 237int 238set_float_prop(Display *dpy, int argc, char** argv, char* n, char *desc) 239{ 240 XDeviceInfo *info; 241 XDevice *dev; 242 Atom prop, float_atom; 243 char *name; 244 int i; 245 Bool is_atom = True; 246 float *data; 247 int nelements = 0; 248 char* endptr; 249 250 if (argc < 2) 251 { 252 fprintf(stderr, "Usage: xinput %s %s\n", n, desc); 253 return EXIT_FAILURE; 254 } 255 256 info = find_device_info(dpy, argv[0], False); 257 if (!info) 258 { 259 fprintf(stderr, "unable to find device %s\n", argv[0]); 260 return EXIT_FAILURE; 261 } 262 263 dev = XOpenDevice(dpy, info->id); 264 if (!dev) 265 { 266 fprintf(stderr, "unable to open device %s\n", argv[0]); 267 return EXIT_FAILURE; 268 } 269 270 name = argv[1]; 271 272 for(i = 0; i < strlen(name); i++) { 273 if (!isdigit(name[i])) { 274 is_atom = False; 275 break; 276 } 277 } 278 279 if (!is_atom) 280 prop = XInternAtom(dpy, name, False); 281 else 282 prop = atoi(name); 283 284 nelements = argc - 2; 285 286 float_atom = XInternAtom(dpy, "FLOAT", False); 287 288 if (float_atom == (Atom)0) 289 { 290 fprintf(stderr, "no FLOAT atom present in server\n"); 291 return EXIT_FAILURE; 292 } 293 294 if (sizeof(float) != 4) 295 { 296 fprintf(stderr, "sane FP required\n"); 297 return EXIT_FAILURE; 298 } 299 300 data = calloc(nelements, 4); 301 for (i = 0; i < nelements; i++) 302 { 303 *(data + i) = strtod(argv[2 + i], &endptr); 304 if(endptr == argv[2 + i]){ 305 fprintf(stderr, "argument %s could not be parsed\n", argv[2 + i]); 306 return EXIT_FAILURE; 307 } 308 } 309 310 XChangeDeviceProperty(dpy, dev, prop, float_atom, 32, PropModeReplace, 311 (unsigned char*)data, nelements); 312 313 free(data); 314 XCloseDevice(dpy, dev); 315 return EXIT_SUCCESS; 316} 317 318 319int watch_props(Display *dpy, int argc, char** argv, char* n, char *desc) 320{ 321 XDevice *dev; 322 XDeviceInfo *info; 323 XEvent ev; 324 XDevicePropertyNotifyEvent *dpev; 325 char *name; 326 int type_prop; 327 XEventClass cls_prop; 328 329 if (list_props(dpy, argc, argv, n, desc) != EXIT_SUCCESS) 330 return EXIT_FAILURE; 331 332 info = find_device_info(dpy, argv[0], False); 333 if (!info) 334 { 335 fprintf(stderr, "unable to find device %s\n", argv[0]); 336 return EXIT_FAILURE; 337 } 338 339 dev = XOpenDevice(dpy, info->id); 340 if (!dev) 341 { 342 fprintf(stderr, "unable to open device '%s'\n", info->name); 343 return EXIT_FAILURE; 344 } 345 346 DevicePropertyNotify(dev, type_prop, cls_prop); 347 XSelectExtensionEvent(dpy, DefaultRootWindow(dpy), &cls_prop, 1); 348 349 while(1) 350 { 351 XNextEvent(dpy, &ev); 352 353 dpev = (XDevicePropertyNotifyEvent*)&ev; 354 if (dpev->type != type_prop) 355 continue; 356 357 name = XGetAtomName(dpy, dpev->atom); 358 printf("Property '%s' changed.\n", name); 359 print_property(dpy, dev, dpev->atom); 360 } 361 362 XCloseDevice(dpy, dev); 363} 364 365int delete_prop(Display *dpy, int argc, char** argv, char* n, char *desc) 366{ 367 XDevice *dev; 368 XDeviceInfo *info; 369 char *name; 370 int i; 371 Bool is_atom = True; 372 Atom prop; 373 374 info = find_device_info(dpy, argv[0], False); 375 if (!info) 376 { 377 fprintf(stderr, "unable to find device %s\n", argv[0]); 378 return EXIT_FAILURE; 379 } 380 381 dev = XOpenDevice(dpy, info->id); 382 if (!dev) 383 { 384 fprintf(stderr, "unable to open device '%s'\n", info->name); 385 return EXIT_FAILURE; 386 } 387 388 name = argv[1]; 389 390 for(i = 0; i < strlen(name); i++) { 391 if (!isdigit(name[i])) { 392 is_atom = False; 393 break; 394 } 395 } 396 397 if (!is_atom) 398 prop = XInternAtom(dpy, name, False); 399 else 400 prop = atoi(name); 401 402 XDeleteDeviceProperty(dpy, dev, prop); 403 404 XCloseDevice(dpy, dev); 405 return EXIT_SUCCESS; 406} 407 408int 409set_atom_prop(Display *dpy, int argc, char** argv, char* n, char *desc) 410{ 411 XDeviceInfo *info; 412 XDevice *dev; 413 Atom prop; 414 char *name; 415 int i, j; 416 Bool is_atom = True; 417 Atom *data; 418 int nelements = 0; 419 420 if (argc < 3) 421 { 422 fprintf(stderr, "Usage: xinput %s %s\n", n, desc); 423 return EXIT_FAILURE; 424 } 425 426 info = find_device_info(dpy, argv[0], False); 427 if (!info) 428 { 429 fprintf(stderr, "unable to find device %s\n", argv[0]); 430 return EXIT_FAILURE; 431 } 432 433 dev = XOpenDevice(dpy, info->id); 434 if (!dev) 435 { 436 fprintf(stderr, "unable to open device %s\n", argv[0]); 437 return EXIT_FAILURE; 438 } 439 440 name = argv[1]; 441 442 for(i = 0; i < strlen(name); i++) { 443 if (!isdigit(name[i])) { 444 is_atom = False; 445 break; 446 } 447 } 448 449 if (!is_atom) 450 prop = XInternAtom(dpy, name, False); 451 else 452 prop = atoi(name); 453 454 nelements = argc - 2; 455 data = calloc(nelements, sizeof(Atom)); 456 for (i = 0; i < nelements; i++) 457 { 458 is_atom = True; 459 name = argv[2 + i]; 460 for(j = 0; j < strlen(name); j++) { 461 if (!isdigit(name[j])) { 462 is_atom = False; 463 break; 464 } 465 } 466 467 if (!is_atom) 468 data[i] = XInternAtom(dpy, name, False); 469 else 470 { 471 data[i] = atoi(name); 472 XFree(XGetAtomName(dpy, data[i])); 473 } 474 } 475 476 XChangeDeviceProperty(dpy, dev, prop, XA_ATOM, 32, PropModeReplace, 477 (unsigned char*)data, nelements); 478 479 free(data); 480 XCloseDevice(dpy, dev); 481 return EXIT_SUCCESS; 482} 483 484 485