Skip to content

Latest commit

 

History

History
331 lines (259 loc) · 8.37 KB

x11_xinput.c

File metadata and controls

331 lines (259 loc) · 8.37 KB
 
Jul 13, 2005
Jul 13, 2005
1
2
3
4
5
6
7
8
/*
* Support for the X11 XInput extension.
*
* Please see the file LICENSE in the source's root directory.
*
* This file written by Ryan C. Gordon.
*/
Mar 24, 2006
Mar 24, 2006
9
10
11
12
13
14
15
16
17
18
19
20
21
#include "manymouse.h"
/* Try to use this on everything but Windows and Mac OS by default... */
#ifndef SUPPORT_XINPUT
#if ( (defined(_WIN32) || defined(__CYGWIN__)) )
#define SUPPORT_XINPUT 0
#elif ( (defined(__MACH__)) && (defined(__APPLE__)) )
#define SUPPORT_XINPUT 0
#else
#define SUPPORT_XINPUT 1
#endif
#endif
Jul 13, 2005
Jul 13, 2005
22
23
#if SUPPORT_XINPUT
Mar 24, 2006
Mar 24, 2006
24
//#error this code is incomplete. Do not use unless you are fixing it.
Jul 13, 2005
Jul 13, 2005
25
26
27
28
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Mar 24, 2006
Mar 24, 2006
29
#include <dlfcn.h>
Jul 13, 2005
Jul 13, 2005
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <X11/extensions/XInput.h>
/* 32 is good enough for now. */
#define MAX_MICE 32
typedef struct
{
XDevice *device;
int min_x;
int min_y;
int max_x;
int max_y;
char name[64];
} MouseStruct;
static MouseStruct mice[MAX_MICE];
static unsigned int available_mice = 0;
static Display *display = NULL;
static XExtensionVersion *extver = NULL;
static XDeviceInfo *device_list = NULL;
static int device_count = 0;
Mar 24, 2006
Mar 24, 2006
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/*
* You _probably_ have Xlib on your system if you're on a Unix box where you
* are planning to plug in multiple mice. That being said, we don't want
* to force a project to add Xlib to their builds, or force the end-user to
* have Xlib installed if they are otherwise running a console app that the
* evdev driver would handle.
*
* We load all Xlib symbols at runtime, and fail gracefully if they aren't
* available for some reason...ManyMouse might be able to use the evdev
* driver or at least return a zero.
*
* On Linux (and probably others), you'll need to add -ldl to your link line,
* but it's part of glibc, so this is pretty much going to be there.
*/
static void *libx11 = NULL;
static void *libxext = NULL;
static void *libxi = NULL;
typedef int (*XExtErrHandler)(Display *, _Xconst char *, _Xconst char *);
static XExtErrHandler (*pXSetExtensionErrorHandler)(XExtErrHandler h) = 0;
static Display* (*pXOpenDisplay)(_Xconst char*) = 0;
static int (*pXCloseDisplay)(Display*) = 0;
static int (*pXFree)(void*) = 0;
static XExtensionVersion* (*pXGetExtensionVersion)(Display*,_Xconst char*) = 0;
static XDeviceInfo* (*pXListInputDevices)(Display*,int*) = 0;
static void (*pXFreeDeviceList)(XDeviceInfo*) = 0;
static XDevice* (*pXOpenDevice)(Display*,XID) = 0;
static int (*pXCloseDevice)(Display*,XDevice*) = 0;
static int symlookup(void *dll, void **addr, const char *sym)
{
*addr = dlsym(dll, sym);
if (*addr == NULL)
return(0);
return(1);
} /* symlookup */
static int find_api_symbols(void)
{
void *dll = NULL;
#define LOOKUP(x) { if (!symlookup(dll, (void **) &p##x, #x)) return(0); }
dll = libx11 = dlopen("libX11.so.6", RTLD_GLOBAL | RTLD_LAZY);
if (dll == NULL)
return(0);
LOOKUP(XOpenDisplay);
LOOKUP(XCloseDisplay);
LOOKUP(XFree);
dll = libxext = dlopen("libXext.so.6", RTLD_GLOBAL | RTLD_LAZY);
if (dll == NULL)
return(0);
LOOKUP(XSetExtensionErrorHandler);
dll = libxi = dlopen("libXi.so.6", RTLD_GLOBAL | RTLD_LAZY);
if (dll == NULL)
return(0);
LOOKUP(XGetExtensionVersion);
LOOKUP(XListInputDevices);
LOOKUP(XFreeDeviceList);
LOOKUP(XOpenDevice);
LOOKUP(XCloseDevice);
#undef LOOKUP
return(1);
} /* find_api_symbols */
Jul 13, 2005
Jul 13, 2005
125
126
127
128
129
130
131
132
133
static void xinput_cleanup(void)
{
int i;
if (display != NULL)
{
for (i = 0; i < available_mice; i++)
{
if (mice[i].device)
Mar 24, 2006
Mar 24, 2006
134
pXCloseDevice(display, mice[i].device);
Jul 13, 2005
Jul 13, 2005
135
136
137
138
139
} /* for */
} /* if */
if (extver != NULL)
{
Mar 24, 2006
Mar 24, 2006
140
pXFree(extver);
Jul 13, 2005
Jul 13, 2005
141
142
143
144
145
extver = NULL;
} /* if */
if (device_list != NULL)
{
Mar 24, 2006
Mar 24, 2006
146
pXFreeDeviceList(device_list);
Jul 13, 2005
Jul 13, 2005
147
148
149
150
151
device_list = NULL;
} /* if */
if (display != NULL)
{
Mar 24, 2006
Mar 24, 2006
152
pXCloseDisplay(display);
Jul 13, 2005
Jul 13, 2005
153
154
155
156
157
display = NULL;
} /* if */
memset(mice, '\0', sizeof (mice));
available_mice = 0;
Mar 24, 2006
Mar 24, 2006
158
159
160
161
162
163
#define LIBCLOSE(lib) { if (lib != NULL) { dlclose(lib); lib = NULL; } }
LIBCLOSE(libxi);
LIBCLOSE(libxext);
LIBCLOSE(libx11);
#undef LIBCLOSE
Jul 13, 2005
Jul 13, 2005
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
} /* xinput_cleanup */
/* Just in case this is compiled as a C++ module... */
static XID get_x11_any_class(const XAnyClassPtr anyclass)
{
#if defined(__cplusplus) || defined(c_plusplus)
return anyclass->c_class;
#else
return anyclass->class;
#endif
} /* get_x11_any_class */
static int init_mouse(MouseStruct *mouse, const XDeviceInfo *devinfo)
{
int i;
int has_axes = 0;
int has_buttons = 0;
XAnyClassPtr any = devinfo->inputclassinfo;
Mar 24, 2006
Mar 24, 2006
185
186
187
188
189
190
if (devinfo->use == IsXPointer)
return(0); /* sucks! Can't open a mouse that is the system pointer! */
if (devinfo->use == IsXKeyboard)
return(0); /* definitely not a mouse. :) */
Jul 13, 2005
Jul 13, 2005
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
for (i = 0; i < devinfo->num_classes; i++)
{
XID cls = get_x11_any_class(any);
if (cls == KeyClass)
return(0); /* a keyboard? */
else if (cls == ButtonClass)
{
const XButtonInfo *info = (const XButtonInfo *) any;
if (info->num_buttons > 0)
has_buttons = 1;
} /* else if */
else if (cls == ValuatorClass)
{
const XValuatorInfo *info = (const XValuatorInfo *) any;
Mar 24, 2006
Mar 24, 2006
208
if (info->num_axes != 2) /* joystick? */ /* !!! FIXME: this isn't right! */
Jul 13, 2005
Jul 13, 2005
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
return 0;
has_axes = 1;
mouse->min_x = info->axes[0].min_value;
mouse->max_x = info->axes[0].max_value;
mouse->min_y = info->axes[1].min_value;
mouse->max_y = info->axes[1].max_value;
} /* else if */
any = (XAnyClassPtr) ((char *) any + any->length);
} /* for */
if ((!has_axes) || (!has_buttons))
return(0); /* probably not a mouse. */
Mar 24, 2006
Mar 24, 2006
224
mouse->device = pXOpenDevice(display, devinfo->id);
Jul 13, 2005
Jul 13, 2005
225
226
227
228
229
230
231
232
233
if (mouse->device == NULL)
return(0);
strncpy(mouse->name, devinfo->name, sizeof (mouse->name));
mouse->name[sizeof (mouse->name) - 1] = '\0';
return(1);
} /* init_mouse */
Mar 24, 2006
Mar 24, 2006
234
235
236
237
238
239
240
241
242
243
244
245
static int (*Xext_handler)(Display *, _Xconst char *, _Xconst char *) = NULL;
static int xext_errhandler(Display *d, _Xconst char *ext, _Xconst char *reason)
{
/* Don't do anything (write an error to stderr) if extension is missing */
if (strcmp(reason, "missing") == 0)
return 0;
return Xext_handler(d, ext, reason);
}
static int x11_xinput_init_internal(void)
Jul 13, 2005
Jul 13, 2005
246
247
248
249
250
{
int i;
xinput_cleanup(); /* just in case... */
Mar 24, 2006
Mar 24, 2006
251
252
253
254
255
256
257
if (getenv("MANYMOUSE_NO_XINPUT") != NULL)
return(-1);
if (!find_api_symbols())
return(-1); /* couldn't find all needed symbols. */
display = pXOpenDisplay(NULL);
Jul 13, 2005
Jul 13, 2005
258
if (display == NULL)
Mar 24, 2006
Mar 24, 2006
259
260
261
262
263
264
265
return(-1); /* no X server at all */
/* Stop stderr output in case XInput extension is missing... */
Xext_handler = pXSetExtensionErrorHandler(xext_errhandler);
extver = pXGetExtensionVersion(display, INAME);
pXSetExtensionErrorHandler(Xext_handler);
Xext_handler = NULL;
Jul 13, 2005
Jul 13, 2005
266
267
if ((extver == NULL) || (extver == (XExtensionVersion *) NoSuchExtension))
Mar 24, 2006
Mar 24, 2006
268
return(-1); /* no such extension */
Jul 13, 2005
Jul 13, 2005
269
270
if (extver->present == XI_Absent)
Mar 24, 2006
Mar 24, 2006
271
return(-1); /* extension not available. */
Jul 13, 2005
Jul 13, 2005
272
Mar 24, 2006
Mar 24, 2006
273
device_list = pXListInputDevices(display, &device_count);
Jul 13, 2005
Jul 13, 2005
274
if (device_list == NULL)
Mar 24, 2006
Mar 24, 2006
275
return(-1);
Jul 13, 2005
Jul 13, 2005
276
277
278
279
280
281
282
283
284
for (i = 0; i < device_count; i++)
{
MouseStruct *mouse = &mice[available_mice];
if (init_mouse(mouse, &device_list[i]))
available_mice++;
} /* for */
return(available_mice);
Mar 24, 2006
Mar 24, 2006
285
} /* x11_xinput_init_internal */
Jul 13, 2005
Jul 13, 2005
286
Mar 24, 2006
Mar 24, 2006
287
288
289
290
291
292
293
static int x11_xinput_init(void)
{
int retval = x11_xinput_init_internal();
if (retval < 0)
xinput_cleanup();
return(retval);
Jul 13, 2005
Jul 13, 2005
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
} /* x11_xinput_init */
static void x11_xinput_quit(void)
{
xinput_cleanup();
} /* x11_xinput_quit */
static const char *x11_xinput_name(unsigned int index)
{
if (index < available_mice)
return(mice[index].name);
return(NULL);
} /* x11_xinput_name */
static int x11_xinput_poll(ManyMouseEvent *event)
{
return(0); /* !!! FIXME */
} /* x11_xinput_poll */
Jul 27, 2007
Jul 27, 2007
316
static const ManyMouseDriver ManyMouseDriver_interface =
Jul 13, 2005
Jul 13, 2005
317
318
319
320
321
322
323
{
x11_xinput_init,
x11_xinput_quit,
x11_xinput_name,
x11_xinput_poll
};
Jul 27, 2007
Jul 27, 2007
324
325
326
327
328
329
const ManyMouseDriver *ManyMouseDriver_xinput = &ManyMouseDriver_interface;
#else
const ManyMouseDriver *ManyMouseDriver_xinput = 0;
#endif /* SUPPORT_XINPUT blocker */
Jul 13, 2005
Jul 13, 2005
330
/* end of x11_xinput.c ... */