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