property.c revision d3263506
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, done = False, size; 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 Atom float_atom = XInternAtom(dpy, "FLOAT", True); 55 56 ptr = data; 57 58 switch(act_format) 59 { 60 case 8: size = sizeof(char); break; 61 case 16: size = sizeof(short); break; 62 case 32: size = sizeof(long); break; 63 } 64 65 for (j = 0; j < nitems; j++) 66 { 67 switch(act_type) 68 { 69 case XA_INTEGER: 70 switch(act_format) 71 { 72 case 8: 73 printf("%d", *((char*)ptr)); 74 break; 75 case 16: 76 printf("%d", *((short*)ptr)); 77 break; 78 case 32: 79 printf("%ld", *((long*)ptr)); 80 break; 81 } 82 break; 83 case XA_STRING: 84 if (act_format != 8) 85 { 86 printf("Unknown string format.\n"); 87 done = True; 88 break; 89 } 90 printf("\"%s\"", ptr); 91 j += strlen((char*)ptr); /* The loop's j++ jumps over the 92 terminating 0 */ 93 ptr += strlen((char*)ptr); /* ptr += size below jumps over 94 the terminating 0 */ 95 break; 96 case XA_ATOM: 97 printf("\"%s\"", XGetAtomName(dpy, *(Atom*)ptr)); 98 break; 99 default: 100 if (float_atom != None && act_type == float_atom) 101 { 102 printf("%f", *((float*)ptr)); 103 break; 104 } 105 106 printf("\t... of unknown type %s\n", 107 XGetAtomName(dpy, act_type)); 108 done = True; 109 break; 110 } 111 112 ptr += size; 113 114 if (j < nitems - 1) 115 printf(", "); 116 if (done == True) 117 break; 118 } 119 printf("\n"); 120 XFree(data); 121 } else 122 printf("\tFetch failure\n"); 123 124} 125 126int list_props(Display *dpy, int argc, char** argv, char* name, char *desc) 127{ 128 XDeviceInfo *info; 129 XDevice *dev; 130 int i; 131 int nprops; 132 Atom *props; 133 134 if (argc == 0) 135 { 136 fprintf(stderr, "Usage: xinput %s %s\n", name, desc); 137 return EXIT_FAILURE; 138 } 139 140 for (i = 0; i < argc; i++) 141 { 142 info = find_device_info(dpy, argv[i], False); 143 if (!info) 144 { 145 fprintf(stderr, "unable to find device %s\n", argv[i]); 146 continue; 147 } 148 149 dev = XOpenDevice(dpy, info->id); 150 if (!dev) 151 { 152 fprintf(stderr, "unable to open device '%s'\n", info->name); 153 continue; 154 } 155 156 props = XListDeviceProperties(dpy, dev, &nprops); 157 if (!nprops) 158 { 159 printf("Device '%s' does not report any properties.\n", info->name); 160 continue; 161 } 162 163 printf("Device '%s':\n", info->name); 164 while(nprops--) 165 { 166 print_property(dpy, dev, props[nprops]); 167 } 168 169 XFree(props); 170 XCloseDevice(dpy, dev); 171 } 172 return EXIT_SUCCESS; 173} 174 175int 176set_int_prop(Display *dpy, int argc, char** argv, char* n, char *desc) 177{ 178 XDeviceInfo *info; 179 XDevice *dev; 180 Atom prop; 181 char *name; 182 int i; 183 Bool is_atom = True; 184 char *data; 185 int format, nelements = 0; 186 187 if (argc < 3) 188 { 189 fprintf(stderr, "Usage: xinput %s %s\n", n, desc); 190 return EXIT_FAILURE; 191 } 192 193 info = find_device_info(dpy, argv[0], False); 194 if (!info) 195 { 196 fprintf(stderr, "unable to find device %s\n", argv[0]); 197 return EXIT_FAILURE; 198 } 199 200 dev = XOpenDevice(dpy, info->id); 201 if (!dev) 202 { 203 fprintf(stderr, "unable to open device %s\n", argv[0]); 204 return EXIT_FAILURE; 205 } 206 207 name = argv[1]; 208 209 for(i = 0; i < strlen(name); i++) { 210 if (!isdigit(name[i])) { 211 is_atom = False; 212 break; 213 } 214 } 215 216 if (!is_atom) 217 prop = XInternAtom(dpy, name, False); 218 else 219 prop = atoi(name); 220 221 nelements = argc - 3; 222 format = atoi(argv[2]); 223 if (format != 8 && format != 16 && format != 32) 224 { 225 fprintf(stderr, "Invalid format %d\n", format); 226 return EXIT_FAILURE; 227 } 228 229 data = calloc(nelements, sizeof(long)); 230 for (i = 0; i < nelements; i++) 231 { 232 switch(format) 233 { 234 case 8: 235 *(((char*)data) + i) = atoi(argv[3 + i]); 236 break; 237 case 16: 238 *(((short*)data) + i) = atoi(argv[3 + i]); 239 break; 240 case 32: 241 *(((long*)data) + i) = atoi(argv[3 + i]); 242 break; 243 } 244 } 245 246 XChangeDeviceProperty(dpy, dev, prop, XA_INTEGER, format, PropModeReplace, 247 (unsigned char*)data, nelements); 248 249 free(data); 250 XCloseDevice(dpy, dev); 251 return EXIT_SUCCESS; 252} 253 254int 255set_float_prop(Display *dpy, int argc, char** argv, char* n, char *desc) 256{ 257 XDeviceInfo *info; 258 XDevice *dev; 259 Atom prop, float_atom; 260 char *name; 261 int i; 262 Bool is_atom = True; 263 long *data; 264 int nelements = 0; 265 char* endptr; 266 267 if (argc < 2) 268 { 269 fprintf(stderr, "Usage: xinput %s %s\n", n, desc); 270 return EXIT_FAILURE; 271 } 272 273 info = find_device_info(dpy, argv[0], False); 274 if (!info) 275 { 276 fprintf(stderr, "unable to find device %s\n", argv[0]); 277 return EXIT_FAILURE; 278 } 279 280 dev = XOpenDevice(dpy, info->id); 281 if (!dev) 282 { 283 fprintf(stderr, "unable to open device %s\n", argv[0]); 284 return EXIT_FAILURE; 285 } 286 287 name = argv[1]; 288 289 for(i = 0; i < strlen(name); i++) { 290 if (!isdigit(name[i])) { 291 is_atom = False; 292 break; 293 } 294 } 295 296 if (!is_atom) 297 prop = XInternAtom(dpy, name, False); 298 else 299 prop = atoi(name); 300 301 nelements = argc - 2; 302 303 float_atom = XInternAtom(dpy, "FLOAT", False); 304 305 if (float_atom == (Atom)0) 306 { 307 fprintf(stderr, "no FLOAT atom present in server\n"); 308 return EXIT_FAILURE; 309 } 310 311 if (sizeof(float) != 4) 312 { 313 fprintf(stderr, "sane FP required\n"); 314 return EXIT_FAILURE; 315 } 316 317 data = calloc(nelements, sizeof(long)); 318 for (i = 0; i < nelements; i++) 319 { 320 *((float*)(data + i)) = strtod(argv[2 + i], &endptr); 321 if(endptr == argv[2 + i]){ 322 fprintf(stderr, "argument %s could not be parsed\n", argv[2 + i]); 323 return EXIT_FAILURE; 324 } 325 } 326 327 XChangeDeviceProperty(dpy, dev, prop, float_atom, 32, PropModeReplace, 328 (unsigned char*)data, nelements); 329 330 free(data); 331 XCloseDevice(dpy, dev); 332 return EXIT_SUCCESS; 333} 334 335 336int watch_props(Display *dpy, int argc, char** argv, char* n, char *desc) 337{ 338 XDevice *dev; 339 XDeviceInfo *info; 340 XEvent ev; 341 XDevicePropertyNotifyEvent *dpev; 342 char *name; 343 int type_prop; 344 XEventClass cls_prop; 345 346 if (list_props(dpy, argc, argv, n, desc) != EXIT_SUCCESS) 347 return EXIT_FAILURE; 348 349 info = find_device_info(dpy, argv[0], False); 350 if (!info) 351 { 352 fprintf(stderr, "unable to find device %s\n", argv[0]); 353 return EXIT_FAILURE; 354 } 355 356 dev = XOpenDevice(dpy, info->id); 357 if (!dev) 358 { 359 fprintf(stderr, "unable to open device '%s'\n", info->name); 360 return EXIT_FAILURE; 361 } 362 363 DevicePropertyNotify(dev, type_prop, cls_prop); 364 XSelectExtensionEvent(dpy, DefaultRootWindow(dpy), &cls_prop, 1); 365 366 while(1) 367 { 368 XNextEvent(dpy, &ev); 369 370 dpev = (XDevicePropertyNotifyEvent*)&ev; 371 if (dpev->type != type_prop) 372 continue; 373 374 name = XGetAtomName(dpy, dpev->atom); 375 printf("Property '%s' changed.\n", name); 376 print_property(dpy, dev, dpev->atom); 377 } 378 379 XCloseDevice(dpy, dev); 380} 381 382int delete_prop(Display *dpy, int argc, char** argv, char* n, char *desc) 383{ 384 XDevice *dev; 385 XDeviceInfo *info; 386 char *name; 387 int i; 388 Bool is_atom = True; 389 Atom prop; 390 391 info = find_device_info(dpy, argv[0], False); 392 if (!info) 393 { 394 fprintf(stderr, "unable to find device %s\n", argv[0]); 395 return EXIT_FAILURE; 396 } 397 398 dev = XOpenDevice(dpy, info->id); 399 if (!dev) 400 { 401 fprintf(stderr, "unable to open device '%s'\n", info->name); 402 return EXIT_FAILURE; 403 } 404 405 name = argv[1]; 406 407 for(i = 0; i < strlen(name); i++) { 408 if (!isdigit(name[i])) { 409 is_atom = False; 410 break; 411 } 412 } 413 414 if (!is_atom) 415 prop = XInternAtom(dpy, name, False); 416 else 417 prop = atoi(name); 418 419 XDeleteDeviceProperty(dpy, dev, prop); 420 421 XCloseDevice(dpy, dev); 422 return EXIT_SUCCESS; 423} 424 425int 426set_atom_prop(Display *dpy, int argc, char** argv, char* n, char *desc) 427{ 428 XDeviceInfo *info; 429 XDevice *dev; 430 Atom prop; 431 char *name; 432 int i, j; 433 Bool is_atom = True; 434 Atom *data; 435 int nelements = 0; 436 437 if (argc < 3) 438 { 439 fprintf(stderr, "Usage: xinput %s %s\n", n, desc); 440 return EXIT_FAILURE; 441 } 442 443 info = find_device_info(dpy, argv[0], False); 444 if (!info) 445 { 446 fprintf(stderr, "unable to find device %s\n", argv[0]); 447 return EXIT_FAILURE; 448 } 449 450 dev = XOpenDevice(dpy, info->id); 451 if (!dev) 452 { 453 fprintf(stderr, "unable to open device %s\n", argv[0]); 454 return EXIT_FAILURE; 455 } 456 457 name = argv[1]; 458 459 for(i = 0; i < strlen(name); i++) { 460 if (!isdigit(name[i])) { 461 is_atom = False; 462 break; 463 } 464 } 465 466 if (!is_atom) 467 prop = XInternAtom(dpy, name, False); 468 else 469 prop = atoi(name); 470 471 nelements = argc - 2; 472 data = calloc(nelements, sizeof(Atom)); 473 for (i = 0; i < nelements; i++) 474 { 475 is_atom = True; 476 name = argv[2 + i]; 477 for(j = 0; j < strlen(name); j++) { 478 if (!isdigit(name[j])) { 479 is_atom = False; 480 break; 481 } 482 } 483 484 if (!is_atom) 485 data[i] = XInternAtom(dpy, name, False); 486 else 487 { 488 data[i] = atoi(name); 489 XFree(XGetAtomName(dpy, data[i])); 490 } 491 } 492 493 XChangeDeviceProperty(dpy, dev, prop, XA_ATOM, 32, PropModeReplace, 494 (unsigned char*)data, nelements); 495 496 free(data); 497 XCloseDevice(dpy, dev); 498 return EXIT_SUCCESS; 499} 500 501 502