xinput.c revision e179d2ea
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 <ctype.h> 26#include <string.h> 27 28int xi_opcode; 29 30typedef int (*prog)(Display* display, int argc, char *argv[], 31 char *prog_name, char *prog_desc); 32 33typedef struct 34{ 35 char *func_name; 36 char *arg_desc; 37 prog func; 38} entry; 39 40static entry drivers[] = 41{ 42 {"get-feedbacks", 43 "<device name>", 44 get_feedbacks 45 }, 46 {"set-ptr-feedback", 47 "<device name> <threshold> <num> <denom>", 48 set_ptr_feedback 49 }, 50 {"set-integer-feedback", 51 "<device name> <feedback id> <value>", 52 set_integer_feedback 53 }, 54 {"get-button-map", 55 "<device name>", 56 get_button_map 57 }, 58 {"set-button-map", 59 "<device name> <map button 1> [<map button 2> [...]]", 60 set_button_map 61 }, 62 {"set-pointer", 63 "<device name> [<x index> <y index>]", 64 set_pointer 65 }, 66 {"set-mode", 67 "<device name> ABSOLUTE|RELATIVE", 68 set_mode 69 }, 70 {"list", 71 "[--short || --long] [<device name>...]", 72 list 73 }, 74 {"query-state", 75 "<device name>", 76 query_state 77 }, 78 {"test", 79 "[-proximity] <device name>", 80 test 81 }, 82#if HAVE_XI2 83 { "create-master", 84 "<id> [<sendCore (dflt:1)>] [<enable (dflt:1)>]", 85 create_master 86 }, 87 { "remove-master", 88 "<id> [Floating|AttachToMaster (dflt:Floating)] [<returnPointer>] [<returnKeyboard>]", 89 remove_master 90 }, 91 { "reattach", 92 "<id> <master>", 93 change_attachment 94 }, 95 { "float", 96 "<id>", 97 float_device 98 }, 99 { "set-cp", 100 "<window> <device>", 101 set_clientpointer 102 }, 103 { "test-xi2", 104 "<device>", 105 test_xi2, 106 }, 107#endif 108 { "list-props", 109 "<device> [<device> ...]", 110 list_props 111 }, 112 { "set-int-prop", 113 "<device> <property> <format (8, 16, 32)> <val> [<val> ...]", 114 set_int_prop 115 }, 116 { "set-float-prop", 117 "<device> <property> <val> [<val> ...]", 118 set_float_prop 119 }, 120 { "set-atom-prop", 121 "<device> <property> <val> [<val> ...]", 122 set_atom_prop 123 }, 124 { "watch-props", 125 "<device>", 126 watch_props 127 }, 128 { "delete-prop", 129 "<device> <property>", 130 delete_prop 131 }, 132 { "set-prop", 133 "<device> [--type=atom|float|int] [--format=8|16|32] <property> <val> [<val> ...]", 134 set_prop 135 }, 136 {NULL, NULL, NULL 137 } 138}; 139 140static const char version_id[] = VERSION; 141 142int 143print_version(void) 144{ 145 XExtensionVersion *version; 146 Display *display; 147 148 printf("xinput version %s\n", version_id); 149 150 display = XOpenDisplay(NULL); 151 152 printf("XI version on server: "); 153 154 if (display == NULL) 155 printf("Failed to open display.\n"); 156 else { 157 version = XGetExtensionVersion(display, INAME); 158 if (!version || (version == (XExtensionVersion*) NoSuchExtension)) 159 printf(" Extension not supported.\n"); 160 else { 161 printf("%d.%d\n", version->major_version, 162 version->minor_version); 163 XFree(version); 164 return 0; 165 } 166 } 167 168 return 1; 169} 170 171int 172xinput_version(Display *display) 173{ 174 XExtensionVersion *version; 175 static int vers = -1; 176 177 if (vers != -1) 178 return vers; 179 180 version = XGetExtensionVersion(display, INAME); 181 182 if (version && (version != (XExtensionVersion*) NoSuchExtension)) { 183 vers = version->major_version; 184 XFree(version); 185 } 186 187 return vers; 188} 189 190XDeviceInfo* 191find_device_info(Display *display, 192 char *name, 193 Bool only_extended) 194{ 195 XDeviceInfo *devices; 196 XDeviceInfo *found = NULL; 197 int loop; 198 int num_devices; 199 int len = strlen(name); 200 Bool is_id = True; 201 XID id = (XID)-1; 202 203 for(loop=0; loop<len; loop++) { 204 if (!isdigit(name[loop])) { 205 is_id = False; 206 break; 207 } 208 } 209 210 if (is_id) { 211 id = atoi(name); 212 } 213 214 devices = XListInputDevices(display, &num_devices); 215 216 for(loop=0; loop<num_devices; loop++) { 217 if ((!only_extended || (devices[loop].use >= IsXExtensionDevice)) && 218 ((!is_id && strcmp(devices[loop].name, name) == 0) || 219 (is_id && devices[loop].id == id))) { 220 if (found) { 221 fprintf(stderr, 222 "Warning: There are multiple devices named \"%s\".\n" 223 "To ensure the correct one is selected, please use " 224 "the device ID instead.\n\n", name); 225 return NULL; 226 } else { 227 found = &devices[loop]; 228 } 229 } 230 } 231 return found; 232} 233 234#ifdef HAVE_XI2 235Bool is_pointer(int use) 236{ 237 return use == XIMasterPointer || use == XISlavePointer; 238} 239 240Bool is_keyboard(int use) 241{ 242 return use == XIMasterKeyboard || use == XISlaveKeyboard; 243} 244 245Bool device_matches(XIDeviceInfo *info, char *name) 246{ 247 if (strcmp(info->name, name) == 0) { 248 return True; 249 } 250 251 if (strncmp(name, "pointer:", strlen("pointer:")) == 0 && 252 strcmp(info->name, name + strlen("pointer:")) == 0 && 253 is_pointer(info->use)) { 254 return True; 255 } 256 257 if (strncmp(name, "keyboard:", strlen("keyboard:")) == 0 && 258 strcmp(info->name, name + strlen("keyboard:")) == 0 && 259 is_keyboard(info->use)) { 260 return True; 261 } 262 263 return False; 264} 265 266XIDeviceInfo* 267xi2_find_device_info(Display *display, char *name) 268{ 269 XIDeviceInfo *info; 270 XIDeviceInfo *found = NULL; 271 int ndevices; 272 Bool is_id = True; 273 int i, id = -1; 274 275 for(i = 0; i < strlen(name); i++) { 276 if (!isdigit(name[i])) { 277 is_id = False; 278 break; 279 } 280 } 281 282 if (is_id) { 283 id = atoi(name); 284 } 285 286 info = XIQueryDevice(display, XIAllDevices, &ndevices); 287 for(i = 0; i < ndevices; i++) 288 { 289 if (is_id ? info[i].deviceid == id : device_matches (&info[i], name)) { 290 if (found) { 291 fprintf(stderr, 292 "Warning: There are multiple devices matching '%s'.\n" 293 "To ensure the correct one is selected, please use " 294 "the device ID, or prefix the\ndevice name with " 295 "'pointer:' or 'keyboard:' as appropriate.\n\n", name); 296 XIFreeDeviceInfo(info); 297 return NULL; 298 } else { 299 found = &info[i]; 300 } 301 } 302 } 303 304 return found; 305} 306#endif 307 308static void 309usage(void) 310{ 311 entry *pdriver = drivers; 312 313 fprintf(stderr, "usage :\n"); 314 315 while(pdriver->func_name) { 316 fprintf(stderr, "\txinput %s %s\n", pdriver->func_name, 317 pdriver->arg_desc); 318 pdriver++; 319 } 320} 321 322int 323main(int argc, char * argv[]) 324{ 325 Display *display; 326 entry *driver = drivers; 327 char *func; 328 int event, error; 329 330 if (argc < 2) { 331 usage(); 332 return EXIT_FAILURE; 333 } 334 335 func = argv[1]; 336 while((*func) == '-') func++; 337 338 if (strcmp("version", func) == 0) { 339 return print_version(); 340 } 341 342 display = XOpenDisplay(NULL); 343 344 if (display == NULL) { 345 fprintf(stderr, "Unable to connect to X server\n"); 346 return EXIT_FAILURE; 347 } 348 349 if (!XQueryExtension(display, "XInputExtension", &xi_opcode, &event, &error)) { 350 printf("X Input extension not available.\n"); 351 return EXIT_FAILURE; 352 } 353 354 if (!xinput_version(display)) { 355 fprintf(stderr, "%s extension not available\n", INAME); 356 return EXIT_FAILURE; 357 } 358 359 while(driver->func_name) { 360 if (strcmp(driver->func_name, func) == 0) { 361 int r = (*driver->func)(display, argc-2, argv+2, 362 driver->func_name, driver->arg_desc); 363 XSync(display, False); 364 XCloseDisplay(display); 365 return r; 366 } 367 driver++; 368 } 369 370 usage(); 371 372 return EXIT_FAILURE; 373} 374 375/* end of xinput.c */ 376