xinput.c revision d3263506
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
28typedef int (*prog)(
29#if NeedFunctionPrototypes
30		    Display* display, int argc, char *argv[],
31		    char *prog_name, char *prog_desc
32#endif
33);
34
35typedef struct
36{
37    char	*func_name;
38    char	*arg_desc;
39    prog	func;
40} entry;
41
42static entry drivers[] =
43{
44    {"get-feedbacks",
45     "<device name>",
46     get_feedbacks
47    },
48    {"set-ptr-feedback",
49     "<device name> <threshold> <num> <denom>",
50     set_ptr_feedback
51    },
52    {"set-integer-feedback",
53     "<device name> <feedback id> <value>",
54     set_integer_feedback
55    },
56    {"get-button-map",
57     "<device name>",
58     get_button_map
59    },
60    {"set-button-map",
61     "<device name> <map button 1> [<map button 2> [...]]",
62     set_button_map
63    },
64    {"set-pointer",
65     "<device name> [<x index> <y index>]",
66     set_pointer
67    },
68    {"set-mode",
69     "<device name> ABSOLUTE|RELATIVE",
70     set_mode
71    },
72    {"list",
73     "[--loop || --short || <device name>...]",
74     list
75    },
76    {"query-state",
77     "<device name>",
78     query_state
79    },
80    {"test",
81     "[-proximity] <device name>",
82     test
83    },
84    {"version",
85     "",
86     version
87    },
88#if HAVE_XI2
89    { "create-master",
90      "<id> [sendCore (dflt:1)] [enable (dflt:1)]",
91      create_master
92    },
93    { "remove-master",
94      "<id> [returnMode (dflt:Floating)] [returnPointer] [returnKeyboard]",
95      remove_master
96    },
97    { "reattach",
98      "<id> <master>",
99      change_attachment
100    },
101    { "float",
102      "<id>",
103      float_device
104    },
105    { "set-cp",
106      "<window> <device>",
107      set_clientpointer
108    },
109#endif
110    { "list-props",
111      "<device> [<device> ...]",
112      list_props
113    },
114    { "set-int-prop",
115      "<device> <property> <format (8, 16, 32)> <val> [<val> ...]",
116      set_int_prop
117    },
118    { "set-float-prop",
119      "<device> <property> <val> [<val> ...]",
120      set_float_prop
121    },
122    { "set-atom-prop",
123      "<device> <property> <val> [<val> ...]",
124      set_atom_prop
125    },
126    { "watch-props",
127      "<device>",
128      watch_props
129    },
130    { "delete-prop",
131      "<device> <property>",
132      delete_prop
133    },
134    {NULL, NULL, NULL
135    }
136};
137
138static Bool
139is_xinput_present(Display	*display)
140{
141    XExtensionVersion	*version;
142    Bool		present;
143
144#if HAVE_XI2
145    version = XQueryInputVersion(display, XI_2_Major, XI_2_Minor);
146#else
147    version = XGetExtensionVersion(display, INAME);
148#endif
149
150    if (version && (version != (XExtensionVersion*) NoSuchExtension)) {
151	present = version->present;
152	XFree(version);
153	return present;
154    } else {
155	return False;
156    }
157}
158
159XDeviceInfo*
160find_device_info(Display	*display,
161		 char		*name,
162		 Bool		only_extended)
163{
164    XDeviceInfo	*devices;
165    XDeviceInfo *found = NULL;
166    int		loop;
167    int		num_devices;
168    int		len = strlen(name);
169    Bool	is_id = True;
170    XID		id = (XID)-1;
171
172    for(loop=0; loop<len; loop++) {
173	if (!isdigit(name[loop])) {
174	    is_id = False;
175	    break;
176	}
177    }
178
179    if (is_id) {
180	id = atoi(name);
181    }
182
183    devices = XListInputDevices(display, &num_devices);
184
185    for(loop=0; loop<num_devices; loop++) {
186	if ((!only_extended || (devices[loop].use >= IsXExtensionDevice)) &&
187	    ((!is_id && strcmp(devices[loop].name, name) == 0) ||
188	     (is_id && devices[loop].id == id))) {
189	    if (found) {
190	        fprintf(stderr,
191	                "Warning: There are multiple devices named \"%s\".\n"
192	                "To ensure the correct one is selected, please use "
193	                "the device ID instead.\n\n", name);
194		return NULL;
195	    } else {
196		found = &devices[loop];
197	    }
198	}
199    }
200    return found;
201}
202
203static void
204usage(void)
205{
206    entry	*pdriver = drivers;
207
208    fprintf(stderr, "usage :\n");
209
210    while(pdriver->func_name) {
211	fprintf(stderr, "\txinput %s %s\n", pdriver->func_name,
212		pdriver->arg_desc);
213	pdriver++;
214    }
215}
216
217int
218main(int argc, char * argv[])
219{
220    Display	*display;
221    entry	*driver = drivers;
222    char        *func;
223
224    if (argc < 2) {
225	usage();
226	return EXIT_FAILURE;
227    }
228
229    display = XOpenDisplay(NULL);
230
231    if (display == NULL) {
232	fprintf(stderr, "Unable to connect to X server\n");
233	return EXIT_FAILURE;
234    }
235
236    func = argv[1];
237    while((*func) == '-') func++;
238
239    if (!is_xinput_present(display)) {
240	fprintf(stderr, "%s extension not available\n", INAME);
241	return EXIT_FAILURE;
242    }
243
244    while(driver->func_name) {
245	if (strcmp(driver->func_name, func) == 0) {
246	    int	r = (*driver->func)(display, argc-2, argv+2,
247				    driver->func_name, driver->arg_desc);
248	    XSync(display, False);
249	    XCloseDisplay(display);
250	    return r;
251	}
252	driver++;
253    }
254
255    usage();
256
257    return EXIT_FAILURE;
258}
259
260/* end of xinput.c */
261