list.c revision 0309d3b3
1/*
2 * Copyright 1996 by Frederic Lepied, France. <Frederic.Lepied@sugix.frmug.org>
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, and that   the  name of  the authors  not  be  used  in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific,  written      prior  permission.     The authors  make  no
11 * representations about the suitability of this software for any purpose.  It
12 * is provided "as is" without express or implied warranty.
13 *
14 * THE AUTHORS DISCLAIM ALL   WARRANTIES WITH REGARD  TO  THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED   WARRANTIES OF MERCHANTABILITY  AND   FITNESS, IN NO
16 * EVENT  SHALL THE AUTHORS  BE   LIABLE   FOR ANY  SPECIAL, INDIRECT   OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA  OR PROFITS, WHETHER  IN  AN ACTION OF  CONTRACT,  NEGLIGENCE OR OTHER
19 * TORTIOUS  ACTION, ARISING    OUT OF OR   IN  CONNECTION  WITH THE USE    OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 *
22 */
23
24#include "xinput.h"
25#include <string.h>
26
27enum print_format {
28    FORMAT_NONE,
29    FORMAT_SHORT,
30    FORMAT_LONG,
31    FORMAT_NAME,
32    FORMAT_ID,
33};
34
35
36static void
37print_info(Display* dpy, XDeviceInfo	*info, enum print_format format)
38{
39    int			i,j;
40    XAnyClassPtr	any;
41    XKeyInfoPtr		k;
42    XButtonInfoPtr	b;
43    XValuatorInfoPtr	v;
44    XAxisInfoPtr	a;
45
46    if (format == FORMAT_NAME)
47    {
48        printf("%s\n", info->name);
49        return;
50    } else if (format == FORMAT_ID)
51    {
52        printf("%ld\n", info->id);
53        return;
54    }
55
56    printf("\"%s\"\tid=%ld\t[", info->name, info->id);
57
58    switch (info->use) {
59    case IsXPointer:
60       printf("XPointer");
61       break;
62    case IsXKeyboard:
63       printf("XKeyboard");
64       break;
65    case IsXExtensionDevice:
66       printf("XExtensionDevice");
67       break;
68    case IsXExtensionKeyboard:
69       printf("XExtensionKeyboard");
70       break;
71    case IsXExtensionPointer:
72       printf("XExtensionPointer");
73       break;
74    default:
75       printf("Unknown class");
76       break;
77    }
78    printf("]\n");
79
80    if (format == FORMAT_SHORT)
81        return;
82
83    if(info->type != None)
84	printf("\tType is %s\n", XGetAtomName(dpy, info->type));
85
86    if (info->num_classes > 0) {
87	any = (XAnyClassPtr) (info->inputclassinfo);
88	for (i=0; i<info->num_classes; i++) {
89	    switch (any->class) {
90	    case KeyClass:
91		k = (XKeyInfoPtr) any;
92		printf("\tNum_keys is %d\n", k->num_keys);
93		printf("\tMin_keycode is %d\n", k->min_keycode);
94		printf("\tMax_keycode is %d\n", k->max_keycode);
95		break;
96
97	    case ButtonClass:
98		b = (XButtonInfoPtr) any;
99		printf("\tNum_buttons is %d\n", b->num_buttons);
100		break;
101
102	    case ValuatorClass:
103		v = (XValuatorInfoPtr) any;
104		a = (XAxisInfoPtr) ((char *) v +
105				    sizeof (XValuatorInfo));
106		printf("\tNum_axes is %d\n", v->num_axes);
107		printf("\tMode is %s\n", (v->mode == Absolute) ? "Absolute" : "Relative");
108		printf("\tMotion_buffer is %ld\n", v->motion_buffer);
109		for (j=0; j<v->num_axes; j++, a++) {
110		    printf("\tAxis %d :\n", j);
111		    printf("\t\tMin_value is %d\n", a->min_value);
112		    printf("\t\tMax_value is %d\n", a->max_value);
113		    printf ("\t\tResolution is %d\n", a->resolution);
114		}
115		break;
116	    default:
117		printf ("unknown class\n");
118	    }
119	    any = (XAnyClassPtr) ((char *) any + any->length);
120	}
121    }
122}
123
124static int list_xi1(Display     *display,
125                    enum print_format format)
126{
127    XDeviceInfo		*info;
128    int			loop;
129    int                 num_devices;
130
131    info = XListInputDevices(display, &num_devices);
132    for(loop=0; loop<num_devices; loop++) {
133        print_info(display, info+loop, format);
134    }
135    return EXIT_SUCCESS;
136}
137
138#ifdef HAVE_XI2
139/* also used from test_xi2.c */
140void
141print_classes_xi2(Display* display, XIAnyClassInfo **classes,
142                  int num_classes)
143{
144    int i, j;
145
146    printf("\tReporting %d classes:\n", num_classes);
147    for (i = 0; i < num_classes; i++)
148    {
149        printf("\t\tClass originated from: %d. Type: ", classes[i]->sourceid);
150        switch(classes[i]->type)
151        {
152            case XIButtonClass:
153                {
154                    XIButtonClassInfo *b = (XIButtonClassInfo*)classes[i];
155                    char *name;
156                    printf("XIButtonClass\n");
157                    printf("\t\tButtons supported: %d\n", b->num_buttons);
158                    printf("\t\tButton labels:");
159                    for (j = 0; j < b->num_buttons; j++)
160                    {
161                        name = (b->labels[j]) ? XGetAtomName(display, b->labels[j]) : NULL;
162                        if (name)
163                            printf(" \"%s\"", name);
164                        else
165                            printf(" None");
166                        XFree(name);
167                    }
168                    printf("\n");
169                    printf("\t\tButton state:");
170                    for (j = 0; j < b->state.mask_len * 8; j++)
171                        if (XIMaskIsSet(b->state.mask, j))
172                            printf(" %d", j);
173                    printf("\n");
174
175                }
176                break;
177            case XIKeyClass:
178                {
179                    XIKeyClassInfo *k = (XIKeyClassInfo*)classes[i];
180                    printf("XIKeyClass\n");
181                    printf("\t\tKeycodes supported: %d\n", k->num_keycodes);
182                }
183                break;
184            case XIValuatorClass:
185                {
186                    XIValuatorClassInfo *v = (XIValuatorClassInfo*)classes[i];
187                    char *name = v->label ?  XGetAtomName(display, v->label) : NULL;
188
189                    /* Bug in X servers 1.7..1.8.1, mode was | OutOfProximity */
190                    v->mode &= DeviceMode;
191
192                    printf("XIValuatorClass\n");
193                    printf("\t\tDetail for Valuator %d:\n", v->number);
194                    printf("\t\t  Label: %s\n",  (name) ? name : "None");
195                    printf("\t\t  Range: %f - %f\n", v->min, v->max);
196                    printf("\t\t  Resolution: %d units/m\n", v->resolution);
197                    printf("\t\t  Mode: %s\n", v->mode == Absolute ? "absolute" :
198                            "relative");
199                    if (v->mode == Absolute)
200                        printf("\t\t  Current value: %f\n", v->value);
201                    XFree(name);
202                }
203                break;
204#if HAVE_XI21
205            case XIScrollClass:
206                {
207                    XIScrollClassInfo *s = (XIScrollClassInfo*)classes[i];
208
209                    printf("XIScrollClass\n");
210                    printf("\t\tScroll info for Valuator %d\n", s->number);
211                    printf("\t\t  type: %d (%s)\n", s->scroll_type,
212                           (s->scroll_type == XIScrollTypeHorizontal) ? "horizontal" :
213                              (s->scroll_type == XIScrollTypeVertical) ? "vertical" : "unknown");
214                    printf("\t\t  increment: %f\n", s->increment);
215                    printf("\t\t  flags: 0x%x", s->flags);
216                    if (s->flags) {
217                        printf(" (");
218                        if (s->flags & XIScrollFlagNoEmulation)
219                            printf(" no-emulation ");
220                        if (s->flags & XIScrollFlagPreferred)
221                            printf(" preferred ");
222                        printf(")");
223                    }
224                    printf("\n");
225                }
226                break;
227#endif
228#if HAVE_XI22
229            case XITouchClass:
230                {
231                    XITouchClassInfo *t = (XITouchClassInfo*)classes[i];
232
233                    printf("XITouchClass\n");
234                    printf("\t\tTouch mode: %s\n",
235                           (t->mode == XIDirectTouch) ? "direct" : "dependent");
236                    printf("\t\tMax number of touches: %d\n", t->num_touches);
237                }
238#endif
239        }
240    }
241
242    printf("\n");
243}
244
245static void
246print_info_xi2(Display* display, XIDeviceInfo *dev, enum print_format format)
247{
248    if (format == FORMAT_NAME)
249    {
250        printf("%s\n", dev->name);
251        return;
252    } else if (format == FORMAT_ID)
253    {
254        printf("%d\n", dev->deviceid);
255        return;
256    }
257
258    printf("%-40s\tid=%d\t[", dev->name, dev->deviceid);
259    switch(dev->use)
260    {
261        case XIMasterPointer:
262            printf("master pointer  (%d)]\n", dev->attachment);
263            break;
264        case XIMasterKeyboard:
265            printf("master keyboard (%d)]\n", dev->attachment);
266            break;
267        case XISlavePointer:
268            printf("slave  pointer  (%d)]\n", dev->attachment);
269            break;
270        case XISlaveKeyboard:
271            printf("slave  keyboard (%d)]\n", dev->attachment);
272            break;
273        case XIFloatingSlave:
274            printf("floating slave]\n");
275            break;
276    }
277
278    if (format == FORMAT_SHORT)
279        return;
280
281    if (!dev->enabled)
282        printf("\tThis device is disabled\n");
283
284    print_classes_xi2(display, dev->classes, dev->num_classes);
285}
286
287
288static int
289list_xi2(Display *display,
290         enum print_format format)
291{
292    int ndevices;
293    int i, j;
294    XIDeviceInfo *info, *dev;
295
296    info = XIQueryDevice(display, XIAllDevices, &ndevices);
297
298    for(i = 0; i < ndevices; i++)
299    {
300        dev = &info[i];
301        if (dev->use == XIMasterPointer || dev->use == XIMasterKeyboard)
302        {
303            if (format == FORMAT_SHORT || format == FORMAT_LONG)
304            {
305                if (dev->use == XIMasterPointer)
306                    printf("⎡ ");
307                else
308                    printf("⎣ ");
309            }
310
311            print_info_xi2(display, dev, format);
312            for (j = 0; j < ndevices; j++)
313            {
314                XIDeviceInfo* sd = &info[j];
315
316                if ((sd->use == XISlavePointer || sd->use == XISlaveKeyboard) &&
317                     (sd->attachment == dev->deviceid))
318                {
319                    if (format == FORMAT_SHORT || format == FORMAT_LONG)
320                        printf("%s   ↳ ", dev->use == XIMasterPointer ? "⎜" : " ");
321                    print_info_xi2(display, sd, format);
322                }
323            }
324        }
325    }
326
327    for (i = 0; i < ndevices; i++)
328    {
329        dev = &info[i];
330        if (dev->use == XIFloatingSlave)
331        {
332            printf("∼ ");
333            print_info_xi2(display, dev, format);
334        }
335    }
336
337
338    XIFreeDeviceInfo(info);
339    return EXIT_SUCCESS;
340}
341#endif
342
343int
344list(Display	*display,
345     int	argc,
346     char	*argv[],
347     char	*name,
348     char	*desc)
349{
350    enum print_format format = FORMAT_NONE;
351    int arg_dev = 1;
352
353    if (argc >= 1)
354    {
355        if (strcmp(argv[0], "--short") == 0)
356            format = FORMAT_SHORT;
357        else if (strcmp(argv[0], "--long") == 0)
358            format = FORMAT_LONG;
359        else if (strcmp(argv[0], "--name-only") == 0)
360            format = FORMAT_NAME;
361        else if (strcmp(argv[0], "--id-only") == 0)
362            format = FORMAT_ID;
363        else
364            arg_dev--;
365    }
366
367    if (argc > arg_dev)
368    {
369        if (format == FORMAT_NONE)
370            format = FORMAT_LONG;
371#ifdef HAVE_XI2
372        if (xinput_version(display) == XI_2_Major)
373        {
374            XIDeviceInfo *info = xi2_find_device_info(display, argv[arg_dev]);
375
376            if (!info) {
377                fprintf(stderr, "unable to find device %s\n", argv[arg_dev]);
378                return EXIT_FAILURE;
379            } else {
380                print_info_xi2(display, info, format);
381                return EXIT_SUCCESS;
382            }
383        } else
384#endif
385        {
386            XDeviceInfo *info = find_device_info(display, argv[arg_dev], False);
387
388            if (!info) {
389                fprintf(stderr, "unable to find device %s\n", argv[arg_dev]);
390                return EXIT_FAILURE;
391            } else {
392                print_info(display, info, format);
393                return EXIT_SUCCESS;
394            }
395        }
396    } else {
397        if (format == FORMAT_NONE)
398            format = FORMAT_SHORT;
399#ifdef HAVE_XI2
400        if (xinput_version(display) == XI_2_Major)
401            return list_xi2(display, format);
402#endif
403        return list_xi1(display, format);
404    }
405}
406
407/* end of list.c */
408