xinput.c revision b1297603
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  Frederic   Lepied not  be  used  in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific,  written      prior  permission.     Frederic  Lepied   makes  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 * FREDERIC  LEPIED DISCLAIMS ALL   WARRANTIES WITH REGARD  TO  THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED   WARRANTIES OF MERCHANTABILITY  AND   FITNESS, IN NO
16 * EVENT  SHALL FREDERIC  LEPIED 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    {"set-button-map",
57     "<device name> <map button 1> [<map button 2> [...]]",
58     set_button_map
59    },
60    {"set-pointer",
61     "<device name> [<x index> <y index>]",
62     set_pointer
63    },
64    {"set-mode",
65     "<device name> ABSOLUTE|RELATIVE",
66     set_mode
67    },
68    {"list",
69     "[--short || <device name>...]",
70     list
71    },
72    {"query-state",
73     "<device name>",
74     query_state
75    },
76    {"test",
77     "[-proximity] <device name>",
78     test
79    },
80    {"version",
81     "",
82     version
83    },
84    {0, 0, 0
85    }
86};
87
88static Bool
89is_xinput_present(Display	*display)
90{
91    XExtensionVersion	*version;
92    Bool		present;
93
94    version = XGetExtensionVersion(display, INAME);
95
96    if (version && (version != (XExtensionVersion*) NoSuchExtension)) {
97	present = version->present;
98	XFree(version);
99	return present;
100    } else {
101	return False;
102    }
103}
104
105XDeviceInfo*
106find_device_info(Display	*display,
107		 char		*name,
108		 Bool		only_extended)
109{
110    XDeviceInfo	*devices;
111    XDeviceInfo *found = NULL;
112    int		loop;
113    int		num_devices;
114    int		len = strlen(name);
115    Bool	is_id = True;
116    XID		id;
117
118    for(loop=0; loop<len; loop++) {
119	if (!isdigit(name[loop])) {
120	    is_id = False;
121	    break;
122	}
123    }
124
125    if (is_id) {
126	id = atoi(name);
127    }
128
129    devices = XListInputDevices(display, &num_devices);
130
131    for(loop=0; loop<num_devices; loop++) {
132	if ((!only_extended || (devices[loop].use >= IsXExtensionDevice)) &&
133	    ((!is_id && strcmp(devices[loop].name, name) == 0) ||
134	     (is_id && devices[loop].id == id))) {
135	    if (found) {
136	        fprintf(stderr,
137	                "Warning: There are multiple devices named \"%s\".\n"
138	                "To ensure the correct one is selected, please use "
139	                "the device ID instead.\n\n", name);
140	    } else {
141		found = &devices[loop];
142	    }
143	}
144    }
145    return found;
146}
147
148static void
149usage()
150{
151    entry	*pdriver = drivers;
152
153    fprintf(stderr, "usage :\n");
154
155    while(pdriver->func_name) {
156	fprintf(stderr, "\txinput %s %s\n", pdriver->func_name,
157		pdriver->arg_desc);
158	pdriver++;
159    }
160}
161
162int
163main(int argc, char * argv[])
164{
165    Display	*display;
166    entry	*driver = drivers;
167    char        *func;
168
169    if (argc < 2) {
170	usage();
171	return EXIT_FAILURE;
172    }
173
174    display = XOpenDisplay(NULL);
175
176    if (display == NULL) {
177	fprintf(stderr, "Unable to connect to X server\n");
178	return EXIT_FAILURE;
179    }
180
181    func = argv[1];
182    while((*func) == '-') func++;
183
184    if (!is_xinput_present(display)) {
185	fprintf(stderr, "%s extension not available\n", INAME);
186	return EXIT_FAILURE;
187    }
188
189    while(driver->func_name) {
190	if (strcmp(driver->func_name, func) == 0) {
191	    int	r = (*driver->func)(display, argc-2, argv+2,
192				    driver->func_name, driver->arg_desc);
193	    XFlush(display);
194	    return r;
195	}
196	driver++;
197    }
198
199    usage();
200
201    return EXIT_FAILURE;
202}
203
204/* end of xinput.c */
205