initial commit
[profile/ivi/xorg-app-xinput.git] / 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] [<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
140 static const char version_id[] = VERSION;
141
142 int
143 print_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
171 int
172 xinput_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
190 XDeviceInfo*
191 find_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
235 Bool is_pointer(int use)
236 {
237     return use == XIMasterPointer || use == XISlavePointer;
238 }
239
240 Bool is_keyboard(int use)
241 {
242     return use == XIMasterKeyboard || use == XISlaveKeyboard;
243 }
244
245 Bool 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
266 XIDeviceInfo*
267 xi2_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
308 static void
309 usage(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
322 int
323 main(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(argv[0]);
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 */