]> diplodocus.org Git - xorg-xinput/blob - src/property.c
1ab7e4ae9d513931e9595e5fbe435779d6896e1c
[xorg-xinput] / src / property.c
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
37 static Atom parse_atom(Display *dpy, char *name) {
38 Bool is_atom = True;
39 int i;
40
41 for (i = 0; name[i] != '\0'; i++) {
42 if (!isdigit(name[i])) {
43 is_atom = False;
44 break;
45 }
46 }
47
48 if (is_atom)
49 return atoi(name);
50 else
51 return XInternAtom(dpy, name, False);
52 }
53
54 static void
55 print_property(Display *dpy, XDevice* dev, Atom property)
56 {
57 Atom act_type;
58 char *name;
59 int act_format;
60 unsigned long nitems, bytes_after;
61 unsigned char *data, *ptr;
62 int j, done = False, size;
63
64 name = XGetAtomName(dpy, property);
65 printf("\t%s (%ld):\t", name, property);
66
67 if (XGetDeviceProperty(dpy, dev, property, 0, 1000, False,
68 AnyPropertyType, &act_type, &act_format,
69 &nitems, &bytes_after, &data) == Success)
70 {
71 Atom float_atom = XInternAtom(dpy, "FLOAT", True);
72
73 ptr = data;
74
75 if (nitems == 0)
76 printf("<no items>");
77
78 switch(act_format)
79 {
80 case 8: size = sizeof(char); break;
81 case 16: size = sizeof(short); break;
82 case 32: size = sizeof(long); break;
83 }
84
85 for (j = 0; j < nitems; j++)
86 {
87 switch(act_type)
88 {
89 case XA_INTEGER:
90 switch(act_format)
91 {
92 case 8:
93 printf("%d", *((char*)ptr));
94 break;
95 case 16:
96 printf("%d", *((short*)ptr));
97 break;
98 case 32:
99 printf("%ld", *((long*)ptr));
100 break;
101 }
102 break;
103 case XA_STRING:
104 if (act_format != 8)
105 {
106 printf("Unknown string format.\n");
107 done = True;
108 break;
109 }
110 printf("\"%s\"", ptr);
111 j += strlen((char*)ptr); /* The loop's j++ jumps over the
112 terminating 0 */
113 ptr += strlen((char*)ptr); /* ptr += size below jumps over
114 the terminating 0 */
115 break;
116 case XA_ATOM:
117 {
118 Atom a = *(Atom*)ptr;
119 printf("\"%s\" (%d)",
120 (a) ? XGetAtomName(dpy, a) : "None",
121 (int)a);
122 break;
123 }
124 default:
125 if (float_atom != None && act_type == float_atom)
126 {
127 printf("%f", *((float*)ptr));
128 break;
129 }
130
131 printf("\t... of unknown type %s\n",
132 XGetAtomName(dpy, act_type));
133 done = True;
134 break;
135 }
136
137 ptr += size;
138
139 if (done == True)
140 break;
141 if (j < nitems - 1)
142 printf(", ");
143 }
144 printf("\n");
145 XFree(data);
146 } else
147 printf("\tFetch failure\n");
148
149 }
150
151 static int
152 list_props_xi1(Display *dpy, int argc, char** argv, char* name, char *desc)
153 {
154 XDeviceInfo *info;
155 XDevice *dev;
156 int i;
157 int nprops;
158 Atom *props;
159
160 if (argc == 0)
161 {
162 fprintf(stderr, "Usage: xinput %s %s\n", name, desc);
163 return EXIT_FAILURE;
164 }
165
166 for (i = 0; i < argc; i++)
167 {
168 info = find_device_info(dpy, argv[i], False);
169 if (!info)
170 {
171 fprintf(stderr, "unable to find device %s\n", argv[i]);
172 continue;
173 }
174
175 dev = XOpenDevice(dpy, info->id);
176 if (!dev)
177 {
178 fprintf(stderr, "unable to open device '%s'\n", info->name);
179 continue;
180 }
181
182 props = XListDeviceProperties(dpy, dev, &nprops);
183 if (!nprops)
184 {
185 printf("Device '%s' does not report any properties.\n", info->name);
186 continue;
187 }
188
189 printf("Device '%s':\n", info->name);
190 while(nprops--)
191 {
192 print_property(dpy, dev, props[nprops]);
193 }
194
195 XFree(props);
196 XCloseDevice(dpy, dev);
197 }
198 return EXIT_SUCCESS;
199 }
200
201 int
202 set_int_prop(Display *dpy, int argc, char** argv, char* n, char *desc)
203 {
204 XDeviceInfo *info;
205 XDevice *dev;
206 Atom prop;
207 char *name;
208 int i;
209 char *data;
210 int format, nelements = 0;
211
212 if (argc < 3)
213 {
214 fprintf(stderr, "Usage: xinput %s %s\n", n, desc);
215 return EXIT_FAILURE;
216 }
217
218 info = find_device_info(dpy, argv[0], False);
219 if (!info)
220 {
221 fprintf(stderr, "unable to find device %s\n", argv[0]);
222 return EXIT_FAILURE;
223 }
224
225 dev = XOpenDevice(dpy, info->id);
226 if (!dev)
227 {
228 fprintf(stderr, "unable to open device %s\n", argv[0]);
229 return EXIT_FAILURE;
230 }
231
232 name = argv[1];
233
234 prop = parse_atom(dpy, name);
235
236 nelements = argc - 3;
237 format = atoi(argv[2]);
238 if (format != 8 && format != 16 && format != 32)
239 {
240 fprintf(stderr, "Invalid format %d\n", format);
241 return EXIT_FAILURE;
242 }
243
244 data = calloc(nelements, sizeof(long));
245 for (i = 0; i < nelements; i++)
246 {
247 switch(format)
248 {
249 case 8:
250 *(((char*)data) + i) = atoi(argv[3 + i]);
251 break;
252 case 16:
253 *(((short*)data) + i) = atoi(argv[3 + i]);
254 break;
255 case 32:
256 *(((long*)data) + i) = atoi(argv[3 + i]);
257 break;
258 }
259 }
260
261 XChangeDeviceProperty(dpy, dev, prop, XA_INTEGER, format, PropModeReplace,
262 (unsigned char*)data, nelements);
263
264 free(data);
265 XCloseDevice(dpy, dev);
266 return EXIT_SUCCESS;
267 }
268
269 int
270 set_float_prop(Display *dpy, int argc, char** argv, char* n, char *desc)
271 {
272 XDeviceInfo *info;
273 XDevice *dev;
274 Atom prop, float_atom;
275 char *name;
276 int i;
277 long *data;
278 int nelements = 0;
279 char* endptr;
280
281 if (argc < 2)
282 {
283 fprintf(stderr, "Usage: xinput %s %s\n", n, desc);
284 return EXIT_FAILURE;
285 }
286
287 info = find_device_info(dpy, argv[0], False);
288 if (!info)
289 {
290 fprintf(stderr, "unable to find device %s\n", argv[0]);
291 return EXIT_FAILURE;
292 }
293
294 dev = XOpenDevice(dpy, info->id);
295 if (!dev)
296 {
297 fprintf(stderr, "unable to open device %s\n", argv[0]);
298 return EXIT_FAILURE;
299 }
300
301 name = argv[1];
302
303 prop = parse_atom(dpy, name);
304
305 nelements = argc - 2;
306
307 float_atom = XInternAtom(dpy, "FLOAT", False);
308
309 if (float_atom == (Atom)0)
310 {
311 fprintf(stderr, "no FLOAT atom present in server\n");
312 return EXIT_FAILURE;
313 }
314
315 if (sizeof(float) != 4)
316 {
317 fprintf(stderr, "sane FP required\n");
318 return EXIT_FAILURE;
319 }
320
321 data = calloc(nelements, sizeof(long));
322 for (i = 0; i < nelements; i++)
323 {
324 *((float*)(data + i)) = strtod(argv[2 + i], &endptr);
325 if(endptr == argv[2 + i]){
326 fprintf(stderr, "argument %s could not be parsed\n", argv[2 + i]);
327 return EXIT_FAILURE;
328 }
329 }
330
331 XChangeDeviceProperty(dpy, dev, prop, float_atom, 32, PropModeReplace,
332 (unsigned char*)data, nelements);
333
334 free(data);
335 XCloseDevice(dpy, dev);
336 return EXIT_SUCCESS;
337 }
338
339
340 int watch_props(Display *dpy, int argc, char** argv, char* n, char *desc)
341 {
342 XDevice *dev;
343 XDeviceInfo *info;
344 XEvent ev;
345 XDevicePropertyNotifyEvent *dpev;
346 char *name;
347 int type_prop;
348 XEventClass cls_prop;
349
350 if (list_props(dpy, argc, argv, n, desc) != EXIT_SUCCESS)
351 return EXIT_FAILURE;
352
353 info = find_device_info(dpy, argv[0], False);
354 if (!info)
355 {
356 fprintf(stderr, "unable to find device %s\n", argv[0]);
357 return EXIT_FAILURE;
358 }
359
360 dev = XOpenDevice(dpy, info->id);
361 if (!dev)
362 {
363 fprintf(stderr, "unable to open device '%s'\n", info->name);
364 return EXIT_FAILURE;
365 }
366
367 DevicePropertyNotify(dev, type_prop, cls_prop);
368 XSelectExtensionEvent(dpy, DefaultRootWindow(dpy), &cls_prop, 1);
369
370 while(1)
371 {
372 XNextEvent(dpy, &ev);
373
374 dpev = (XDevicePropertyNotifyEvent*)&ev;
375 if (dpev->type != type_prop)
376 continue;
377
378 name = XGetAtomName(dpy, dpev->atom);
379 printf("Property '%s' changed.\n", name);
380 print_property(dpy, dev, dpev->atom);
381 }
382
383 XCloseDevice(dpy, dev);
384 }
385
386 static int
387 delete_prop_xi1(Display *dpy, int argc, char** argv, char* n, char *desc)
388 {
389 XDevice *dev;
390 XDeviceInfo *info;
391 char *name;
392 Atom prop;
393
394 info = find_device_info(dpy, argv[0], False);
395 if (!info)
396 {
397 fprintf(stderr, "unable to find device %s\n", argv[0]);
398 return EXIT_FAILURE;
399 }
400
401 dev = XOpenDevice(dpy, info->id);
402 if (!dev)
403 {
404 fprintf(stderr, "unable to open device '%s'\n", info->name);
405 return EXIT_FAILURE;
406 }
407
408 name = argv[1];
409
410 prop = parse_atom(dpy, name);
411
412 XDeleteDeviceProperty(dpy, dev, prop);
413
414 XCloseDevice(dpy, dev);
415 return EXIT_SUCCESS;
416 }
417
418 int
419 set_atom_prop(Display *dpy, int argc, char** argv, char* n, char *desc)
420 {
421 XDeviceInfo *info;
422 XDevice *dev;
423 Atom prop;
424 char *name;
425 int i, j;
426 Bool is_atom;
427 Atom *data;
428 int nelements = 0;
429
430 if (argc < 3)
431 {
432 fprintf(stderr, "Usage: xinput %s %s\n", n, desc);
433 return EXIT_FAILURE;
434 }
435
436 info = find_device_info(dpy, argv[0], False);
437 if (!info)
438 {
439 fprintf(stderr, "unable to find device %s\n", argv[0]);
440 return EXIT_FAILURE;
441 }
442
443 dev = XOpenDevice(dpy, info->id);
444 if (!dev)
445 {
446 fprintf(stderr, "unable to open device %s\n", argv[0]);
447 return EXIT_FAILURE;
448 }
449
450 name = argv[1];
451
452 prop = parse_atom(dpy, 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 static int
485 do_set_prop_xi1(Display *dpy, Atom type, int format, int argc, char **argv, char *n, char *desc)
486 {
487 XDeviceInfo *info;
488 XDevice *dev;
489 Atom prop;
490 Atom old_type;
491 char *name;
492 int i;
493 Atom float_atom;
494 int old_format, nelements = 0;
495 unsigned long act_nitems, bytes_after;
496 char *endptr;
497 union {
498 unsigned char *c;
499 short *s;
500 long *l;
501 Atom *a;
502 } data;
503
504 if (argc < 3)
505 {
506 fprintf(stderr, "Usage: xinput %s %s\n", n, desc);
507 return EXIT_FAILURE;
508 }
509
510 info = find_device_info(dpy, argv[0], False);
511 if (!info)
512 {
513 fprintf(stderr, "unable to find device %s\n", argv[0]);
514 return EXIT_FAILURE;
515 }
516
517 dev = XOpenDevice(dpy, info->id);
518 if (!dev)
519 {
520 fprintf(stderr, "unable to open device %s\n", argv[0]);
521 return EXIT_FAILURE;
522 }
523
524 name = argv[1];
525
526 prop = parse_atom(dpy, name);
527
528 if (prop == None) {
529 fprintf(stderr, "invalid property %s\n", name);
530 return EXIT_FAILURE;
531 }
532
533 float_atom = XInternAtom(dpy, "FLOAT", False);
534
535 nelements = argc - 2;
536 if (type == None || format == 0) {
537 if (XGetDeviceProperty(dpy, dev, prop, 0, 0, False, AnyPropertyType,
538 &old_type, &old_format, &act_nitems,
539 &bytes_after, &data.c) != Success) {
540 fprintf(stderr, "failed to get property type and format for %s\n",
541 name);
542 return EXIT_FAILURE;
543 } else {
544 if (type == None)
545 type = old_type;
546 if (format == 0)
547 format = old_format;
548 }
549
550 XFree(data.c);
551 }
552
553 if (type == None) {
554 fprintf(stderr, "property %s doesn't exist, you need to specify "
555 "its type and format\n", name);
556 return EXIT_FAILURE;
557 }
558
559 data.c = calloc(nelements, sizeof(long));
560
561 for (i = 0; i < nelements; i++)
562 {
563 if (type == XA_INTEGER) {
564 switch (format)
565 {
566 case 8:
567 data.c[i] = atoi(argv[2 + i]);
568 break;
569 case 16:
570 data.s[i] = atoi(argv[2 + i]);
571 break;
572 case 32:
573 data.l[i] = atoi(argv[2 + i]);
574 break;
575 default:
576 fprintf(stderr, "unexpected size for property %s", name);
577 return EXIT_FAILURE;
578 }
579 } else if (type == float_atom) {
580 if (format != 32) {
581 fprintf(stderr, "unexpected format %d for property %s\n",
582 format, name);
583 return EXIT_FAILURE;
584 }
585 *(float *)(data.l + i) = strtod(argv[2 + i], &endptr);
586 if (endptr == argv[2 + i]) {
587 fprintf(stderr, "argument %s could not be parsed\n", argv[2 + i]);
588 return EXIT_FAILURE;
589 }
590 } else if (type == XA_ATOM) {
591 if (format != 32) {
592 fprintf(stderr, "unexpected format %d for property %s\n",
593 format, name);
594 return EXIT_FAILURE;
595 }
596 data.a[i] = parse_atom(dpy, argv[2 + i]);
597 } else {
598 fprintf(stderr, "unexpected type for property %s\n", name);
599 return EXIT_FAILURE;
600 }
601 }
602
603 XChangeDeviceProperty(dpy, dev, prop, type, format, PropModeReplace,
604 data.c, nelements);
605 free(data.c);
606 XCloseDevice(dpy, dev);
607 return EXIT_SUCCESS;
608 }
609
610 #if HAVE_XI2
611 static void
612 print_property_xi2(Display *dpy, int deviceid, Atom property)
613 {
614 Atom act_type;
615 char *name;
616 int act_format;
617 unsigned long nitems, bytes_after;
618 unsigned char *data, *ptr;
619 int j, done = False;
620
621 name = XGetAtomName(dpy, property);
622 printf("\t%s (%ld):\t", name, property);
623
624 if (XIGetProperty(dpy, deviceid, property, 0, 1000, False,
625 AnyPropertyType, &act_type, &act_format,
626 &nitems, &bytes_after, &data) == Success)
627 {
628 Atom float_atom = XInternAtom(dpy, "FLOAT", True);
629
630 ptr = data;
631
632 if (nitems == 0)
633 printf("<no items>");
634
635 for (j = 0; j < nitems; j++)
636 {
637 switch(act_type)
638 {
639 case XA_INTEGER:
640 switch(act_format)
641 {
642 case 8:
643 printf("%d", *((int8_t*)ptr));
644 break;
645 case 16:
646 printf("%d", *((int16_t*)ptr));
647 break;
648 case 32:
649 printf("%d", *((int32_t*)ptr));
650 break;
651 }
652 break;
653 case XA_STRING:
654 if (act_format != 8)
655 {
656 printf("Unknown string format.\n");
657 done = True;
658 break;
659 }
660 printf("\"%s\"", ptr);
661 j += strlen((char*)ptr); /* The loop's j++ jumps over the
662 terminating 0 */
663 ptr += strlen((char*)ptr); /* ptr += size below jumps over
664 the terminating 0 */
665 break;
666 case XA_ATOM:
667 {
668 Atom a = *(Atom*)ptr;
669 printf("\"%s\" (%d)",
670 (a) ? XGetAtomName(dpy, a) : "None",
671 (int)a);
672 break;
673 }
674 break;
675 default:
676 if (float_atom != None && act_type == float_atom)
677 {
678 printf("%f", *((float*)ptr));
679 break;
680 }
681
682 printf("\t... of unknown type %s\n",
683 XGetAtomName(dpy, act_type));
684 done = True;
685 break;
686 }
687
688 ptr += act_format/8;
689
690 if (done == True)
691 break;
692 if (j < nitems - 1)
693 printf(", ");
694 }
695 printf("\n");
696 XFree(data);
697 } else
698 printf("\tFetch failure\n");
699
700 }
701
702 static int
703 list_props_xi2(Display *dpy, int argc, char** argv, char* name, char *desc)
704 {
705 XIDeviceInfo *info;
706 int i;
707 int nprops;
708 Atom *props;
709
710 if (argc == 0)
711 {
712 fprintf(stderr, "Usage: xinput %s %s\n", name, desc);
713 return EXIT_FAILURE;
714 }
715
716 for (i = 0; i < argc; i++)
717 {
718 info = xi2_find_device_info(dpy, argv[i]);
719 if (!info)
720 {
721 fprintf(stderr, "unable to find device %s\n", argv[i]);
722 continue;
723 }
724
725 props = XIListProperties(dpy, info->deviceid, &nprops);
726 if (!nprops)
727 {
728 printf("Device '%s' does not report any properties.\n", info->name);
729 continue;
730 }
731
732 printf("Device '%s':\n", info->name);
733 while(nprops--)
734 {
735 print_property_xi2(dpy, info->deviceid, props[nprops]);
736 }
737
738 XFree(props);
739 }
740 return EXIT_SUCCESS;
741 }
742
743 static int
744 delete_prop_xi2(Display *dpy, int argc, char** argv, char* n, char *desc)
745 {
746 XIDeviceInfo *info;
747 char *name;
748 Atom prop;
749
750 info = xi2_find_device_info(dpy, argv[0]);
751 if (!info)
752 {
753 fprintf(stderr, "unable to find device %s\n", argv[0]);
754 return EXIT_FAILURE;
755 }
756
757 name = argv[1];
758
759 prop = parse_atom(dpy, name);
760
761 XIDeleteProperty(dpy, info->deviceid, prop);
762
763 return EXIT_SUCCESS;
764 }
765
766 static int
767 do_set_prop_xi2(Display *dpy, Atom type, int format, int argc, char **argv, char *n, char *desc)
768 {
769 XIDeviceInfo *info;
770 Atom prop;
771 Atom old_type;
772 char *name;
773 int i;
774 Atom float_atom;
775 int old_format, nelements = 0;
776 unsigned long act_nitems, bytes_after;
777 char *endptr;
778 union {
779 unsigned char *c;
780 int16_t *s;
781 int32_t *l;
782 } data;
783
784 if (argc < 3)
785 {
786 fprintf(stderr, "Usage: xinput %s %s\n", n, desc);
787 return EXIT_FAILURE;
788 }
789
790 info = xi2_find_device_info(dpy, argv[0]);
791 if (!info)
792 {
793 fprintf(stderr, "unable to find device %s\n", argv[0]);
794 return EXIT_FAILURE;
795 }
796
797 name = argv[1];
798
799 prop = parse_atom(dpy, name);
800
801 if (prop == None) {
802 fprintf(stderr, "invalid property %s\n", name);
803 return EXIT_FAILURE;
804 }
805
806 float_atom = XInternAtom(dpy, "FLOAT", False);
807
808 nelements = argc - 2;
809 if (type == None || format == 0) {
810 if (XIGetProperty(dpy, info->deviceid, prop, 0, 0, False,
811 AnyPropertyType, &old_type, &old_format, &act_nitems,
812 &bytes_after, &data.c) != Success) {
813 fprintf(stderr, "failed to get property type and format for %s\n",
814 name);
815 return EXIT_FAILURE;
816 } else {
817 if (type == None)
818 type = old_type;
819 if (format == 0)
820 format = old_format;
821 }
822
823 XFree(data.c);
824 }
825
826 if (type == None) {
827 fprintf(stderr, "property %s doesn't exist, you need to specify "
828 "its type and format\n", name);
829 return EXIT_FAILURE;
830 }
831
832 data.c = calloc(nelements, sizeof(int32_t));
833
834 for (i = 0; i < nelements; i++)
835 {
836 if (type == XA_INTEGER) {
837 switch (format)
838 {
839 case 8:
840 data.c[i] = atoi(argv[2 + i]);
841 break;
842 case 16:
843 data.s[i] = atoi(argv[2 + i]);
844 break;
845 case 32:
846 data.l[i] = atoi(argv[2 + i]);
847 break;
848 default:
849 fprintf(stderr, "unexpected size for property %s", name);
850 return EXIT_FAILURE;
851 }
852 } else if (type == float_atom) {
853 if (format != 32) {
854 fprintf(stderr, "unexpected format %d for property %s\n",
855 format, name);
856 return EXIT_FAILURE;
857 }
858 *(float *)(data.l + i) = strtod(argv[2 + i], &endptr);
859 if (endptr == argv[2 + i]) {
860 fprintf(stderr, "argument %s could not be parsed\n", argv[2 + i]);
861 return EXIT_FAILURE;
862 }
863 } else if (type == XA_ATOM) {
864 if (format != 32) {
865 fprintf(stderr, "unexpected format %d for property %s\n",
866 format, name);
867 return EXIT_FAILURE;
868 }
869 data.l[i] = parse_atom(dpy, argv[2 + i]);
870 } else {
871 fprintf(stderr, "unexpected type for property %s\n", name);
872 return EXIT_FAILURE;
873 }
874 }
875
876 XIChangeProperty(dpy, info->deviceid, prop, type, format, PropModeReplace,
877 data.c, nelements);
878 free(data.c);
879 return EXIT_SUCCESS;
880 }
881 #endif
882
883 int list_props(Display *display, int argc, char *argv[], char *name,
884 char *desc)
885 {
886 #ifdef HAVE_XI2
887 if (xinput_version(display) == XI_2_Major)
888 return list_props_xi2(display, argc, argv, name, desc);
889 #endif
890 return list_props_xi1(display, argc, argv, name, desc);
891
892 }
893
894 int delete_prop(Display *display, int argc, char *argv[], char *name,
895 char *desc)
896 {
897 #ifdef HAVE_XI2
898 if (xinput_version(display) == XI_2_Major)
899 return delete_prop_xi2(display, argc, argv, name, desc);
900 #endif
901 return delete_prop_xi1(display, argc, argv, name, desc);
902
903 }
904
905 static int
906 do_set_prop(Display *display, Atom type, int format, int argc, char *argv[], char *name, char *desc)
907 {
908 #ifdef HAVE_XI2
909 if (xinput_version(display) == XI_2_Major)
910 return do_set_prop_xi2(display, type, format, argc, argv, name, desc);
911 #endif
912 return do_set_prop_xi1(display, type, format, argc, argv, name, desc);
913 }
914
915 int set_prop(Display *display, int argc, char *argv[], char *name,
916 char *desc)
917 {
918 Atom type = None;
919 int format = 0;
920 int i = 0, j;
921
922 while (i < argc) {
923 char *option = strchr(argv[i], '=');
924 /* skip non-option arguments */
925 if (strncmp(argv[i], "--", 2) || !option) {
926 i++;
927 continue;
928 }
929
930 if (!strncmp(argv[i], "--type=", strlen("--type="))) {
931 if (!strcmp(option + 1, "int")) {
932 type = XA_INTEGER;
933 } else if (!strcmp(option + 1, "float")) {
934 type = XInternAtom(display, "FLOAT", False);
935 format = 32;
936 } else if (!strcmp(option + 1, "atom")) {
937 type = XA_ATOM;
938 format = 32;
939 } else {
940 fprintf(stderr, "unknown property type %s\n", option + 1);
941 return EXIT_FAILURE;
942 }
943 } else if (!strncmp(argv[i], "--format=", strlen("--format="))) {
944 format = atoi(option + 1);
945 if (format != 8 && format != 16 && format != 32) {
946 fprintf(stderr, "invalid property format %s\n", option + 1);
947 return EXIT_FAILURE;
948 }
949 } else {
950 fprintf(stderr, "invalid option %s\n", argv[i]);
951 return EXIT_FAILURE;
952 }
953
954 for (j = i; j + 1 < argc; j++)
955 argv[j] = argv[j + 1];
956 argc--;
957 }
958
959 return do_set_prop(display, type, format, argc, argv, name, desc);
960 }