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