1/* 2 * Copyright © 2007 Peter Hutterer 3 * Copyright © 2009 Red Hat, Inc. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 */ 24 25#include <ctype.h> 26#include <string.h> 27#include <stdlib.h> 28#include <stdint.h> 29#include <X11/Xatom.h> 30#include <X11/extensions/XIproto.h> 31 32#include "xinput.h" 33 34static Atom parse_atom(Display *dpy, char *name) { 35 Bool is_atom = True; 36 int i; 37 38 for (i = 0; name[i] != '\0'; i++) { 39 if (!isdigit(name[i])) { 40 is_atom = False; 41 break; 42 } 43 } 44 45 if (is_atom) 46 return atoi(name); 47 else 48 return XInternAtom(dpy, name, False); 49} 50 51static void 52print_property(Display *dpy, XDevice* dev, Atom property) 53{ 54 Atom act_type; 55 char *name; 56 int act_format; 57 unsigned long nitems, bytes_after; 58 unsigned char *data, *ptr; 59 int j, done = False, size = 0; 60 61 name = XGetAtomName(dpy, property); 62 printf("\t%s (%ld):\t", name, property); 63 XFree(name); 64 65 if (XGetDeviceProperty(dpy, dev, property, 0, 1000, False, 66 AnyPropertyType, &act_type, &act_format, 67 &nitems, &bytes_after, &data) == Success) 68 { 69 Atom float_atom = XInternAtom(dpy, "FLOAT", True); 70 71 ptr = data; 72 73 if (nitems == 0) 74 printf("<no items>"); 75 76 switch(act_format) 77 { 78 case 8: size = sizeof(char); break; 79 case 16: size = sizeof(short); break; 80 case 32: size = sizeof(long); break; 81 } 82 83 for (j = 0; j < nitems; j++) 84 { 85 switch(act_type) 86 { 87 case XA_INTEGER: 88 switch(act_format) 89 { 90 case 8: 91 printf("%d", *((char*)ptr)); 92 break; 93 case 16: 94 printf("%d", *((short*)ptr)); 95 break; 96 case 32: 97 printf("%ld", *((long*)ptr)); 98 break; 99 } 100 break; 101 case XA_CARDINAL: 102 switch(act_format) 103 { 104 case 8: 105 printf("%u", *((unsigned char*)ptr)); 106 break; 107 case 16: 108 printf("%u", *((unsigned short*)ptr)); 109 break; 110 case 32: 111 printf("%lu", *((unsigned long*)ptr)); 112 break; 113 } 114 break; 115 case XA_STRING: 116 if (act_format != 8) 117 { 118 printf("Unknown string format.\n"); 119 done = True; 120 break; 121 } 122 printf("\"%s\"", ptr); 123 j += strlen((char*)ptr); /* The loop's j++ jumps over the 124 terminating 0 */ 125 ptr += strlen((char*)ptr); /* ptr += size below jumps over 126 the terminating 0 */ 127 break; 128 case XA_ATOM: 129 { 130 Atom a = *(Atom*)ptr; 131 name = (a) ? XGetAtomName(dpy, a) : NULL; 132 printf("\"%s\" (%d)", name ? name : "None", (int)a); 133 XFree(name); 134 break; 135 } 136 default: 137 if (float_atom != None && act_type == float_atom) 138 { 139 printf("%f", *((float*)ptr)); 140 break; 141 } 142 143 name = XGetAtomName(dpy, act_type); 144 printf("\t... of unknown type '%s'\n", name); 145 XFree(name); 146 done = True; 147 break; 148 } 149 150 ptr += size; 151 152 if (done == True) 153 break; 154 if (j < nitems - 1) 155 printf(", "); 156 } 157 printf("\n"); 158 XFree(data); 159 } else 160 printf("\tFetch failure\n"); 161 162} 163 164static int 165list_props_xi1(Display *dpy, int argc, char** argv, char* name, char *desc) 166{ 167 XDeviceInfo *info; 168 XDevice *dev; 169 int i; 170 int nprops; 171 Atom *props; 172 int rc = EXIT_SUCCESS; 173 174 if (argc == 0) 175 { 176 fprintf(stderr, "Usage: xinput %s %s\n", name, desc); 177 return EXIT_FAILURE; 178 } 179 180 for (i = 0; i < argc; i++) 181 { 182 info = find_device_info(dpy, argv[i], False); 183 if (!info) 184 { 185 fprintf(stderr, "unable to find device '%s'\n", argv[i]); 186 rc = EXIT_FAILURE; 187 continue; 188 } 189 190 dev = XOpenDevice(dpy, info->id); 191 if (!dev) 192 { 193 fprintf(stderr, "unable to open device '%s'\n", info->name); 194 rc = EXIT_FAILURE; 195 continue; 196 } 197 198 props = XListDeviceProperties(dpy, dev, &nprops); 199 if (!nprops) 200 { 201 printf("Device '%s' does not report any properties.\n", info->name); 202 continue; 203 } 204 205 printf("Device '%s':\n", info->name); 206 while(nprops--) 207 { 208 print_property(dpy, dev, props[nprops]); 209 } 210 211 XFree(props); 212 XCloseDevice(dpy, dev); 213 } 214 return rc; 215} 216 217 218int watch_props(Display *dpy, int argc, char** argv, char* n, char *desc) 219{ 220 XDevice *dev; 221 XDeviceInfo *info; 222 XEvent ev; 223 XDevicePropertyNotifyEvent *dpev; 224 char *name; 225 int type_prop; 226 XEventClass cls_prop; 227 228 if (list_props(dpy, argc, argv, n, desc) != EXIT_SUCCESS) 229 return EXIT_FAILURE; 230 231 info = find_device_info(dpy, argv[0], False); 232 if (!info) 233 { 234 fprintf(stderr, "unable to find device '%s'\n", argv[0]); 235 return EXIT_FAILURE; 236 } 237 238 dev = XOpenDevice(dpy, info->id); 239 if (!dev) 240 { 241 fprintf(stderr, "unable to open device '%s'\n", info->name); 242 return EXIT_FAILURE; 243 } 244 245 DevicePropertyNotify(dev, type_prop, cls_prop); 246 XSelectExtensionEvent(dpy, DefaultRootWindow(dpy), &cls_prop, 1); 247 248 while(1) 249 { 250 XNextEvent(dpy, &ev); 251 252 dpev = (XDevicePropertyNotifyEvent*)&ev; 253 if (dpev->type != type_prop) 254 continue; 255 256 name = XGetAtomName(dpy, dpev->atom); 257 printf("Property '%s' changed.\n", name); 258 XFree(name); 259 print_property(dpy, dev, dpev->atom); 260 } 261 262 XCloseDevice(dpy, dev); 263} 264 265static int 266delete_prop_xi1(Display *dpy, int argc, char** argv, char* n, char *desc) 267{ 268 XDevice *dev; 269 XDeviceInfo *info; 270 char *name; 271 Atom prop; 272 273 if (argc < 2) 274 { 275 fprintf(stderr, "Usage: xinput %s %s\n", n, desc); 276 return EXIT_FAILURE; 277 } 278 279 info = find_device_info(dpy, argv[0], False); 280 if (!info) 281 { 282 fprintf(stderr, "unable to find device '%s'\n", argv[0]); 283 return EXIT_FAILURE; 284 } 285 286 dev = XOpenDevice(dpy, info->id); 287 if (!dev) 288 { 289 fprintf(stderr, "unable to open device '%s'\n", info->name); 290 return EXIT_FAILURE; 291 } 292 293 name = argv[1]; 294 295 prop = parse_atom(dpy, name); 296 297 XDeleteDeviceProperty(dpy, dev, prop); 298 299 XCloseDevice(dpy, dev); 300 return EXIT_SUCCESS; 301} 302 303static int 304do_set_prop_xi1(Display *dpy, Atom type, int format, int argc, char **argv, char *n, char *desc) 305{ 306 XDeviceInfo *info; 307 XDevice *dev; 308 Atom prop; 309 Atom old_type; 310 char *name; 311 int i; 312 Atom float_atom; 313 int old_format, nelements = 0; 314 unsigned long act_nitems, bytes_after; 315 char *endptr; 316 union { 317 unsigned char *c; 318 short *s; 319 long *l; 320 Atom *a; 321 } data; 322 323 if (argc < 3) 324 { 325 fprintf(stderr, "Usage: xinput %s %s\n", n, desc); 326 return EXIT_FAILURE; 327 } 328 329 info = find_device_info(dpy, argv[0], False); 330 if (!info) 331 { 332 fprintf(stderr, "unable to find device '%s'\n", argv[0]); 333 return EXIT_FAILURE; 334 } 335 336 dev = XOpenDevice(dpy, info->id); 337 if (!dev) 338 { 339 fprintf(stderr, "unable to open device '%s'\n", argv[0]); 340 return EXIT_FAILURE; 341 } 342 343 name = argv[1]; 344 345 prop = parse_atom(dpy, name); 346 347 if (prop == None) { 348 fprintf(stderr, "invalid property '%s'\n", name); 349 return EXIT_FAILURE; 350 } 351 352 float_atom = XInternAtom(dpy, "FLOAT", False); 353 354 nelements = argc - 2; 355 if (type == None || format == 0) { 356 if (XGetDeviceProperty(dpy, dev, prop, 0, 0, False, AnyPropertyType, 357 &old_type, &old_format, &act_nitems, 358 &bytes_after, &data.c) != Success) { 359 fprintf(stderr, "failed to get property type and format for '%s'\n", 360 name); 361 return EXIT_FAILURE; 362 } else { 363 if (type == None) 364 type = old_type; 365 if (format == 0) 366 format = old_format; 367 } 368 369 XFree(data.c); 370 } 371 372 if (type == None) { 373 fprintf(stderr, "property '%s' doesn't exist, you need to specify " 374 "its type and format\n", name); 375 return EXIT_FAILURE; 376 } 377 378 data.c = calloc(nelements, sizeof(long)); 379 380 for (i = 0; i < nelements; i++) 381 { 382 if (type == XA_INTEGER || type == XA_CARDINAL) { 383 switch (format) 384 { 385 case 8: 386 data.c[i] = atoi(argv[2 + i]); 387 break; 388 case 16: 389 data.s[i] = atoi(argv[2 + i]); 390 break; 391 case 32: 392 data.l[i] = atoi(argv[2 + i]); 393 break; 394 default: 395 fprintf(stderr, "unexpected size for property '%s'", name); 396 return EXIT_FAILURE; 397 } 398 } else if (type == float_atom) { 399 if (format != 32) { 400 fprintf(stderr, "unexpected format %d for property '%s'\n", 401 format, name); 402 return EXIT_FAILURE; 403 } 404 *(float *)(data.l + i) = strtod(argv[2 + i], &endptr); 405 if (endptr == argv[2 + i]) { 406 fprintf(stderr, "argument '%s' could not be parsed\n", argv[2 + i]); 407 return EXIT_FAILURE; 408 } 409 } else if (type == XA_ATOM) { 410 if (format != 32) { 411 fprintf(stderr, "unexpected format %d for property '%s'\n", 412 format, name); 413 return EXIT_FAILURE; 414 } 415 data.a[i] = parse_atom(dpy, argv[2 + i]); 416 } else { 417 fprintf(stderr, "unexpected type for property '%s'\n", name); 418 return EXIT_FAILURE; 419 } 420 } 421 422 XChangeDeviceProperty(dpy, dev, prop, type, format, PropModeReplace, 423 data.c, nelements); 424 free(data.c); 425 XCloseDevice(dpy, dev); 426 return EXIT_SUCCESS; 427} 428 429#if HAVE_XI2 430static void 431print_property_xi2(Display *dpy, int deviceid, Atom property) 432{ 433 Atom act_type; 434 char *name; 435 int act_format; 436 unsigned long nitems, bytes_after; 437 unsigned char *data, *ptr; 438 int j, done = False; 439 440 name = XGetAtomName(dpy, property); 441 printf("\t%s (%ld):\t", name, property); 442 XFree(name); 443 444 if (XIGetProperty(dpy, deviceid, property, 0, 1000, False, 445 AnyPropertyType, &act_type, &act_format, 446 &nitems, &bytes_after, &data) == Success) 447 { 448 Atom float_atom = XInternAtom(dpy, "FLOAT", True); 449 450 ptr = data; 451 452 if (nitems == 0) 453 printf("<no items>"); 454 455 for (j = 0; j < nitems; j++) 456 { 457 switch(act_type) 458 { 459 case XA_INTEGER: 460 switch(act_format) 461 { 462 case 8: 463 printf("%d", *((int8_t*)ptr)); 464 break; 465 case 16: 466 printf("%d", *((int16_t*)ptr)); 467 break; 468 case 32: 469 printf("%d", *((int32_t*)ptr)); 470 break; 471 } 472 break; 473 case XA_CARDINAL: 474 switch(act_format) 475 { 476 case 8: 477 printf("%u", *((uint8_t*)ptr)); 478 break; 479 case 16: 480 printf("%u", *((uint16_t*)ptr)); 481 break; 482 case 32: 483 printf("%u", *((uint32_t*)ptr)); 484 break; 485 } 486 break; 487 case XA_STRING: 488 if (act_format != 8) 489 { 490 printf("Unknown string format.\n"); 491 done = True; 492 break; 493 } 494 printf("\"%s\"", ptr); 495 j += strlen((char*)ptr); /* The loop's j++ jumps over the 496 terminating 0 */ 497 ptr += strlen((char*)ptr); /* ptr += size below jumps over 498 the terminating 0 */ 499 break; 500 case XA_ATOM: 501 { 502 Atom a = *(uint32_t*)ptr; 503 name = (a) ? XGetAtomName(dpy, a) : NULL; 504 printf("\"%s\" (%ld)", name ? name : "None", a); 505 XFree(name); 506 break; 507 } 508 break; 509 default: 510 if (float_atom != None && act_type == float_atom) 511 { 512 printf("%f", *((float*)ptr)); 513 break; 514 } 515 516 name = XGetAtomName(dpy, act_type); 517 printf("\t... of unknown type %s\n", name); 518 XFree(name); 519 done = True; 520 break; 521 } 522 523 ptr += act_format/8; 524 525 if (done == True) 526 break; 527 if (j < nitems - 1) 528 printf(", "); 529 } 530 printf("\n"); 531 XFree(data); 532 } else 533 printf("\tFetch failure\n"); 534 535} 536 537static int 538list_props_xi2(Display *dpy, int argc, char** argv, char* name, char *desc) 539{ 540 XIDeviceInfo *info; 541 int i; 542 int nprops; 543 Atom *props; 544 int rc = EXIT_SUCCESS; 545 546 if (argc == 0) 547 { 548 fprintf(stderr, "Usage: xinput %s %s\n", name, desc); 549 return EXIT_FAILURE; 550 } 551 552 for (i = 0; i < argc; i++) 553 { 554 info = xi2_find_device_info(dpy, argv[i]); 555 if (!info) 556 { 557 fprintf(stderr, "unable to find device %s\n", argv[i]); 558 rc = EXIT_FAILURE; 559 continue; 560 } 561 562 props = XIListProperties(dpy, info->deviceid, &nprops); 563 if (!nprops) 564 { 565 printf("Device '%s' does not report any properties.\n", info->name); 566 continue; 567 } 568 569 printf("Device '%s':\n", info->name); 570 while(nprops--) 571 { 572 print_property_xi2(dpy, info->deviceid, props[nprops]); 573 } 574 575 XFree(props); 576 } 577 return rc; 578} 579 580static int 581delete_prop_xi2(Display *dpy, int argc, char** argv, char* n, char *desc) 582{ 583 XIDeviceInfo *info; 584 char *name; 585 Atom prop; 586 587 if (argc < 2) 588 { 589 fprintf(stderr, "Usage: xinput %s %s\n", n, desc); 590 return EXIT_FAILURE; 591 } 592 593 info = xi2_find_device_info(dpy, argv[0]); 594 if (!info) 595 { 596 fprintf(stderr, "unable to find device %s\n", argv[0]); 597 return EXIT_FAILURE; 598 } 599 600 name = argv[1]; 601 602 prop = parse_atom(dpy, name); 603 604 XIDeleteProperty(dpy, info->deviceid, prop); 605 606 return EXIT_SUCCESS; 607} 608 609static int 610do_set_prop_xi2(Display *dpy, Atom type, int format, int argc, char **argv, char *n, char *desc) 611{ 612 XIDeviceInfo *info; 613 Atom prop; 614 Atom old_type; 615 char *name; 616 int i; 617 Atom float_atom; 618 int old_format, nelements = 0; 619 unsigned long act_nitems, bytes_after; 620 char *endptr; 621 union { 622 unsigned char *c; 623 int16_t *s; 624 int32_t *l; 625 } data = { NULL }; 626 int rc = EXIT_FAILURE; 627 628 if (argc < 3) 629 { 630 fprintf(stderr, "Usage: xinput %s %s\n", n, desc); 631 goto out; 632 } 633 634 info = xi2_find_device_info(dpy, argv[0]); 635 if (!info) 636 { 637 fprintf(stderr, "unable to find device %s\n", argv[0]); 638 goto out; 639 } 640 641 name = argv[1]; 642 643 prop = parse_atom(dpy, name); 644 645 if (prop == None) { 646 fprintf(stderr, "invalid property '%s'\n", name); 647 goto out; 648 } 649 650 float_atom = XInternAtom(dpy, "FLOAT", False); 651 652 nelements = argc - 2; 653 if (type == None || format == 0) { 654 if (XIGetProperty(dpy, info->deviceid, prop, 0, 0, False, 655 AnyPropertyType, &old_type, &old_format, &act_nitems, 656 &bytes_after, &data.c) != Success) { 657 fprintf(stderr, "failed to get property type and format for '%s'\n", 658 name); 659 goto out; 660 } else { 661 if (type == None) 662 type = old_type; 663 if (format == 0) 664 format = old_format; 665 } 666 667 XFree(data.c); 668 } 669 670 if (type == None) { 671 fprintf(stderr, "property '%s' doesn't exist, you need to specify " 672 "its type and format\n", name); 673 goto out; 674 } 675 676 data.c = calloc(nelements, sizeof(int32_t)); 677 678 for (i = 0; i < nelements; i++) 679 { 680 if (type == XA_INTEGER || type == XA_CARDINAL) { 681 switch (format) 682 { 683 case 8: 684 data.c[i] = atoi(argv[2 + i]); 685 break; 686 case 16: 687 data.s[i] = atoi(argv[2 + i]); 688 break; 689 case 32: 690 data.l[i] = atoi(argv[2 + i]); 691 break; 692 default: 693 fprintf(stderr, "unexpected size for property %s", name); 694 goto out; 695 } 696 } else if (type == float_atom) { 697 if (format != 32) { 698 fprintf(stderr, "unexpected format %d for property '%s'\n", 699 format, name); 700 goto out; 701 } 702 *(float *)(data.l + i) = strtod(argv[2 + i], &endptr); 703 if (endptr == argv[2 + i]) { 704 fprintf(stderr, "argument %s could not be parsed\n", argv[2 + i]); 705 goto out; 706 } 707 } else if (type == XA_ATOM) { 708 if (format != 32) { 709 fprintf(stderr, "unexpected format %d for property '%s'\n", 710 format, name); 711 goto out; 712 } 713 data.l[i] = parse_atom(dpy, argv[2 + i]); 714 } else { 715 fprintf(stderr, "unexpected type for property '%s'\n", name); 716 goto out; 717 } 718 } 719 720 XIChangeProperty(dpy, info->deviceid, prop, type, format, PropModeReplace, 721 data.c, nelements); 722 rc = EXIT_SUCCESS; 723out: 724 free(data.c); 725 return rc; 726} 727#endif 728 729int list_props(Display *display, int argc, char *argv[], char *name, 730 char *desc) 731{ 732#if HAVE_XI2 733 if (xinput_version(display) == XI_2_Major) 734 return list_props_xi2(display, argc, argv, name, desc); 735#endif 736 return list_props_xi1(display, argc, argv, name, desc); 737 738} 739 740int delete_prop(Display *display, int argc, char *argv[], char *name, 741 char *desc) 742{ 743#if HAVE_XI2 744 if (xinput_version(display) == XI_2_Major) 745 return delete_prop_xi2(display, argc, argv, name, desc); 746#endif 747 return delete_prop_xi1(display, argc, argv, name, desc); 748 749} 750 751static int 752do_set_prop(Display *display, Atom type, int format, int argc, char *argv[], char *name, char *desc) 753{ 754#if HAVE_XI2 755 if (xinput_version(display) == XI_2_Major) 756 return do_set_prop_xi2(display, type, format, argc, argv, name, desc); 757#endif 758 return do_set_prop_xi1(display, type, format, argc, argv, name, desc); 759} 760 761int 762set_atom_prop(Display *dpy, int argc, char** argv, char* n, char *desc) 763{ 764 return do_set_prop(dpy, XA_ATOM, 32, argc, argv, n, desc); 765} 766 767int 768set_int_prop(Display *dpy, int argc, char** argv, char* n, char *desc) 769{ 770 int i; 771 int format; 772 773 if (argc < 3) 774 { 775 fprintf(stderr, "Usage: xinput %s %s\n", n, desc); 776 return EXIT_FAILURE; 777 } 778 779 format = atoi(argv[2]); 780 if (format != 8 && format != 16 && format != 32) 781 { 782 fprintf(stderr, "Invalid format %d\n", format); 783 return EXIT_FAILURE; 784 } 785 786 for (i = 3; i < argc; i++) 787 argv[i - 1] = argv[i]; 788 789 return do_set_prop(dpy, XA_INTEGER, format, argc - 1, argv, n, desc); 790} 791 792int 793set_float_prop(Display *dpy, int argc, char** argv, char* n, char *desc) 794{ 795 Atom float_atom = XInternAtom(dpy, "FLOAT", False); 796 797 if (sizeof(float) != 4) 798 { 799 fprintf(stderr, "sane FP required\n"); 800 return EXIT_FAILURE; 801 } 802 803 return do_set_prop(dpy, float_atom, 32, argc, argv, n, desc); 804} 805 806int set_prop(Display *display, int argc, char *argv[], char *name, 807 char *desc) 808{ 809 Atom type = None; 810 int format = 0; 811 int i = 0, j; 812 813 while (i < argc) { 814 char *option = strchr(argv[i], '='); 815 /* skip non-option arguments */ 816 if (strncmp(argv[i], "--", 2) || !option) { 817 i++; 818 continue; 819 } 820 821 if (!strncmp(argv[i], "--type=", strlen("--type="))) { 822 if (!strcmp(option + 1, "int")) { 823 type = XA_INTEGER; 824 } else if (!strcmp(option + 1, "float")) { 825 type = XInternAtom(display, "FLOAT", False); 826 format = 32; 827 } else if (!strcmp(option + 1, "atom")) { 828 type = XA_ATOM; 829 format = 32; 830 } else { 831 fprintf(stderr, "unknown property type %s\n", option + 1); 832 return EXIT_FAILURE; 833 } 834 } else if (!strncmp(argv[i], "--format=", strlen("--format="))) { 835 format = atoi(option + 1); 836 if (format != 8 && format != 16 && format != 32) { 837 fprintf(stderr, "invalid property format '%s'\n", option + 1); 838 return EXIT_FAILURE; 839 } 840 } else { 841 fprintf(stderr, "invalid option '%s'\n", argv[i]); 842 return EXIT_FAILURE; 843 } 844 845 for (j = i; j + 1 < argc; j++) 846 argv[j] = argv[j + 1]; 847 argc--; 848 } 849 850 return do_set_prop(display, type, format, argc, argv, name, desc); 851} 852 853int disable(Display *display, int argc, char *argv[], char *name, char *desc) 854{ 855 char *new_argv[3] = { NULL, "Device Enabled", "0" }; 856 857 if (argc != 1) { 858 fprintf(stderr, "Usage: xinput %s %s\n", name, desc); 859 return EXIT_FAILURE; 860 } 861 862 new_argv[0] = argv[0]; 863 864 return set_prop(display, 3, new_argv, name, desc); 865} 866 867int enable(Display *display, int argc, char *argv[], char *name, char *desc) 868{ 869 char *new_argv[3] = { NULL, "Device Enabled", "1" }; 870 871 if (argc != 1) { 872 fprintf(stderr, "Usage: xinput %s %s\n", name, desc); 873 return EXIT_FAILURE; 874 } 875 876 new_argv[0] = argv[0]; 877 878 return set_prop(display, 3, new_argv, name, desc); 879} 880