xinput.c revision 53719b08
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() 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 235XIDeviceInfo* 236xi2_find_device_info(Display *display, char *name) 237{ 238 XIDeviceInfo *info; 239 int ndevices; 240 Bool is_id = True; 241 int i, id = -1; 242 243 for(i = 0; i < strlen(name); i++) { 244 if (!isdigit(name[i])) { 245 is_id = False; 246 break; 247 } 248 } 249 250 if (is_id) { 251 id = atoi(name); 252 } 253 254 info = XIQueryDevice(display, XIAllDevices, &ndevices); 255 for(i = 0; i < ndevices; i++) 256 { 257 if ((is_id && info[i].deviceid == id) || 258 (!is_id && strcmp(info[i].name, name) == 0)) 259 { 260 return &info[i]; 261 } 262 } 263 264 XIFreeDeviceInfo(info); 265 return NULL; 266} 267#endif 268 269static void 270usage(void) 271{ 272 entry *pdriver = drivers; 273 274 fprintf(stderr, "usage :\n"); 275 276 while(pdriver->func_name) { 277 fprintf(stderr, "\txinput %s %s\n", pdriver->func_name, 278 pdriver->arg_desc); 279 pdriver++; 280 } 281} 282 283int 284main(int argc, char * argv[]) 285{ 286 Display *display; 287 entry *driver = drivers; 288 char *func; 289 int event, error; 290 291 if (argc < 2) { 292 usage(); 293 return EXIT_FAILURE; 294 } 295 296 func = argv[1]; 297 while((*func) == '-') func++; 298 299 if (strcmp("version", func) == 0) { 300 return print_version(argv[0]); 301 } 302 303 display = XOpenDisplay(NULL); 304 305 if (display == NULL) { 306 fprintf(stderr, "Unable to connect to X server\n"); 307 return EXIT_FAILURE; 308 } 309 310 if (!XQueryExtension(display, "XInputExtension", &xi_opcode, &event, &error)) { 311 printf("X Input extension not available.\n"); 312 return EXIT_FAILURE; 313 } 314 315 if (!xinput_version(display)) { 316 fprintf(stderr, "%s extension not available\n", INAME); 317 return EXIT_FAILURE; 318 } 319 320 while(driver->func_name) { 321 if (strcmp(driver->func_name, func) == 0) { 322 int r = (*driver->func)(display, argc-2, argv+2, 323 driver->func_name, driver->arg_desc); 324 XSync(display, False); 325 XCloseDisplay(display); 326 return r; 327 } 328 driver++; 329 } 330 331 usage(); 332 333 return EXIT_FAILURE; 334} 335 336/* end of xinput.c */ 337