Tizen 2.0 Release
[framework/uifw/xorg/util/x11-xserver-utils.git] / xinput / src / xinput.c
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
28 int xi_opcode;
29
30 typedef int (*prog)(Display* display, int argc, char *argv[],
31                     char *prog_name, char *prog_desc);
32
33 typedef struct
34 {
35     char        *func_name;
36     char        *arg_desc;
37     prog        func;
38 } entry;
39
40 static 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 || --name-only || --id-only] [<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     { "map-to-output",
108       "<device> <output name>",
109       map_to_output,
110     },
111 #endif
112     { "list-props",
113       "<device> [<device> ...]",
114       list_props
115     },
116     { "set-int-prop",
117       "<device> <property> <format (8, 16, 32)> <val> [<val> ...]",
118       set_int_prop
119     },
120     { "set-float-prop",
121       "<device> <property> <val> [<val> ...]",
122       set_float_prop
123     },
124     { "set-atom-prop",
125       "<device> <property> <val> [<val> ...]",
126       set_atom_prop
127     },
128     { "watch-props",
129       "<device>",
130       watch_props
131     },
132     { "delete-prop",
133       "<device> <property>",
134       delete_prop
135     },
136     { "set-prop",
137       "<device> [--type=atom|float|int] [--format=8|16|32] <property> <val> [<val> ...]",
138       set_prop
139     },
140     {
141       "disable",
142       "<device>",
143       disable,
144     },
145     {
146       "enable",
147       "<device>",
148       enable,
149     },
150     {NULL, NULL, NULL
151     }
152 };
153
154 static const char version_id[] = VERSION;
155
156 static int
157 print_version(void)
158 {
159     XExtensionVersion   *version;
160     Display *display;
161
162     printf("xinput version %s\n", version_id);
163
164     display = XOpenDisplay(NULL);
165
166     printf("XI version on server: ");
167
168     if (display == NULL)
169         printf("Failed to open display.\n");
170     else {
171         version = XGetExtensionVersion(display, INAME);
172         if (!version || (version == (XExtensionVersion*) NoSuchExtension))
173             printf(" Extension not supported.\n");
174         else {
175             printf("%d.%d\n", version->major_version,
176                     version->minor_version);
177             XFree(version);
178             return 0;
179         }
180     }
181
182     return 1;
183 }
184
185 int
186 xinput_version(Display  *display)
187 {
188     XExtensionVersion   *version;
189     static int vers = -1;
190
191     if (vers != -1)
192         return vers;
193
194     version = XGetExtensionVersion(display, INAME);
195
196     if (version && (version != (XExtensionVersion*) NoSuchExtension)) {
197         vers = version->major_version;
198         XFree(version);
199     }
200
201 #if HAVE_XI2
202     /* Announce our supported version so the server treats us correctly. */
203     if (vers >= XI_2_Major)
204     {
205         int maj = 2,
206             min = 0;
207
208 #if HAVE_XI21
209         min = 1;
210 #elif HAVE_XI22
211         min = 2;
212 #endif
213
214         XIQueryVersion(display, &maj, &min);
215     }
216 #endif
217
218     return vers;
219 }
220
221 XDeviceInfo*
222 find_device_info(Display        *display,
223                  char           *name,
224                  Bool           only_extended)
225 {
226     XDeviceInfo *devices;
227     XDeviceInfo *found = NULL;
228     int         loop;
229     int         num_devices;
230     int         len = strlen(name);
231     Bool        is_id = True;
232     XID         id = (XID)-1;
233
234     for(loop=0; loop<len; loop++) {
235         if (!isdigit(name[loop])) {
236             is_id = False;
237             break;
238         }
239     }
240
241     if (is_id) {
242         id = atoi(name);
243     }
244
245     devices = XListInputDevices(display, &num_devices);
246
247     for(loop=0; loop<num_devices; loop++) {
248         if ((!only_extended || (devices[loop].use >= IsXExtensionDevice)) &&
249             ((!is_id && strcmp(devices[loop].name, name) == 0) ||
250              (is_id && devices[loop].id == id))) {
251             if (found) {
252                 fprintf(stderr,
253                         "Warning: There are multiple devices named '%s'.\n"
254                         "To ensure the correct one is selected, please use "
255                         "the device ID instead.\n\n", name);
256                 return NULL;
257             } else {
258                 found = &devices[loop];
259             }
260         }
261     }
262     return found;
263 }
264
265 #ifdef HAVE_XI2
266 Bool is_pointer(int use)
267 {
268     return use == XIMasterPointer || use == XISlavePointer;
269 }
270
271 Bool is_keyboard(int use)
272 {
273     return use == XIMasterKeyboard || use == XISlaveKeyboard;
274 }
275
276 Bool device_matches(XIDeviceInfo *info, char *name)
277 {
278     if (strcmp(info->name, name) == 0) {
279         return True;
280     }
281
282     if (strncmp(name, "pointer:", strlen("pointer:")) == 0 &&
283         strcmp(info->name, name + strlen("pointer:")) == 0 &&
284         is_pointer(info->use)) {
285         return True;
286     }
287
288     if (strncmp(name, "keyboard:", strlen("keyboard:")) == 0 &&
289         strcmp(info->name, name + strlen("keyboard:")) == 0 &&
290         is_keyboard(info->use)) {
291         return True;
292     }
293
294     return False;
295 }
296
297 XIDeviceInfo*
298 xi2_find_device_info(Display *display, char *name)
299 {
300     XIDeviceInfo *info;
301     XIDeviceInfo *found = NULL;
302     int ndevices;
303     Bool is_id = True;
304     int i, id = -1;
305
306     for(i = 0; i < strlen(name); i++) {
307         if (!isdigit(name[i])) {
308             is_id = False;
309             break;
310         }
311     }
312
313     if (is_id) {
314         id = atoi(name);
315     }
316
317     info = XIQueryDevice(display, XIAllDevices, &ndevices);
318     for(i = 0; i < ndevices; i++)
319     {
320         if (is_id ? info[i].deviceid == id : device_matches (&info[i], name)) {
321             if (found) {
322                 fprintf(stderr,
323                         "Warning: There are multiple devices matching '%s'.\n"
324                         "To ensure the correct one is selected, please use "
325                         "the device ID, or prefix the\ndevice name with "
326                         "'pointer:' or 'keyboard:' as appropriate.\n\n", name);
327                 XIFreeDeviceInfo(info);
328                 return NULL;
329             } else {
330                 found = &info[i];
331             }
332         }
333     }
334
335     return found;
336 }
337 #endif
338
339 static void
340 usage(void)
341 {
342     entry       *pdriver = drivers;
343
344     fprintf(stderr, "usage :\n");
345
346     while(pdriver->func_name) {
347         fprintf(stderr, "\txinput %s %s\n", pdriver->func_name,
348                 pdriver->arg_desc);
349         pdriver++;
350     }
351 }
352
353 int
354 main(int argc, char * argv[])
355 {
356     Display     *display;
357     entry       *driver = drivers;
358     char        *func;
359     int event, error;
360
361     if (argc > 1) {
362         func = argv[1];
363         while(func[0] == '-') func++;
364     } else {
365         func = "list";
366     }
367
368     if (strcmp("version", func) == 0) {
369         return print_version();
370     }
371
372     if (strcmp("help", func) == 0) {
373         usage();
374         return 0;
375     }
376
377     display = XOpenDisplay(NULL);
378
379     if (display == NULL) {
380         fprintf(stderr, "Unable to connect to X server\n");
381         goto out;
382     }
383
384     if (!XQueryExtension(display, "XInputExtension", &xi_opcode, &event, &error)) {
385         printf("X Input extension not available.\n");
386         goto out;
387     }
388
389     if (!xinput_version(display)) {
390         fprintf(stderr, "%s extension not available\n", INAME);
391         goto out;
392     }
393
394     while(driver->func_name) {
395         if (strcmp(driver->func_name, func) == 0) {
396             int r = (*driver->func)(display, argc-2, argv+2,
397                                     driver->func_name, driver->arg_desc);
398             XSync(display, False);
399             XCloseDisplay(display);
400             return r;
401         }
402         driver++;
403     }
404
405     usage();
406
407 out:
408     if (display)
409         XCloseDisplay(display);
410     return EXIT_FAILURE;
411 }
412
413 /* end of xinput.c */