File: | hw/kdrive/src/kinput.c |
Location: | line 1328, column 5 |
Description: | Potential leak of memory pointed to by 'ki' |
1 | /* | |||
2 | * Copyright © 1999 Keith Packard | |||
3 | * Copyright © 2006 Nokia Corporation | |||
4 | * | |||
5 | * Permission to use, copy, modify, distribute, and sell this software and its | |||
6 | * documentation for any purpose is hereby granted without fee, provided that | |||
7 | * the above copyright notice appear in all copies and that both that | |||
8 | * copyright notice and this permission notice appear in supporting | |||
9 | * documentation, and that the name of the authors not be used in | |||
10 | * advertising or publicity pertaining to distribution of the software without | |||
11 | * specific, written prior permission. The authors make no | |||
12 | * representations about the suitability of this software for any purpose. It | |||
13 | * is provided "as is" without express or implied warranty. | |||
14 | * | |||
15 | * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | |||
16 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | |||
17 | * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR | |||
18 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | |||
19 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||
20 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | |||
21 | * PERFORMANCE OF THIS SOFTWARE. | |||
22 | */ | |||
23 | ||||
24 | #ifdef HAVE_CONFIG_H1 | |||
25 | #include <kdrive-config.h> | |||
26 | #endif | |||
27 | #include "kdrive.h" | |||
28 | #include "inputstr.h" | |||
29 | ||||
30 | #define XK_PUBLISHING | |||
31 | #include <X11/keysym.h> | |||
32 | #if HAVE_X11_XF86KEYSYM_H | |||
33 | #include <X11/XF86keysym.h> | |||
34 | #endif | |||
35 | #include <signal.h> | |||
36 | #include <stdio.h> | |||
37 | #ifdef __sun | |||
38 | #include <sys/file.h> /* needed for FNONBLOCK & FASYNC */ | |||
39 | #endif | |||
40 | ||||
41 | #include "xkbsrv.h" | |||
42 | ||||
43 | #include <X11/extensions/XI.h> | |||
44 | #include <X11/extensions/XIproto.h> | |||
45 | #include "XIstubs.h" /* even though we don't use stubs. cute, no? */ | |||
46 | #include "exevents.h" | |||
47 | #include "extinit.h" | |||
48 | #include "exglobals.h" | |||
49 | #include "eventstr.h" | |||
50 | #include "xserver-properties.h" | |||
51 | #include "inpututils.h" | |||
52 | #include "optionstr.h" | |||
53 | ||||
54 | #if defined(CONFIG_UDEV) || defined(CONFIG_HAL) | |||
55 | #include <hotplug.h> | |||
56 | #endif | |||
57 | ||||
58 | #ifdef KDRIVE_EVDEV | |||
59 | #define DEV_INPUT_EVENT_PREFIX "/dev/input/event" | |||
60 | #define DEV_INPUT_EVENT_PREFIX_LEN (sizeof(DEV_INPUT_EVENT_PREFIX) - 1) | |||
61 | #endif | |||
62 | ||||
63 | #define AtomFromName(x)MakeAtom(x, strlen(x), 1) MakeAtom(x, strlen(x), 1) | |||
64 | ||||
65 | struct KdConfigDevice { | |||
66 | char *line; | |||
67 | struct KdConfigDevice *next; | |||
68 | }; | |||
69 | ||||
70 | /* kdKeyboards and kdPointers hold all the real devices. */ | |||
71 | static KdKeyboardInfo *kdKeyboards = NULL((void*)0); | |||
72 | static KdPointerInfo *kdPointers = NULL((void*)0); | |||
73 | static struct KdConfigDevice *kdConfigKeyboards = NULL((void*)0); | |||
74 | static struct KdConfigDevice *kdConfigPointers = NULL((void*)0); | |||
75 | ||||
76 | static KdKeyboardDriver *kdKeyboardDrivers = NULL((void*)0); | |||
77 | static KdPointerDriver *kdPointerDrivers = NULL((void*)0); | |||
78 | ||||
79 | static Bool kdInputEnabled; | |||
80 | static Bool kdOffScreen; | |||
81 | static unsigned long kdOffScreenTime; | |||
82 | ||||
83 | static KdPointerMatrix kdPointerMatrix = { | |||
84 | {{1, 0, 0}, | |||
85 | {0, 1, 0}} | |||
86 | }; | |||
87 | ||||
88 | void KdResetInputMachine(void); | |||
89 | ||||
90 | #define KD_MAX_INPUT_FDS8 8 | |||
91 | ||||
92 | typedef struct _kdInputFd { | |||
93 | int fd; | |||
94 | void (*read) (int fd, void *closure); | |||
95 | int (*enable) (int fd, void *closure); | |||
96 | void (*disable) (int fd, void *closure); | |||
97 | void *closure; | |||
98 | } KdInputFd; | |||
99 | ||||
100 | static KdInputFd kdInputFds[KD_MAX_INPUT_FDS8]; | |||
101 | static int kdNumInputFds; | |||
102 | ||||
103 | extern Bool kdRawPointerCoordinates; | |||
104 | ||||
105 | extern const char *kdGlobalXkbRules; | |||
106 | extern const char *kdGlobalXkbModel; | |||
107 | extern const char *kdGlobalXkbLayout; | |||
108 | extern const char *kdGlobalXkbVariant; | |||
109 | extern const char *kdGlobalXkbOptions; | |||
110 | ||||
111 | #ifdef FNONBLOCK0x0004 | |||
112 | #define NOBLOCK0x0004 FNONBLOCK0x0004 | |||
113 | #else | |||
114 | #define NOBLOCK0x0004 FNDELAY0x0004 | |||
115 | #endif | |||
116 | ||||
117 | void | |||
118 | KdResetInputMachine(void) | |||
119 | { | |||
120 | KdPointerInfo *pi; | |||
121 | ||||
122 | for (pi = kdPointers; pi; pi = pi->next) { | |||
123 | pi->mouseState = start; | |||
124 | pi->eventHeld = FALSE0; | |||
125 | } | |||
126 | } | |||
127 | ||||
128 | static void | |||
129 | KdNonBlockFd(int fd) | |||
130 | { | |||
131 | int flags; | |||
132 | ||||
133 | flags = fcntl(fd, F_GETFL3); | |||
134 | flags |= FASYNC0x0040 | NOBLOCK0x0004; | |||
135 | fcntl(fd, F_SETFL4, flags); | |||
136 | } | |||
137 | ||||
138 | static void | |||
139 | KdNotifyFd(int fd, int ready, void *data) | |||
140 | { | |||
141 | int i = (int) (intptr_t) data; | |||
142 | (*kdInputFds[i].read)(fd, kdInputFds[i].closure); | |||
143 | } | |||
144 | ||||
145 | static void | |||
146 | KdAddFd(int fd, int i) | |||
147 | { | |||
148 | KdNonBlockFd(fd); | |||
149 | InputThreadRegisterDev(fd, KdNotifyFd, (void *) (intptr_t) i); | |||
150 | } | |||
151 | ||||
152 | static void | |||
153 | KdRemoveFd(int fd) | |||
154 | { | |||
155 | int flags; | |||
156 | ||||
157 | InputThreadUnregisterDev(fd); | |||
158 | flags = fcntl(fd, F_GETFL3); | |||
159 | flags &= ~(FASYNC0x0040 | NOBLOCK0x0004); | |||
160 | fcntl(fd, F_SETFL4, flags); | |||
161 | } | |||
162 | ||||
163 | Bool | |||
164 | KdRegisterFd(int fd, void (*read) (int fd, void *closure), void *closure) | |||
165 | { | |||
166 | if (kdNumInputFds == KD_MAX_INPUT_FDS8) | |||
167 | return FALSE0; | |||
168 | kdInputFds[kdNumInputFds].fd = fd; | |||
169 | kdInputFds[kdNumInputFds].read = read; | |||
170 | kdInputFds[kdNumInputFds].enable = 0; | |||
171 | kdInputFds[kdNumInputFds].disable = 0; | |||
172 | kdInputFds[kdNumInputFds].closure = closure; | |||
173 | if (kdInputEnabled) | |||
174 | KdAddFd(fd, kdNumInputFds); | |||
175 | kdNumInputFds++; | |||
176 | return TRUE1; | |||
177 | } | |||
178 | ||||
179 | void | |||
180 | KdUnregisterFd(void *closure, int fd, Bool do_close) | |||
181 | { | |||
182 | int i, j; | |||
183 | ||||
184 | for (i = 0; i < kdNumInputFds; i++) { | |||
185 | if (kdInputFds[i].closure == closure && | |||
186 | (fd == -1 || kdInputFds[i].fd == fd)) { | |||
187 | if (kdInputEnabled) | |||
188 | KdRemoveFd(kdInputFds[i].fd); | |||
189 | if (do_close) | |||
190 | close(kdInputFds[i].fd); | |||
191 | for (j = i; j < (kdNumInputFds - 1); j++) | |||
192 | kdInputFds[j] = kdInputFds[j + 1]; | |||
193 | kdNumInputFds--; | |||
194 | break; | |||
195 | } | |||
196 | } | |||
197 | } | |||
198 | ||||
199 | void | |||
200 | KdUnregisterFds(void *closure, Bool do_close) | |||
201 | { | |||
202 | KdUnregisterFd(closure, -1, do_close); | |||
203 | } | |||
204 | ||||
205 | void | |||
206 | KdDisableInput(void) | |||
207 | { | |||
208 | KdKeyboardInfo *ki; | |||
209 | KdPointerInfo *pi; | |||
210 | int found = 0, i = 0; | |||
211 | ||||
212 | input_lock(); | |||
213 | ||||
214 | for (ki = kdKeyboards; ki; ki = ki->next) { | |||
215 | if (ki->driver && ki->driver->Disable) | |||
216 | (*ki->driver->Disable) (ki); | |||
217 | } | |||
218 | ||||
219 | for (pi = kdPointers; pi; pi = pi->next) { | |||
220 | if (pi->driver && pi->driver->Disable) | |||
221 | (*pi->driver->Disable) (pi); | |||
222 | } | |||
223 | ||||
224 | if (kdNumInputFds) { | |||
225 | ErrorF("[KdDisableInput] Buggy drivers: still %d input fds left!", | |||
226 | kdNumInputFds); | |||
227 | i = 0; | |||
228 | while (i < kdNumInputFds) { | |||
229 | found = 0; | |||
230 | for (ki = kdKeyboards; ki; ki = ki->next) { | |||
231 | if (ki == kdInputFds[i].closure) { | |||
232 | ErrorF(" fd %d belongs to keybd driver %s\n", | |||
233 | kdInputFds[i].fd, | |||
234 | ki->driver && ki->driver->name ? | |||
235 | ki->driver->name : "(unnamed!)"); | |||
236 | found = 1; | |||
237 | break; | |||
238 | } | |||
239 | } | |||
240 | ||||
241 | if (found) { | |||
242 | i++; | |||
243 | continue; | |||
244 | } | |||
245 | ||||
246 | for (pi = kdPointers; pi; pi = pi->next) { | |||
247 | if (pi == kdInputFds[i].closure) { | |||
248 | ErrorF(" fd %d belongs to pointer driver %s\n", | |||
249 | kdInputFds[i].fd, | |||
250 | pi->driver && pi->driver->name ? | |||
251 | pi->driver->name : "(unnamed!)"); | |||
252 | break; | |||
253 | } | |||
254 | } | |||
255 | ||||
256 | if (found) { | |||
257 | i++; | |||
258 | continue; | |||
259 | } | |||
260 | ||||
261 | ErrorF(" fd %d not claimed by any active device!\n", | |||
262 | kdInputFds[i].fd); | |||
263 | KdUnregisterFd(kdInputFds[i].closure, kdInputFds[i].fd, TRUE1); | |||
264 | } | |||
265 | } | |||
266 | ||||
267 | kdInputEnabled = FALSE0; | |||
268 | } | |||
269 | ||||
270 | void | |||
271 | KdEnableInput(void) | |||
272 | { | |||
273 | InternalEvent ev; | |||
274 | KdKeyboardInfo *ki; | |||
275 | KdPointerInfo *pi; | |||
276 | ||||
277 | kdInputEnabled = TRUE1; | |||
278 | ||||
279 | ev.any.time = GetTimeInMillis(); | |||
280 | ||||
281 | for (ki = kdKeyboards; ki; ki = ki->next) { | |||
282 | if (ki->driver && ki->driver->Enable) | |||
283 | (*ki->driver->Enable) (ki); | |||
284 | /* reset screen saver */ | |||
285 | NoticeEventTime (&ev, ki->dixdev); | |||
286 | } | |||
287 | ||||
288 | for (pi = kdPointers; pi; pi = pi->next) { | |||
289 | if (pi->driver && pi->driver->Enable) | |||
290 | (*pi->driver->Enable) (pi); | |||
291 | /* reset screen saver */ | |||
292 | NoticeEventTime (&ev, pi->dixdev); | |||
293 | } | |||
294 | ||||
295 | input_unlock(); | |||
296 | } | |||
297 | ||||
298 | static KdKeyboardDriver * | |||
299 | KdFindKeyboardDriver(const char *name) | |||
300 | { | |||
301 | KdKeyboardDriver *ret; | |||
302 | ||||
303 | /* ask a stupid question ... */ | |||
304 | if (!name) | |||
305 | return NULL((void*)0); | |||
306 | ||||
307 | for (ret = kdKeyboardDrivers; ret; ret = ret->next) { | |||
308 | if (strcmp(ret->name, name) == 0) | |||
309 | return ret; | |||
310 | } | |||
311 | ||||
312 | return NULL((void*)0); | |||
313 | } | |||
314 | ||||
315 | static KdPointerDriver * | |||
316 | KdFindPointerDriver(const char *name) | |||
317 | { | |||
318 | KdPointerDriver *ret; | |||
319 | ||||
320 | /* ask a stupid question ... */ | |||
321 | if (!name) | |||
322 | return NULL((void*)0); | |||
323 | ||||
324 | for (ret = kdPointerDrivers; ret; ret = ret->next) { | |||
325 | if (strcmp(ret->name, name) == 0) | |||
326 | return ret; | |||
327 | } | |||
328 | ||||
329 | return NULL((void*)0); | |||
330 | } | |||
331 | ||||
332 | static int | |||
333 | KdPointerProc(DeviceIntPtr pDevice, int onoff) | |||
334 | { | |||
335 | DevicePtr pDev = (DevicePtr) pDevice; | |||
336 | KdPointerInfo *pi; | |||
337 | Atom xiclass; | |||
338 | Atom *btn_labels; | |||
339 | Atom *axes_labels; | |||
340 | ||||
341 | if (!pDev) | |||
342 | return BadImplementation17; | |||
343 | ||||
344 | for (pi = kdPointers; pi; pi = pi->next) { | |||
345 | if (pi->dixdev && pi->dixdev->id == pDevice->id) | |||
346 | break; | |||
347 | } | |||
348 | ||||
349 | if (!pi || !pi->dixdev || pi->dixdev->id != pDevice->id) { | |||
350 | ErrorF("[KdPointerProc] Failed to find pointer for device %d!\n", | |||
351 | pDevice->id); | |||
352 | return BadImplementation17; | |||
353 | } | |||
354 | ||||
355 | switch (onoff) { | |||
356 | case DEVICE_INIT0: | |||
357 | #ifdef DEBUG | |||
358 | ErrorF("initialising pointer %s ...\n", pi->name); | |||
359 | #endif | |||
360 | if (!pi->driver) { | |||
361 | if (!pi->driverPrivate) { | |||
362 | ErrorF("no driver specified for pointer device \"%s\" (%s)\n", | |||
363 | pi->name ? pi->name : "(unnamed)", pi->path); | |||
364 | return BadImplementation17; | |||
365 | } | |||
366 | ||||
367 | pi->driver = KdFindPointerDriver(pi->driverPrivate); | |||
368 | if (!pi->driver) { | |||
369 | ErrorF("Couldn't find pointer driver %s\n", | |||
370 | pi->driverPrivate ? (char *) pi->driverPrivate : | |||
371 | "(unnamed)"); | |||
372 | return !Success0; | |||
373 | } | |||
374 | free(pi->driverPrivate); | |||
375 | pi->driverPrivate = NULL((void*)0); | |||
376 | } | |||
377 | ||||
378 | if (!pi->driver->Init) { | |||
379 | ErrorF("no init function\n"); | |||
380 | return BadImplementation17; | |||
381 | } | |||
382 | ||||
383 | if ((*pi->driver->Init) (pi) != Success0) { | |||
384 | return !Success0; | |||
385 | } | |||
386 | ||||
387 | btn_labels = calloc(pi->nButtons, sizeof(Atom)); | |||
388 | if (!btn_labels) | |||
389 | return BadAlloc11; | |||
390 | axes_labels = calloc(pi->nAxes, sizeof(Atom)); | |||
391 | if (!axes_labels) { | |||
392 | free(btn_labels); | |||
393 | return BadAlloc11; | |||
394 | } | |||
395 | ||||
396 | switch (pi->nAxes) { | |||
397 | default: | |||
398 | case 7: | |||
399 | btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT"Button Horiz Wheel Right"); | |||
400 | case 6: | |||
401 | btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT"Button Horiz Wheel Left"); | |||
402 | case 5: | |||
403 | btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN"Button Wheel Down"); | |||
404 | case 4: | |||
405 | btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP"Button Wheel Up"); | |||
406 | case 3: | |||
407 | btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT"Button Right"); | |||
408 | case 2: | |||
409 | btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE"Button Middle"); | |||
410 | case 1: | |||
411 | btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT"Button Left"); | |||
412 | case 0: | |||
413 | break; | |||
414 | } | |||
415 | ||||
416 | if (pi->nAxes >= 2) { | |||
417 | axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X"Rel X"); | |||
418 | axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y"Rel Y"); | |||
419 | } | |||
420 | ||||
421 | InitPointerDeviceStruct(pDev, pi->map, pi->nButtons, btn_labels, | |||
422 | (PtrCtrlProcPtr) NoopDDA, | |||
423 | GetMotionHistorySize(), pi->nAxes, axes_labels); | |||
424 | ||||
425 | free(btn_labels); | |||
426 | free(axes_labels); | |||
427 | ||||
428 | if (pi->inputClass == KD_TOUCHSCREEN3) { | |||
429 | xiclass = AtomFromName(XI_TOUCHSCREEN)MakeAtom("TOUCHSCREEN", strlen("TOUCHSCREEN"), 1); | |||
430 | } | |||
431 | else { | |||
432 | xiclass = AtomFromName(XI_MOUSE)MakeAtom("MOUSE", strlen("MOUSE"), 1); | |||
433 | } | |||
434 | ||||
435 | AssignTypeAndName(pi->dixdev, xiclass, | |||
436 | pi->name ? pi->name : "Generic KDrive Pointer"); | |||
437 | ||||
438 | return Success0; | |||
439 | ||||
440 | case DEVICE_ON1: | |||
441 | if (pDev->on == TRUE1) | |||
442 | return Success0; | |||
443 | ||||
444 | if (!pi->driver->Enable) { | |||
445 | ErrorF("no enable function\n"); | |||
446 | return BadImplementation17; | |||
447 | } | |||
448 | ||||
449 | if ((*pi->driver->Enable) (pi) == Success0) { | |||
450 | pDev->on = TRUE1; | |||
451 | return Success0; | |||
452 | } | |||
453 | else { | |||
454 | return BadImplementation17; | |||
455 | } | |||
456 | ||||
457 | return Success0; | |||
458 | ||||
459 | case DEVICE_OFF2: | |||
460 | if (pDev->on == FALSE0) { | |||
461 | return Success0; | |||
462 | } | |||
463 | ||||
464 | if (!pi->driver->Disable) { | |||
465 | return BadImplementation17; | |||
466 | } | |||
467 | else { | |||
468 | (*pi->driver->Disable) (pi); | |||
469 | pDev->on = FALSE0; | |||
470 | return Success0; | |||
471 | } | |||
472 | ||||
473 | return Success0; | |||
474 | ||||
475 | case DEVICE_CLOSE3: | |||
476 | if (pDev->on) { | |||
477 | if (!pi->driver->Disable) { | |||
478 | return BadImplementation17; | |||
479 | } | |||
480 | (*pi->driver->Disable) (pi); | |||
481 | pDev->on = FALSE0; | |||
482 | } | |||
483 | ||||
484 | if (!pi->driver->Fini) | |||
485 | return BadImplementation17; | |||
486 | ||||
487 | (*pi->driver->Fini) (pi); | |||
488 | ||||
489 | KdRemovePointer(pi); | |||
490 | ||||
491 | return Success0; | |||
492 | } | |||
493 | ||||
494 | /* NOTREACHED */ | |||
495 | return BadImplementation17; | |||
496 | } | |||
497 | ||||
498 | Bool | |||
499 | LegalModifier(unsigned int key, DeviceIntPtr pDev) | |||
500 | { | |||
501 | return TRUE1; | |||
502 | } | |||
503 | ||||
504 | static void | |||
505 | KdBell(int volume, DeviceIntPtr pDev, void *arg, int something) | |||
506 | { | |||
507 | KeybdCtrl *ctrl = arg; | |||
508 | KdKeyboardInfo *ki = NULL((void*)0); | |||
509 | ||||
510 | for (ki = kdKeyboards; ki; ki = ki->next) { | |||
511 | if (ki->dixdev && ki->dixdev->id == pDev->id) | |||
512 | break; | |||
513 | } | |||
514 | ||||
515 | if (!ki || !ki->dixdev || ki->dixdev->id != pDev->id || !ki->driver) | |||
516 | return; | |||
517 | ||||
518 | KdRingBell(ki, volume, ctrl->bell_pitch, ctrl->bell_duration); | |||
519 | } | |||
520 | ||||
521 | void | |||
522 | DDXRingBell(int volume, int pitch, int duration) | |||
523 | { | |||
524 | KdKeyboardInfo *ki = NULL((void*)0); | |||
525 | ||||
526 | if (kdOsFuncs->Bell) { | |||
527 | (*kdOsFuncs->Bell) (volume, pitch, duration); | |||
528 | } | |||
529 | else { | |||
530 | for (ki = kdKeyboards; ki; ki = ki->next) { | |||
531 | if (ki->dixdev->coreEvents) | |||
532 | KdRingBell(ki, volume, pitch, duration); | |||
533 | } | |||
534 | } | |||
535 | } | |||
536 | ||||
537 | void | |||
538 | KdRingBell(KdKeyboardInfo * ki, int volume, int pitch, int duration) | |||
539 | { | |||
540 | if (!ki || !ki->driver || !ki->driver->Bell) | |||
541 | return; | |||
542 | ||||
543 | if (kdInputEnabled) | |||
544 | (*ki->driver->Bell) (ki, volume, pitch, duration); | |||
545 | } | |||
546 | ||||
547 | static void | |||
548 | KdSetLeds(KdKeyboardInfo * ki, int leds) | |||
549 | { | |||
550 | if (!ki || !ki->driver) | |||
551 | return; | |||
552 | ||||
553 | if (kdInputEnabled) { | |||
554 | if (ki->driver->Leds) | |||
555 | (*ki->driver->Leds) (ki, leds); | |||
556 | } | |||
557 | } | |||
558 | ||||
559 | void | |||
560 | KdSetLed(KdKeyboardInfo * ki, int led, Bool on) | |||
561 | { | |||
562 | if (!ki || !ki->dixdev || !ki->dixdev->kbdfeed) | |||
563 | return; | |||
564 | ||||
565 | NoteLedState(ki->dixdev, led, on); | |||
566 | KdSetLeds(ki, ki->dixdev->kbdfeed->ctrl.leds); | |||
567 | } | |||
568 | ||||
569 | void | |||
570 | KdSetPointerMatrix(KdPointerMatrix * matrix) | |||
571 | { | |||
572 | kdPointerMatrix = *matrix; | |||
573 | } | |||
574 | ||||
575 | void | |||
576 | KdComputePointerMatrix(KdPointerMatrix * m, Rotation randr, int width, | |||
577 | int height) | |||
578 | { | |||
579 | int x_dir = 1, y_dir = 1; | |||
580 | int i, j; | |||
581 | int size[2]; | |||
582 | ||||
583 | size[0] = width; | |||
584 | size[1] = height; | |||
585 | if (randr & RR_Reflect_X16) | |||
586 | x_dir = -1; | |||
587 | if (randr & RR_Reflect_Y32) | |||
588 | y_dir = -1; | |||
589 | switch (randr & (RR_Rotate_All(1|2|4|8))) { | |||
590 | case RR_Rotate_01: | |||
591 | m->matrix[0][0] = x_dir; | |||
592 | m->matrix[0][1] = 0; | |||
593 | m->matrix[1][0] = 0; | |||
594 | m->matrix[1][1] = y_dir; | |||
595 | break; | |||
596 | case RR_Rotate_902: | |||
597 | m->matrix[0][0] = 0; | |||
598 | m->matrix[0][1] = -x_dir; | |||
599 | m->matrix[1][0] = y_dir; | |||
600 | m->matrix[1][1] = 0; | |||
601 | break; | |||
602 | case RR_Rotate_1804: | |||
603 | m->matrix[0][0] = -x_dir; | |||
604 | m->matrix[0][1] = 0; | |||
605 | m->matrix[1][0] = 0; | |||
606 | m->matrix[1][1] = -y_dir; | |||
607 | break; | |||
608 | case RR_Rotate_2708: | |||
609 | m->matrix[0][0] = 0; | |||
610 | m->matrix[0][1] = x_dir; | |||
611 | m->matrix[1][0] = -y_dir; | |||
612 | m->matrix[1][1] = 0; | |||
613 | break; | |||
614 | } | |||
615 | for (i = 0; i < 2; i++) { | |||
616 | m->matrix[i][2] = 0; | |||
617 | for (j = 0; j < 2; j++) | |||
618 | if (m->matrix[i][j] < 0) | |||
619 | m->matrix[i][2] = size[j] - 1; | |||
620 | } | |||
621 | } | |||
622 | ||||
623 | void | |||
624 | KdScreenToPointerCoords(int *x, int *y) | |||
625 | { | |||
626 | int (*m)[3] = kdPointerMatrix.matrix; | |||
627 | int div = m[0][1] * m[1][0] - m[1][1] * m[0][0]; | |||
628 | int sx = *x; | |||
629 | int sy = *y; | |||
630 | ||||
631 | *x = (m[0][1] * sy - m[0][1] * m[1][2] + m[1][1] * m[0][2] - | |||
632 | m[1][1] * sx) / div; | |||
633 | *y = (m[1][0] * sx + m[0][0] * m[1][2] - m[1][0] * m[0][2] - | |||
634 | m[0][0] * sy) / div; | |||
635 | } | |||
636 | ||||
637 | static void | |||
638 | KdKbdCtrl(DeviceIntPtr pDevice, KeybdCtrl * ctrl) | |||
639 | { | |||
640 | KdKeyboardInfo *ki; | |||
641 | ||||
642 | for (ki = kdKeyboards; ki; ki = ki->next) { | |||
643 | if (ki->dixdev && ki->dixdev->id == pDevice->id) | |||
644 | break; | |||
645 | } | |||
646 | ||||
647 | if (!ki || !ki->dixdev || ki->dixdev->id != pDevice->id || !ki->driver) | |||
648 | return; | |||
649 | ||||
650 | KdSetLeds(ki, ctrl->leds); | |||
651 | ki->bellPitch = ctrl->bell_pitch; | |||
652 | ki->bellDuration = ctrl->bell_duration; | |||
653 | } | |||
654 | ||||
655 | static int | |||
656 | KdKeyboardProc(DeviceIntPtr pDevice, int onoff) | |||
657 | { | |||
658 | Bool ret; | |||
659 | DevicePtr pDev = (DevicePtr) pDevice; | |||
660 | KdKeyboardInfo *ki; | |||
661 | Atom xiclass; | |||
662 | XkbRMLVOSet rmlvo; | |||
663 | ||||
664 | if (!pDev) | |||
665 | return BadImplementation17; | |||
666 | ||||
667 | for (ki = kdKeyboards; ki; ki = ki->next) { | |||
668 | if (ki->dixdev && ki->dixdev->id == pDevice->id) | |||
669 | break; | |||
670 | } | |||
671 | ||||
672 | if (!ki || !ki->dixdev || ki->dixdev->id != pDevice->id) { | |||
673 | return BadImplementation17; | |||
674 | } | |||
675 | ||||
676 | switch (onoff) { | |||
677 | case DEVICE_INIT0: | |||
678 | #ifdef DEBUG | |||
679 | ErrorF("initialising keyboard %s\n", ki->name); | |||
680 | #endif | |||
681 | if (!ki->driver) { | |||
682 | if (!ki->driverPrivate) { | |||
683 | ErrorF("no driver specified for keyboard device \"%s\" (%s)\n", | |||
684 | ki->name ? ki->name : "(unnamed)", ki->path); | |||
685 | return BadImplementation17; | |||
686 | } | |||
687 | ||||
688 | ki->driver = KdFindKeyboardDriver(ki->driverPrivate); | |||
689 | if (!ki->driver) { | |||
690 | ErrorF("Couldn't find keyboard driver %s\n", | |||
691 | ki->driverPrivate ? (char *) ki->driverPrivate : | |||
692 | "(unnamed)"); | |||
693 | return !Success0; | |||
694 | } | |||
695 | free(ki->driverPrivate); | |||
696 | ki->driverPrivate = NULL((void*)0); | |||
697 | } | |||
698 | ||||
699 | if (!ki->driver->Init) { | |||
700 | ErrorF("Keyboard %s: no init function\n", ki->name); | |||
701 | return BadImplementation17; | |||
702 | } | |||
703 | ||||
704 | memset(&rmlvo, 0, sizeof(rmlvo))__builtin___memset_chk (&rmlvo, 0, sizeof(rmlvo), __builtin_object_size (&rmlvo, 0)); | |||
705 | rmlvo.rules = ki->xkbRules; | |||
706 | rmlvo.model = ki->xkbModel; | |||
707 | rmlvo.layout = ki->xkbLayout; | |||
708 | rmlvo.variant = ki->xkbVariant; | |||
709 | rmlvo.options = ki->xkbOptions; | |||
710 | ret = InitKeyboardDeviceStruct(pDevice, &rmlvo, KdBell, KdKbdCtrl); | |||
711 | if (!ret) { | |||
712 | ErrorF("Couldn't initialise keyboard %s\n", ki->name); | |||
713 | return BadImplementation17; | |||
714 | } | |||
715 | ||||
716 | if ((*ki->driver->Init) (ki) != Success0) { | |||
717 | return !Success0; | |||
718 | } | |||
719 | ||||
720 | xiclass = AtomFromName(XI_KEYBOARD)MakeAtom("KEYBOARD", strlen("KEYBOARD"), 1); | |||
721 | AssignTypeAndName(pDevice, xiclass, | |||
722 | ki->name ? ki->name : "Generic KDrive Keyboard"); | |||
723 | ||||
724 | KdResetInputMachine(); | |||
725 | ||||
726 | return Success0; | |||
727 | ||||
728 | case DEVICE_ON1: | |||
729 | if (pDev->on == TRUE1) | |||
730 | return Success0; | |||
731 | ||||
732 | if (!ki->driver->Enable) | |||
733 | return BadImplementation17; | |||
734 | ||||
735 | if ((*ki->driver->Enable) (ki) != Success0) { | |||
736 | return BadMatch8; | |||
737 | } | |||
738 | ||||
739 | pDev->on = TRUE1; | |||
740 | return Success0; | |||
741 | ||||
742 | case DEVICE_OFF2: | |||
743 | if (pDev->on == FALSE0) | |||
744 | return Success0; | |||
745 | ||||
746 | if (!ki->driver->Disable) | |||
747 | return BadImplementation17; | |||
748 | ||||
749 | (*ki->driver->Disable) (ki); | |||
750 | pDev->on = FALSE0; | |||
751 | ||||
752 | return Success0; | |||
753 | ||||
754 | break; | |||
755 | ||||
756 | case DEVICE_CLOSE3: | |||
757 | if (pDev->on) { | |||
758 | if (!ki->driver->Disable) | |||
759 | return BadImplementation17; | |||
760 | ||||
761 | (*ki->driver->Disable) (ki); | |||
762 | pDev->on = FALSE0; | |||
763 | } | |||
764 | ||||
765 | if (!ki->driver->Fini) | |||
766 | return BadImplementation17; | |||
767 | ||||
768 | (*ki->driver->Fini) (ki); | |||
769 | ||||
770 | KdRemoveKeyboard(ki); | |||
771 | ||||
772 | return Success0; | |||
773 | } | |||
774 | ||||
775 | /* NOTREACHED */ | |||
776 | return BadImplementation17; | |||
777 | } | |||
778 | ||||
779 | void | |||
780 | KdAddPointerDriver(KdPointerDriver * driver) | |||
781 | { | |||
782 | KdPointerDriver **prev; | |||
783 | ||||
784 | if (!driver) | |||
785 | return; | |||
786 | ||||
787 | for (prev = &kdPointerDrivers; *prev; prev = &(*prev)->next) { | |||
788 | if (*prev == driver) | |||
789 | return; | |||
790 | } | |||
791 | *prev = driver; | |||
792 | } | |||
793 | ||||
794 | void | |||
795 | KdRemovePointerDriver(KdPointerDriver * driver) | |||
796 | { | |||
797 | KdPointerDriver *tmp; | |||
798 | ||||
799 | if (!driver) | |||
800 | return; | |||
801 | ||||
802 | /* FIXME remove all pointers using this driver */ | |||
803 | for (tmp = kdPointerDrivers; tmp; tmp = tmp->next) { | |||
804 | if (tmp->next == driver) | |||
805 | tmp->next = driver->next; | |||
806 | } | |||
807 | if (tmp == driver) | |||
808 | tmp = NULL((void*)0); | |||
809 | } | |||
810 | ||||
811 | void | |||
812 | KdAddKeyboardDriver(KdKeyboardDriver * driver) | |||
813 | { | |||
814 | KdKeyboardDriver **prev; | |||
815 | ||||
816 | if (!driver) | |||
817 | return; | |||
818 | ||||
819 | for (prev = &kdKeyboardDrivers; *prev; prev = &(*prev)->next) { | |||
820 | if (*prev == driver) | |||
821 | return; | |||
822 | } | |||
823 | *prev = driver; | |||
824 | } | |||
825 | ||||
826 | void | |||
827 | KdRemoveKeyboardDriver(KdKeyboardDriver * driver) | |||
828 | { | |||
829 | KdKeyboardDriver *tmp; | |||
830 | ||||
831 | if (!driver) | |||
832 | return; | |||
833 | ||||
834 | /* FIXME remove all keyboards using this driver */ | |||
835 | for (tmp = kdKeyboardDrivers; tmp; tmp = tmp->next) { | |||
836 | if (tmp->next == driver) | |||
837 | tmp->next = driver->next; | |||
838 | } | |||
839 | if (tmp == driver) | |||
840 | tmp = NULL((void*)0); | |||
841 | } | |||
842 | ||||
843 | KdKeyboardInfo * | |||
844 | KdNewKeyboard(void) | |||
845 | { | |||
846 | KdKeyboardInfo *ki = calloc(sizeof(KdKeyboardInfo), 1); | |||
847 | ||||
848 | if (!ki) | |||
849 | return NULL((void*)0); | |||
850 | ||||
851 | ki->minScanCode = 0; | |||
852 | ki->maxScanCode = 0; | |||
853 | ki->leds = 0; | |||
854 | ki->bellPitch = 1000; | |||
855 | ki->bellDuration = 200; | |||
856 | ki->next = NULL((void*)0); | |||
857 | ki->options = NULL((void*)0); | |||
858 | ki->name = strdup("Generic Keyboard"); | |||
859 | ki->path = NULL((void*)0); | |||
860 | ki->xkbRules = strdup(kdGlobalXkbRules ? kdGlobalXkbRules : XKB_DFLT_RULES"base"); | |||
861 | ki->xkbModel = strdup(kdGlobalXkbModel ? kdGlobalXkbModel : XKB_DFLT_MODEL"pc105"); | |||
862 | ki->xkbLayout = strdup(kdGlobalXkbLayout ? kdGlobalXkbLayout : XKB_DFLT_LAYOUT"us"); | |||
863 | ki->xkbVariant = strdup(kdGlobalXkbVariant ? kdGlobalXkbVariant :XKB_DFLT_VARIANT""); | |||
864 | ki->xkbOptions = strdup(kdGlobalXkbOptions ? kdGlobalXkbOptions : XKB_DFLT_OPTIONS""); | |||
865 | ||||
866 | return ki; | |||
867 | } | |||
868 | ||||
869 | int | |||
870 | KdAddConfigKeyboard(char *keyboard) | |||
871 | { | |||
872 | struct KdConfigDevice **prev, *new; | |||
873 | ||||
874 | if (!keyboard) | |||
875 | return Success0; | |||
876 | ||||
877 | new = (struct KdConfigDevice *) calloc(sizeof(struct KdConfigDevice), 1); | |||
878 | if (!new) | |||
879 | return BadAlloc11; | |||
880 | ||||
881 | new->line = strdup(keyboard); | |||
882 | new->next = NULL((void*)0); | |||
883 | ||||
884 | for (prev = &kdConfigKeyboards; *prev; prev = &(*prev)->next); | |||
885 | *prev = new; | |||
886 | ||||
887 | return Success0; | |||
888 | } | |||
889 | ||||
890 | int | |||
891 | KdAddKeyboard(KdKeyboardInfo * ki) | |||
892 | { | |||
893 | KdKeyboardInfo **prev; | |||
894 | ||||
895 | if (!ki) | |||
896 | return !Success0; | |||
897 | ||||
898 | ki->dixdev = AddInputDevice(serverClient, KdKeyboardProc, TRUE1); | |||
899 | if (!ki->dixdev) { | |||
900 | ErrorF("Couldn't register keyboard device %s\n", | |||
901 | ki->name ? ki->name : "(unnamed)"); | |||
902 | return !Success0; | |||
903 | } | |||
904 | ||||
905 | #ifdef DEBUG | |||
906 | ErrorF("added keyboard %s with dix id %d\n", ki->name, ki->dixdev->id); | |||
907 | #endif | |||
908 | ||||
909 | for (prev = &kdKeyboards; *prev; prev = &(*prev)->next); | |||
910 | *prev = ki; | |||
911 | ||||
912 | return Success0; | |||
913 | } | |||
914 | ||||
915 | void | |||
916 | KdRemoveKeyboard(KdKeyboardInfo * ki) | |||
917 | { | |||
918 | KdKeyboardInfo **prev; | |||
919 | ||||
920 | if (!ki) | |||
921 | return; | |||
922 | ||||
923 | for (prev = &kdKeyboards; *prev; prev = &(*prev)->next) { | |||
924 | if (*prev == ki) { | |||
925 | *prev = ki->next; | |||
926 | break; | |||
927 | } | |||
928 | } | |||
929 | ||||
930 | KdFreeKeyboard(ki); | |||
931 | } | |||
932 | ||||
933 | int | |||
934 | KdAddConfigPointer(char *pointer) | |||
935 | { | |||
936 | struct KdConfigDevice **prev, *new; | |||
937 | ||||
938 | if (!pointer) | |||
939 | return Success0; | |||
940 | ||||
941 | new = (struct KdConfigDevice *) calloc(sizeof(struct KdConfigDevice), 1); | |||
942 | if (!new) | |||
943 | return BadAlloc11; | |||
944 | ||||
945 | new->line = strdup(pointer); | |||
946 | new->next = NULL((void*)0); | |||
947 | ||||
948 | for (prev = &kdConfigPointers; *prev; prev = &(*prev)->next); | |||
949 | *prev = new; | |||
950 | ||||
951 | return Success0; | |||
952 | } | |||
953 | ||||
954 | int | |||
955 | KdAddPointer(KdPointerInfo * pi) | |||
956 | { | |||
957 | KdPointerInfo **prev; | |||
958 | ||||
959 | if (!pi) | |||
960 | return Success0; | |||
961 | ||||
962 | pi->mouseState = start; | |||
963 | pi->eventHeld = FALSE0; | |||
964 | ||||
965 | pi->dixdev = AddInputDevice(serverClient, KdPointerProc, TRUE1); | |||
966 | if (!pi->dixdev) { | |||
967 | ErrorF("Couldn't add pointer device %s\n", | |||
968 | pi->name ? pi->name : "(unnamed)"); | |||
969 | return BadDevice; | |||
970 | } | |||
971 | ||||
972 | for (prev = &kdPointers; *prev; prev = &(*prev)->next); | |||
973 | *prev = pi; | |||
974 | ||||
975 | return Success0; | |||
976 | } | |||
977 | ||||
978 | void | |||
979 | KdRemovePointer(KdPointerInfo * pi) | |||
980 | { | |||
981 | KdPointerInfo **prev; | |||
982 | ||||
983 | if (!pi) | |||
984 | return; | |||
985 | ||||
986 | for (prev = &kdPointers; *prev; prev = &(*prev)->next) { | |||
987 | if (*prev == pi) { | |||
988 | *prev = pi->next; | |||
989 | break; | |||
990 | } | |||
991 | } | |||
992 | ||||
993 | KdFreePointer(pi); | |||
994 | } | |||
995 | ||||
996 | /* | |||
997 | * You can call your kdriver server with something like: | |||
998 | * $ ./hw/kdrive/yourserver/X :1 -mouse evdev,,device=/dev/input/event4 -keybd | |||
999 | * evdev,,device=/dev/input/event1,xkbmodel=abnt2,xkblayout=br | |||
1000 | */ | |||
1001 | static Bool | |||
1002 | KdGetOptions(InputOption **options, char *string) | |||
1003 | { | |||
1004 | InputOption *newopt = NULL((void*)0); | |||
1005 | char *key = NULL((void*)0), *value = NULL((void*)0); | |||
1006 | int tam_key = 0; | |||
1007 | ||||
1008 | if (strchr(string, '=')) { | |||
1009 | tam_key = (strchr(string, '=') - string); | |||
1010 | key = strndup(string, tam_key); | |||
1011 | if (!key) | |||
1012 | goto out; | |||
1013 | ||||
1014 | value = strdup(strchr(string, '=') + 1); | |||
1015 | if (!value) | |||
1016 | goto out; | |||
1017 | } | |||
1018 | else { | |||
1019 | key = strdup(string); | |||
1020 | value = NULL((void*)0); | |||
1021 | } | |||
1022 | ||||
1023 | newopt = input_option_new(*options, key, value); | |||
1024 | if (newopt) | |||
1025 | *options = newopt; | |||
1026 | ||||
1027 | out: | |||
1028 | free(key); | |||
1029 | free(value); | |||
1030 | ||||
1031 | return (newopt != NULL((void*)0)); | |||
1032 | } | |||
1033 | ||||
1034 | static void | |||
1035 | KdParseKbdOptions(KdKeyboardInfo * ki) | |||
1036 | { | |||
1037 | InputOption *option = NULL((void*)0); | |||
1038 | ||||
1039 | nt_list_for_each_entry(option, ki->options, list.next)for (option = ki->options; option; option = (option)->list .next) { | |||
1040 | const char *key = input_option_get_key(option); | |||
1041 | const char *value = input_option_get_value(option); | |||
1042 | ||||
1043 | if ( | |||
1044 | #if defined(CONFIG_UDEV) || defined(CONFIG_HAL) | |||
1045 | strcasecmp(key, "xkb_rules") == 0 || | |||
1046 | #endif | |||
1047 | strcasecmp(key, "XkbRules") == 0) | |||
1048 | ki->xkbRules = strdup(value); | |||
1049 | else if ( | |||
1050 | #if defined(CONFIG_UDEV) || defined(CONFIG_HAL) | |||
1051 | strcasecmp(key, "xkb_model") == 0 || | |||
1052 | #endif | |||
1053 | strcasecmp(key, "XkbModel") == 0) | |||
1054 | ki->xkbModel = strdup(value); | |||
1055 | else if ( | |||
1056 | #if defined(CONFIG_UDEV) || defined(CONFIG_HAL) | |||
1057 | strcasecmp(key, "xkb_layout") == 0 || | |||
1058 | #endif | |||
1059 | strcasecmp(key, "XkbLayout") == 0) | |||
1060 | ki->xkbLayout = strdup(value); | |||
1061 | else if ( | |||
1062 | #if defined(CONFIG_UDEV) || defined(CONFIG_HAL) | |||
1063 | strcasecmp(key, "xkb_variant") == 0 || | |||
1064 | #endif | |||
1065 | strcasecmp(key, "XkbVariant") == 0) | |||
1066 | ki->xkbVariant = strdup(value); | |||
1067 | else if ( | |||
1068 | #if defined(CONFIG_UDEV) || defined(CONFIG_HAL) | |||
1069 | strcasecmp(key, "xkb_options") == 0 || | |||
1070 | #endif | |||
1071 | strcasecmp(key, "XkbOptions") == 0) | |||
1072 | ki->xkbOptions = strdup(value); | |||
1073 | else if (!strcasecmp(key, "device")) { | |||
1074 | if (ki->path != NULL((void*)0)) | |||
1075 | free(ki->path); | |||
1076 | ki->path = strdup(value); | |||
1077 | } | |||
1078 | #if defined(CONFIG_UDEV) || defined(CONFIG_HAL) | |||
1079 | else if (!strcasecmp(key, "path")) { | |||
1080 | if (ki->path != NULL((void*)0)) | |||
1081 | free(ki->path); | |||
1082 | ki->path = strdup(value); | |||
1083 | } | |||
1084 | else if (!strcasecmp(key, "name")) { | |||
1085 | free(ki->name); | |||
1086 | ki->name = strdup(value); | |||
1087 | } | |||
1088 | #endif | |||
1089 | else if (!strcasecmp(key, "driver")) | |||
1090 | ki->driver = KdFindKeyboardDriver(value); | |||
1091 | else | |||
1092 | ErrorF("Kbd option key (%s) of value (%s) not assigned!\n", | |||
1093 | key, value); | |||
1094 | } | |||
1095 | ||||
1096 | #ifdef KDRIVE_EVDEV | |||
1097 | if (!ki->driver && ki->path != NULL((void*)0) && | |||
1098 | strncasecmp(ki->path, | |||
1099 | DEV_INPUT_EVENT_PREFIX, | |||
1100 | DEV_INPUT_EVENT_PREFIX_LEN) == 0) { | |||
1101 | ki->driver = KdFindKeyboardDriver("evdev"); | |||
1102 | ki->options = input_option_new(ki->options, "driver", "evdev"); | |||
1103 | } | |||
1104 | #endif | |||
1105 | } | |||
1106 | ||||
1107 | KdKeyboardInfo * | |||
1108 | KdParseKeyboard(const char *arg) | |||
1109 | { | |||
1110 | char save[1024]; | |||
1111 | char delim; | |||
1112 | InputOption *options = NULL((void*)0); | |||
1113 | KdKeyboardInfo *ki = NULL((void*)0); | |||
1114 | ||||
1115 | ki = KdNewKeyboard(); | |||
1116 | if (!ki) | |||
1117 | return NULL((void*)0); | |||
1118 | ||||
1119 | ki->name = strdup("Unknown KDrive Keyboard"); | |||
1120 | ki->path = NULL((void*)0); | |||
1121 | ki->driver = NULL((void*)0); | |||
1122 | ki->driverPrivate = NULL((void*)0); | |||
1123 | ki->next = NULL((void*)0); | |||
1124 | ||||
1125 | if (!arg) { | |||
1126 | ErrorF("keybd: no arg\n"); | |||
1127 | KdFreeKeyboard(ki); | |||
1128 | return NULL((void*)0); | |||
1129 | } | |||
1130 | ||||
1131 | if (strlen(arg) >= sizeof(save)) { | |||
1132 | ErrorF("keybd: arg too long\n"); | |||
1133 | KdFreeKeyboard(ki); | |||
1134 | return NULL((void*)0); | |||
1135 | } | |||
1136 | ||||
1137 | arg = KdParseFindNext(arg, ",", save, &delim); | |||
1138 | if (!save[0]) { | |||
1139 | ErrorF("keybd: failed on save[0]\n"); | |||
1140 | KdFreeKeyboard(ki); | |||
1141 | return NULL((void*)0); | |||
1142 | } | |||
1143 | ||||
1144 | if (strcmp(save, "auto") == 0) | |||
1145 | ki->driverPrivate = NULL((void*)0); | |||
1146 | else | |||
1147 | ki->driverPrivate = strdup(save); | |||
1148 | ||||
1149 | if (delim != ',') { | |||
1150 | return ki; | |||
1151 | } | |||
1152 | ||||
1153 | arg = KdParseFindNext(arg, ",", save, &delim); | |||
1154 | ||||
1155 | while (delim == ',') { | |||
1156 | arg = KdParseFindNext(arg, ",", save, &delim); | |||
1157 | ||||
1158 | if (!KdGetOptions(&options, save)) { | |||
1159 | KdFreeKeyboard(ki); | |||
1160 | return NULL((void*)0); | |||
1161 | } | |||
1162 | } | |||
1163 | ||||
1164 | if (options) { | |||
1165 | ki->options = options; | |||
1166 | KdParseKbdOptions(ki); | |||
1167 | } | |||
1168 | ||||
1169 | return ki; | |||
1170 | } | |||
1171 | ||||
1172 | static void | |||
1173 | KdParsePointerOptions(KdPointerInfo * pi) | |||
1174 | { | |||
1175 | InputOption *option = NULL((void*)0); | |||
1176 | ||||
1177 | nt_list_for_each_entry(option, pi->options, list.next)for (option = pi->options; option; option = (option)->list .next) { | |||
1178 | const char *key = input_option_get_key(option); | |||
1179 | const char *value = input_option_get_value(option); | |||
1180 | ||||
1181 | if (!strcasecmp(key, "emulatemiddle")) | |||
1182 | pi->emulateMiddleButton = TRUE1; | |||
1183 | else if (!strcasecmp(key, "noemulatemiddle")) | |||
1184 | pi->emulateMiddleButton = FALSE0; | |||
1185 | else if (!strcasecmp(key, "transformcoord")) | |||
1186 | pi->transformCoordinates = TRUE1; | |||
1187 | else if (!strcasecmp(key, "rawcoord")) | |||
1188 | pi->transformCoordinates = FALSE0; | |||
1189 | else if (!strcasecmp(key, "device")) { | |||
1190 | if (pi->path != NULL((void*)0)) | |||
1191 | free(pi->path); | |||
1192 | pi->path = strdup(value); | |||
1193 | } | |||
1194 | #if defined(CONFIG_UDEV) || defined(CONFIG_HAL) | |||
1195 | else if (!strcasecmp(key, "path")) { | |||
1196 | if (pi->path != NULL((void*)0)) | |||
1197 | free(pi->path); | |||
1198 | pi->path = strdup(value); | |||
1199 | } | |||
1200 | else if (!strcasecmp(key, "name")) { | |||
1201 | free(pi->name); | |||
1202 | pi->name = strdup(value); | |||
1203 | } | |||
1204 | #endif | |||
1205 | else if (!strcasecmp(key, "protocol")) | |||
1206 | pi->protocol = strdup(value); | |||
1207 | else if (!strcasecmp(key, "driver")) | |||
1208 | pi->driver = KdFindPointerDriver(value); | |||
1209 | else | |||
1210 | ErrorF("Pointer option key (%s) of value (%s) not assigned!\n", | |||
1211 | key, value); | |||
1212 | } | |||
1213 | ||||
1214 | #ifdef KDRIVE_EVDEV | |||
1215 | if (!pi->driver && pi->path != NULL((void*)0) && | |||
1216 | strncasecmp(pi->path, | |||
1217 | DEV_INPUT_EVENT_PREFIX, | |||
1218 | DEV_INPUT_EVENT_PREFIX_LEN) == 0) { | |||
1219 | pi->driver = KdFindPointerDriver("evdev"); | |||
1220 | pi->options = input_option_new(pi->options, "driver", "evdev"); | |||
1221 | } | |||
1222 | #endif | |||
1223 | } | |||
1224 | ||||
1225 | KdPointerInfo * | |||
1226 | KdParsePointer(const char *arg) | |||
1227 | { | |||
1228 | char save[1024]; | |||
1229 | char delim; | |||
1230 | KdPointerInfo *pi = NULL((void*)0); | |||
1231 | InputOption *options = NULL((void*)0); | |||
1232 | int i = 0; | |||
1233 | ||||
1234 | pi = KdNewPointer(); | |||
1235 | if (!pi) | |||
1236 | return NULL((void*)0); | |||
1237 | pi->emulateMiddleButton = kdEmulateMiddleButton; | |||
1238 | pi->transformCoordinates = !kdRawPointerCoordinates; | |||
1239 | pi->protocol = NULL((void*)0); | |||
1240 | pi->nButtons = 5; /* XXX should not be hardcoded */ | |||
1241 | pi->inputClass = KD_MOUSE2; | |||
1242 | ||||
1243 | if (!arg) { | |||
1244 | ErrorF("mouse: no arg\n"); | |||
1245 | KdFreePointer(pi); | |||
1246 | return NULL((void*)0); | |||
1247 | } | |||
1248 | ||||
1249 | if (strlen(arg) >= sizeof(save)) { | |||
1250 | ErrorF("mouse: arg too long\n"); | |||
1251 | KdFreePointer(pi); | |||
1252 | return NULL((void*)0); | |||
1253 | } | |||
1254 | arg = KdParseFindNext(arg, ",", save, &delim); | |||
1255 | if (!save[0]) { | |||
1256 | ErrorF("failed on save[0]\n"); | |||
1257 | KdFreePointer(pi); | |||
1258 | return NULL((void*)0); | |||
1259 | } | |||
1260 | ||||
1261 | if (strcmp(save, "auto") == 0) | |||
1262 | pi->driverPrivate = NULL((void*)0); | |||
1263 | else | |||
1264 | pi->driverPrivate = strdup(save); | |||
1265 | ||||
1266 | if (delim != ',') { | |||
1267 | return pi; | |||
1268 | } | |||
1269 | ||||
1270 | arg = KdParseFindNext(arg, ",", save, &delim); | |||
1271 | ||||
1272 | while (delim == ',') { | |||
1273 | arg = KdParseFindNext(arg, ",", save, &delim); | |||
1274 | if (save[0] == '{') { | |||
1275 | char *s = save + 1; | |||
1276 | ||||
1277 | i = 0; | |||
1278 | while (*s && *s != '}') { | |||
1279 | if ('1' <= *s && *s <= '0' + pi->nButtons) | |||
1280 | pi->map[i] = *s - '0'; | |||
1281 | else | |||
1282 | UseMsg(); | |||
1283 | s++; | |||
1284 | } | |||
1285 | } | |||
1286 | else { | |||
1287 | if (!KdGetOptions(&options, save)) { | |||
1288 | KdFreePointer(pi); | |||
1289 | return NULL((void*)0); | |||
1290 | } | |||
1291 | } | |||
1292 | } | |||
1293 | ||||
1294 | if (options) { | |||
1295 | pi->options = options; | |||
1296 | KdParsePointerOptions(pi); | |||
1297 | } | |||
1298 | ||||
1299 | return pi; | |||
1300 | } | |||
1301 | ||||
1302 | void | |||
1303 | KdInitInput(void) | |||
1304 | { | |||
1305 | KdPointerInfo *pi; | |||
1306 | KdKeyboardInfo *ki; | |||
1307 | struct KdConfigDevice *dev; | |||
1308 | ||||
1309 | InputThreadPreInit(); | |||
1310 | ||||
1311 | kdInputEnabled = TRUE1; | |||
1312 | ||||
1313 | for (dev = kdConfigPointers; dev; dev = dev->next) { | |||
| ||||
1314 | pi = KdParsePointer(dev->line); | |||
1315 | if (!pi) | |||
1316 | ErrorF("Failed to parse pointer\n"); | |||
1317 | if (KdAddPointer(pi) != Success0) | |||
1318 | ErrorF("Failed to add pointer!\n"); | |||
1319 | } | |||
1320 | for (dev = kdConfigKeyboards; dev; dev = dev->next) { | |||
1321 | ki = KdParseKeyboard(dev->line); | |||
1322 | if (!ki) | |||
1323 | ErrorF("Failed to parse keyboard\n"); | |||
1324 | if (KdAddKeyboard(ki) != Success0) | |||
1325 | ErrorF("Failed to add keyboard!\n"); | |||
1326 | } | |||
1327 | ||||
1328 | mieqInit(); | |||
| ||||
1329 | ||||
1330 | #if defined(CONFIG_UDEV) || defined(CONFIG_HAL) | |||
1331 | if (SeatId) /* Enable input hot-plugging */ | |||
1332 | config_init(); | |||
1333 | #endif | |||
1334 | } | |||
1335 | ||||
1336 | void | |||
1337 | KdCloseInput(void) | |||
1338 | { | |||
1339 | #if defined(CONFIG_UDEV) || defined(CONFIG_HAL) | |||
1340 | if (SeatId) /* Input hot-plugging is enabled */ | |||
1341 | config_fini(); | |||
1342 | #endif | |||
1343 | ||||
1344 | mieqFini(); | |||
1345 | } | |||
1346 | ||||
1347 | /* | |||
1348 | * Middle button emulation state machine | |||
1349 | * | |||
1350 | * Possible transitions: | |||
1351 | * Button 1 press v1 | |||
1352 | * Button 1 release ^1 | |||
1353 | * Button 2 press v2 | |||
1354 | * Button 2 release ^2 | |||
1355 | * Button 3 press v3 | |||
1356 | * Button 3 release ^3 | |||
1357 | * Button other press vo | |||
1358 | * Button other release ^o | |||
1359 | * Mouse motion <> | |||
1360 | * Keyboard event k | |||
1361 | * timeout ... | |||
1362 | * outside box <-> | |||
1363 | * | |||
1364 | * States: | |||
1365 | * start | |||
1366 | * button_1_pend | |||
1367 | * button_1_down | |||
1368 | * button_2_down | |||
1369 | * button_3_pend | |||
1370 | * button_3_down | |||
1371 | * synthetic_2_down_13 | |||
1372 | * synthetic_2_down_3 | |||
1373 | * synthetic_2_down_1 | |||
1374 | * | |||
1375 | * Transition diagram | |||
1376 | * | |||
1377 | * start | |||
1378 | * v1 -> (hold) (settimeout) button_1_pend | |||
1379 | * ^1 -> (deliver) start | |||
1380 | * v2 -> (deliver) button_2_down | |||
1381 | * ^2 -> (deliever) start | |||
1382 | * v3 -> (hold) (settimeout) button_3_pend | |||
1383 | * ^3 -> (deliver) start | |||
1384 | * vo -> (deliver) start | |||
1385 | * ^o -> (deliver) start | |||
1386 | * <> -> (deliver) start | |||
1387 | * k -> (deliver) start | |||
1388 | * | |||
1389 | * button_1_pend (button 1 is down, timeout pending) | |||
1390 | * ^1 -> (release) (deliver) start | |||
1391 | * v2 -> (release) (deliver) button_1_down | |||
1392 | * ^2 -> (release) (deliver) button_1_down | |||
1393 | * v3 -> (cleartimeout) (generate v2) synthetic_2_down_13 | |||
1394 | * ^3 -> (release) (deliver) button_1_down | |||
1395 | * vo -> (release) (deliver) button_1_down | |||
1396 | * ^o -> (release) (deliver) button_1_down | |||
1397 | * <-> -> (release) (deliver) button_1_down | |||
1398 | * <> -> (deliver) button_1_pend | |||
1399 | * k -> (release) (deliver) button_1_down | |||
1400 | * ... -> (release) button_1_down | |||
1401 | * | |||
1402 | * button_1_down (button 1 is down) | |||
1403 | * ^1 -> (deliver) start | |||
1404 | * v2 -> (deliver) button_1_down | |||
1405 | * ^2 -> (deliver) button_1_down | |||
1406 | * v3 -> (deliver) button_1_down | |||
1407 | * ^3 -> (deliver) button_1_down | |||
1408 | * vo -> (deliver) button_1_down | |||
1409 | * ^o -> (deliver) button_1_down | |||
1410 | * <> -> (deliver) button_1_down | |||
1411 | * k -> (deliver) button_1_down | |||
1412 | * | |||
1413 | * button_2_down (button 2 is down) | |||
1414 | * v1 -> (deliver) button_2_down | |||
1415 | * ^1 -> (deliver) button_2_down | |||
1416 | * ^2 -> (deliver) start | |||
1417 | * v3 -> (deliver) button_2_down | |||
1418 | * ^3 -> (deliver) button_2_down | |||
1419 | * vo -> (deliver) button_2_down | |||
1420 | * ^o -> (deliver) button_2_down | |||
1421 | * <> -> (deliver) button_2_down | |||
1422 | * k -> (deliver) button_2_down | |||
1423 | * | |||
1424 | * button_3_pend (button 3 is down, timeout pending) | |||
1425 | * v1 -> (generate v2) synthetic_2_down | |||
1426 | * ^1 -> (release) (deliver) button_3_down | |||
1427 | * v2 -> (release) (deliver) button_3_down | |||
1428 | * ^2 -> (release) (deliver) button_3_down | |||
1429 | * ^3 -> (release) (deliver) start | |||
1430 | * vo -> (release) (deliver) button_3_down | |||
1431 | * ^o -> (release) (deliver) button_3_down | |||
1432 | * <-> -> (release) (deliver) button_3_down | |||
1433 | * <> -> (deliver) button_3_pend | |||
1434 | * k -> (release) (deliver) button_3_down | |||
1435 | * ... -> (release) button_3_down | |||
1436 | * | |||
1437 | * button_3_down (button 3 is down) | |||
1438 | * v1 -> (deliver) button_3_down | |||
1439 | * ^1 -> (deliver) button_3_down | |||
1440 | * v2 -> (deliver) button_3_down | |||
1441 | * ^2 -> (deliver) button_3_down | |||
1442 | * ^3 -> (deliver) start | |||
1443 | * vo -> (deliver) button_3_down | |||
1444 | * ^o -> (deliver) button_3_down | |||
1445 | * <> -> (deliver) button_3_down | |||
1446 | * k -> (deliver) button_3_down | |||
1447 | * | |||
1448 | * synthetic_2_down_13 (button 1 and 3 are down) | |||
1449 | * ^1 -> (generate ^2) synthetic_2_down_3 | |||
1450 | * v2 -> synthetic_2_down_13 | |||
1451 | * ^2 -> synthetic_2_down_13 | |||
1452 | * ^3 -> (generate ^2) synthetic_2_down_1 | |||
1453 | * vo -> (deliver) synthetic_2_down_13 | |||
1454 | * ^o -> (deliver) synthetic_2_down_13 | |||
1455 | * <> -> (deliver) synthetic_2_down_13 | |||
1456 | * k -> (deliver) synthetic_2_down_13 | |||
1457 | * | |||
1458 | * synthetic_2_down_3 (button 3 is down) | |||
1459 | * v1 -> (deliver) synthetic_2_down_3 | |||
1460 | * ^1 -> (deliver) synthetic_2_down_3 | |||
1461 | * v2 -> synthetic_2_down_3 | |||
1462 | * ^2 -> synthetic_2_down_3 | |||
1463 | * ^3 -> start | |||
1464 | * vo -> (deliver) synthetic_2_down_3 | |||
1465 | * ^o -> (deliver) synthetic_2_down_3 | |||
1466 | * <> -> (deliver) synthetic_2_down_3 | |||
1467 | * k -> (deliver) synthetic_2_down_3 | |||
1468 | * | |||
1469 | * synthetic_2_down_1 (button 1 is down) | |||
1470 | * ^1 -> start | |||
1471 | * v2 -> synthetic_2_down_1 | |||
1472 | * ^2 -> synthetic_2_down_1 | |||
1473 | * v3 -> (deliver) synthetic_2_down_1 | |||
1474 | * ^3 -> (deliver) synthetic_2_down_1 | |||
1475 | * vo -> (deliver) synthetic_2_down_1 | |||
1476 | * ^o -> (deliver) synthetic_2_down_1 | |||
1477 | * <> -> (deliver) synthetic_2_down_1 | |||
1478 | * k -> (deliver) synthetic_2_down_1 | |||
1479 | */ | |||
1480 | ||||
1481 | typedef enum _inputClass { | |||
1482 | down_1, up_1, | |||
1483 | down_2, up_2, | |||
1484 | down_3, up_3, | |||
1485 | down_o, up_o, | |||
1486 | motion, outside_box, | |||
1487 | keyboard, timeout, | |||
1488 | num_input_class | |||
1489 | } KdInputClass; | |||
1490 | ||||
1491 | typedef enum _inputAction { | |||
1492 | noop, | |||
1493 | hold, | |||
1494 | setto, | |||
1495 | deliver, | |||
1496 | release, | |||
1497 | clearto, | |||
1498 | gen_down_2, | |||
1499 | gen_up_2 | |||
1500 | } KdInputAction; | |||
1501 | ||||
1502 | #define MAX_ACTIONS2 2 | |||
1503 | ||||
1504 | typedef struct _inputTransition { | |||
1505 | KdInputAction actions[MAX_ACTIONS2]; | |||
1506 | KdPointerState nextState; | |||
1507 | } KdInputTransition; | |||
1508 | ||||
1509 | static const | |||
1510 | KdInputTransition kdInputMachine[num_input_states][num_input_class] = { | |||
1511 | /* start */ | |||
1512 | { | |||
1513 | {{hold, setto}, button_1_pend}, /* v1 */ | |||
1514 | {{deliver, noop}, start}, /* ^1 */ | |||
1515 | {{deliver, noop}, button_2_down}, /* v2 */ | |||
1516 | {{deliver, noop}, start}, /* ^2 */ | |||
1517 | {{hold, setto}, button_3_pend}, /* v3 */ | |||
1518 | {{deliver, noop}, start}, /* ^3 */ | |||
1519 | {{deliver, noop}, start}, /* vo */ | |||
1520 | {{deliver, noop}, start}, /* ^o */ | |||
1521 | {{deliver, noop}, start}, /* <> */ | |||
1522 | {{deliver, noop}, start}, /* <-> */ | |||
1523 | {{noop, noop}, start}, /* k */ | |||
1524 | {{noop, noop}, start}, /* ... */ | |||
1525 | }, | |||
1526 | /* button_1_pend */ | |||
1527 | { | |||
1528 | {{noop, noop}, button_1_pend}, /* v1 */ | |||
1529 | {{release, deliver}, start}, /* ^1 */ | |||
1530 | {{release, deliver}, button_1_down}, /* v2 */ | |||
1531 | {{release, deliver}, button_1_down}, /* ^2 */ | |||
1532 | {{clearto, gen_down_2}, synth_2_down_13}, /* v3 */ | |||
1533 | {{release, deliver}, button_1_down}, /* ^3 */ | |||
1534 | {{release, deliver}, button_1_down}, /* vo */ | |||
1535 | {{release, deliver}, button_1_down}, /* ^o */ | |||
1536 | {{deliver, noop}, button_1_pend}, /* <> */ | |||
1537 | {{release, deliver}, button_1_down}, /* <-> */ | |||
1538 | {{noop, noop}, button_1_down}, /* k */ | |||
1539 | {{release, noop}, button_1_down}, /* ... */ | |||
1540 | }, | |||
1541 | /* button_1_down */ | |||
1542 | { | |||
1543 | {{noop, noop}, button_1_down}, /* v1 */ | |||
1544 | {{deliver, noop}, start}, /* ^1 */ | |||
1545 | {{deliver, noop}, button_1_down}, /* v2 */ | |||
1546 | {{deliver, noop}, button_1_down}, /* ^2 */ | |||
1547 | {{deliver, noop}, button_1_down}, /* v3 */ | |||
1548 | {{deliver, noop}, button_1_down}, /* ^3 */ | |||
1549 | {{deliver, noop}, button_1_down}, /* vo */ | |||
1550 | {{deliver, noop}, button_1_down}, /* ^o */ | |||
1551 | {{deliver, noop}, button_1_down}, /* <> */ | |||
1552 | {{deliver, noop}, button_1_down}, /* <-> */ | |||
1553 | {{noop, noop}, button_1_down}, /* k */ | |||
1554 | {{noop, noop}, button_1_down}, /* ... */ | |||
1555 | }, | |||
1556 | /* button_2_down */ | |||
1557 | { | |||
1558 | {{deliver, noop}, button_2_down}, /* v1 */ | |||
1559 | {{deliver, noop}, button_2_down}, /* ^1 */ | |||
1560 | {{noop, noop}, button_2_down}, /* v2 */ | |||
1561 | {{deliver, noop}, start}, /* ^2 */ | |||
1562 | {{deliver, noop}, button_2_down}, /* v3 */ | |||
1563 | {{deliver, noop}, button_2_down}, /* ^3 */ | |||
1564 | {{deliver, noop}, button_2_down}, /* vo */ | |||
1565 | {{deliver, noop}, button_2_down}, /* ^o */ | |||
1566 | {{deliver, noop}, button_2_down}, /* <> */ | |||
1567 | {{deliver, noop}, button_2_down}, /* <-> */ | |||
1568 | {{noop, noop}, button_2_down}, /* k */ | |||
1569 | {{noop, noop}, button_2_down}, /* ... */ | |||
1570 | }, | |||
1571 | /* button_3_pend */ | |||
1572 | { | |||
1573 | {{clearto, gen_down_2}, synth_2_down_13}, /* v1 */ | |||
1574 | {{release, deliver}, button_3_down}, /* ^1 */ | |||
1575 | {{release, deliver}, button_3_down}, /* v2 */ | |||
1576 | {{release, deliver}, button_3_down}, /* ^2 */ | |||
1577 | {{release, deliver}, button_3_down}, /* v3 */ | |||
1578 | {{release, deliver}, start}, /* ^3 */ | |||
1579 | {{release, deliver}, button_3_down}, /* vo */ | |||
1580 | {{release, deliver}, button_3_down}, /* ^o */ | |||
1581 | {{deliver, noop}, button_3_pend}, /* <> */ | |||
1582 | {{release, deliver}, button_3_down}, /* <-> */ | |||
1583 | {{release, noop}, button_3_down}, /* k */ | |||
1584 | {{release, noop}, button_3_down}, /* ... */ | |||
1585 | }, | |||
1586 | /* button_3_down */ | |||
1587 | { | |||
1588 | {{deliver, noop}, button_3_down}, /* v1 */ | |||
1589 | {{deliver, noop}, button_3_down}, /* ^1 */ | |||
1590 | {{deliver, noop}, button_3_down}, /* v2 */ | |||
1591 | {{deliver, noop}, button_3_down}, /* ^2 */ | |||
1592 | {{noop, noop}, button_3_down}, /* v3 */ | |||
1593 | {{deliver, noop}, start}, /* ^3 */ | |||
1594 | {{deliver, noop}, button_3_down}, /* vo */ | |||
1595 | {{deliver, noop}, button_3_down}, /* ^o */ | |||
1596 | {{deliver, noop}, button_3_down}, /* <> */ | |||
1597 | {{deliver, noop}, button_3_down}, /* <-> */ | |||
1598 | {{noop, noop}, button_3_down}, /* k */ | |||
1599 | {{noop, noop}, button_3_down}, /* ... */ | |||
1600 | }, | |||
1601 | /* synthetic_2_down_13 */ | |||
1602 | { | |||
1603 | {{noop, noop}, synth_2_down_13}, /* v1 */ | |||
1604 | {{gen_up_2, noop}, synth_2_down_3}, /* ^1 */ | |||
1605 | {{noop, noop}, synth_2_down_13}, /* v2 */ | |||
1606 | {{noop, noop}, synth_2_down_13}, /* ^2 */ | |||
1607 | {{noop, noop}, synth_2_down_13}, /* v3 */ | |||
1608 | {{gen_up_2, noop}, synth_2_down_1}, /* ^3 */ | |||
1609 | {{deliver, noop}, synth_2_down_13}, /* vo */ | |||
1610 | {{deliver, noop}, synth_2_down_13}, /* ^o */ | |||
1611 | {{deliver, noop}, synth_2_down_13}, /* <> */ | |||
1612 | {{deliver, noop}, synth_2_down_13}, /* <-> */ | |||
1613 | {{noop, noop}, synth_2_down_13}, /* k */ | |||
1614 | {{noop, noop}, synth_2_down_13}, /* ... */ | |||
1615 | }, | |||
1616 | /* synthetic_2_down_3 */ | |||
1617 | { | |||
1618 | {{deliver, noop}, synth_2_down_3}, /* v1 */ | |||
1619 | {{deliver, noop}, synth_2_down_3}, /* ^1 */ | |||
1620 | {{deliver, noop}, synth_2_down_3}, /* v2 */ | |||
1621 | {{deliver, noop}, synth_2_down_3}, /* ^2 */ | |||
1622 | {{noop, noop}, synth_2_down_3}, /* v3 */ | |||
1623 | {{noop, noop}, start}, /* ^3 */ | |||
1624 | {{deliver, noop}, synth_2_down_3}, /* vo */ | |||
1625 | {{deliver, noop}, synth_2_down_3}, /* ^o */ | |||
1626 | {{deliver, noop}, synth_2_down_3}, /* <> */ | |||
1627 | {{deliver, noop}, synth_2_down_3}, /* <-> */ | |||
1628 | {{noop, noop}, synth_2_down_3}, /* k */ | |||
1629 | {{noop, noop}, synth_2_down_3}, /* ... */ | |||
1630 | }, | |||
1631 | /* synthetic_2_down_1 */ | |||
1632 | { | |||
1633 | {{noop, noop}, synth_2_down_1}, /* v1 */ | |||
1634 | {{noop, noop}, start}, /* ^1 */ | |||
1635 | {{deliver, noop}, synth_2_down_1}, /* v2 */ | |||
1636 | {{deliver, noop}, synth_2_down_1}, /* ^2 */ | |||
1637 | {{deliver, noop}, synth_2_down_1}, /* v3 */ | |||
1638 | {{deliver, noop}, synth_2_down_1}, /* ^3 */ | |||
1639 | {{deliver, noop}, synth_2_down_1}, /* vo */ | |||
1640 | {{deliver, noop}, synth_2_down_1}, /* ^o */ | |||
1641 | {{deliver, noop}, synth_2_down_1}, /* <> */ | |||
1642 | {{deliver, noop}, synth_2_down_1}, /* <-> */ | |||
1643 | {{noop, noop}, synth_2_down_1}, /* k */ | |||
1644 | {{noop, noop}, synth_2_down_1}, /* ... */ | |||
1645 | }, | |||
1646 | }; | |||
1647 | ||||
1648 | #define EMULATION_WINDOW10 10 | |||
1649 | #define EMULATION_TIMEOUT100 100 | |||
1650 | ||||
1651 | static int | |||
1652 | KdInsideEmulationWindow(KdPointerInfo * pi, int x, int y, int z) | |||
1653 | { | |||
1654 | pi->emulationDx = pi->heldEvent.x - x; | |||
1655 | pi->emulationDy = pi->heldEvent.y - y; | |||
1656 | ||||
1657 | return (abs(pi->emulationDx) < EMULATION_WINDOW10 && | |||
1658 | abs(pi->emulationDy) < EMULATION_WINDOW10); | |||
1659 | } | |||
1660 | ||||
1661 | static KdInputClass | |||
1662 | KdClassifyInput(KdPointerInfo * pi, int type, int x, int y, int z, int b) | |||
1663 | { | |||
1664 | switch (type) { | |||
1665 | case ButtonPress4: | |||
1666 | switch (b) { | |||
1667 | case 1: | |||
1668 | return down_1; | |||
1669 | case 2: | |||
1670 | return down_2; | |||
1671 | case 3: | |||
1672 | return down_3; | |||
1673 | default: | |||
1674 | return down_o; | |||
1675 | } | |||
1676 | break; | |||
1677 | case ButtonRelease5: | |||
1678 | switch (b) { | |||
1679 | case 1: | |||
1680 | return up_1; | |||
1681 | case 2: | |||
1682 | return up_2; | |||
1683 | case 3: | |||
1684 | return up_3; | |||
1685 | default: | |||
1686 | return up_o; | |||
1687 | } | |||
1688 | break; | |||
1689 | case MotionNotify6: | |||
1690 | if (pi->eventHeld && !KdInsideEmulationWindow(pi, x, y, z)) | |||
1691 | return outside_box; | |||
1692 | else | |||
1693 | return motion; | |||
1694 | default: | |||
1695 | return keyboard; | |||
1696 | } | |||
1697 | return keyboard; | |||
1698 | } | |||
1699 | ||||
1700 | /* We return true if we're stealing the event. */ | |||
1701 | static Bool | |||
1702 | KdRunMouseMachine(KdPointerInfo * pi, KdInputClass c, int type, int x, int y, | |||
1703 | int z, int b, int absrel) | |||
1704 | { | |||
1705 | const KdInputTransition *t; | |||
1706 | int a; | |||
1707 | ||||
1708 | c = KdClassifyInput(pi, type, x, y, z, b); | |||
1709 | t = &kdInputMachine[pi->mouseState][c]; | |||
1710 | for (a = 0; a < MAX_ACTIONS2; a++) { | |||
1711 | switch (t->actions[a]) { | |||
1712 | case noop: | |||
1713 | break; | |||
1714 | case hold: | |||
1715 | pi->eventHeld = TRUE1; | |||
1716 | pi->emulationDx = 0; | |||
1717 | pi->emulationDy = 0; | |||
1718 | pi->heldEvent.type = type; | |||
1719 | pi->heldEvent.x = x; | |||
1720 | pi->heldEvent.y = y; | |||
1721 | pi->heldEvent.z = z; | |||
1722 | pi->heldEvent.flags = b; | |||
1723 | pi->heldEvent.absrel = absrel; | |||
1724 | return TRUE1; | |||
1725 | break; | |||
1726 | case setto: | |||
1727 | pi->emulationTimeout = GetTimeInMillis() + EMULATION_TIMEOUT100; | |||
1728 | pi->timeoutPending = TRUE1; | |||
1729 | break; | |||
1730 | case deliver: | |||
1731 | _KdEnqueuePointerEvent(pi, pi->heldEvent.type, pi->heldEvent.x, | |||
1732 | pi->heldEvent.y, pi->heldEvent.z, | |||
1733 | pi->heldEvent.flags, pi->heldEvent.absrel, | |||
1734 | TRUE1); | |||
1735 | break; | |||
1736 | case release: | |||
1737 | pi->eventHeld = FALSE0; | |||
1738 | pi->timeoutPending = FALSE0; | |||
1739 | _KdEnqueuePointerEvent(pi, pi->heldEvent.type, pi->heldEvent.x, | |||
1740 | pi->heldEvent.y, pi->heldEvent.z, | |||
1741 | pi->heldEvent.flags, pi->heldEvent.absrel, | |||
1742 | TRUE1); | |||
1743 | return TRUE1; | |||
1744 | break; | |||
1745 | case clearto: | |||
1746 | pi->timeoutPending = FALSE0; | |||
1747 | break; | |||
1748 | case gen_down_2: | |||
1749 | _KdEnqueuePointerEvent(pi, ButtonPress4, x, y, z, 2, absrel, TRUE1); | |||
1750 | pi->eventHeld = FALSE0; | |||
1751 | return TRUE1; | |||
1752 | break; | |||
1753 | case gen_up_2: | |||
1754 | _KdEnqueuePointerEvent(pi, ButtonRelease5, x, y, z, 2, absrel, TRUE1); | |||
1755 | return TRUE1; | |||
1756 | break; | |||
1757 | } | |||
1758 | } | |||
1759 | pi->mouseState = t->nextState; | |||
1760 | return FALSE0; | |||
1761 | } | |||
1762 | ||||
1763 | static int | |||
1764 | KdHandlePointerEvent(KdPointerInfo * pi, int type, int x, int y, int z, int b, | |||
1765 | int absrel) | |||
1766 | { | |||
1767 | if (pi->emulateMiddleButton) | |||
1768 | return KdRunMouseMachine(pi, KdClassifyInput(pi, type, x, y, z, b), | |||
1769 | type, x, y, z, b, absrel); | |||
1770 | return FALSE0; | |||
1771 | } | |||
1772 | ||||
1773 | static void | |||
1774 | KdReceiveTimeout(KdPointerInfo * pi) | |||
1775 | { | |||
1776 | KdRunMouseMachine(pi, timeout, 0, 0, 0, 0, 0, 0); | |||
1777 | } | |||
1778 | ||||
1779 | /* | |||
1780 | * kdCheckTermination | |||
1781 | * | |||
1782 | * This function checks for the key sequence that terminates the server. When | |||
1783 | * detected, it sets the dispatchException flag and returns. The key sequence | |||
1784 | * is: | |||
1785 | * Control-Alt | |||
1786 | * It's assumed that the server will be waken up by the caller when this | |||
1787 | * function returns. | |||
1788 | */ | |||
1789 | ||||
1790 | extern int nClients; | |||
1791 | ||||
1792 | void | |||
1793 | KdReleaseAllKeys(void) | |||
1794 | { | |||
1795 | #if 0 | |||
1796 | int key; | |||
1797 | KdKeyboardInfo *ki; | |||
1798 | ||||
1799 | input_lock(); | |||
1800 | ||||
1801 | for (ki = kdKeyboards; ki; ki = ki->next) { | |||
1802 | for (key = ki->keySyms.minKeyCode; key < ki->keySyms.maxKeyCode; key++) { | |||
1803 | if (key_is_down(ki->dixdev, key, KEY_POSTED2 | KEY_PROCESSED1)) { | |||
1804 | KdHandleKeyboardEvent(ki, KeyRelease3, key); | |||
1805 | QueueGetKeyboardEvents(ki->dixdev, KeyRelease3, key, NULL((void*)0)); | |||
1806 | } | |||
1807 | } | |||
1808 | } | |||
1809 | ||||
1810 | input_unlock(); | |||
1811 | #endif | |||
1812 | } | |||
1813 | ||||
1814 | static void | |||
1815 | KdCheckLock(void) | |||
1816 | { | |||
1817 | KeyClassPtr keyc = NULL((void*)0); | |||
1818 | Bool isSet = FALSE0, shouldBeSet = FALSE0; | |||
1819 | KdKeyboardInfo *tmp = NULL((void*)0); | |||
1820 | ||||
1821 | for (tmp = kdKeyboards; tmp; tmp = tmp->next) { | |||
1822 | if (tmp->LockLed && tmp->dixdev && tmp->dixdev->key) { | |||
1823 | keyc = tmp->dixdev->key; | |||
1824 | isSet = (tmp->leds & (1 << (tmp->LockLed - 1))) != 0; | |||
1825 | /* FIXME: Just use XKB indicators! */ | |||
1826 | shouldBeSet = | |||
1827 | ! !(XkbStateFieldFromRec(&keyc->xkbInfo->state)(((((&keyc->xkbInfo->state)->group)&0x3)<< 13)|(((&keyc->xkbInfo->state)->lookup_mods)& 0xff)) & LockMask(1<<1)); | |||
1828 | if (isSet != shouldBeSet) | |||
1829 | KdSetLed(tmp, tmp->LockLed, shouldBeSet); | |||
1830 | } | |||
1831 | } | |||
1832 | } | |||
1833 | ||||
1834 | void | |||
1835 | KdEnqueueKeyboardEvent(KdKeyboardInfo * ki, | |||
1836 | unsigned char scan_code, unsigned char is_up) | |||
1837 | { | |||
1838 | unsigned char key_code; | |||
1839 | int type; | |||
1840 | ||||
1841 | if (!ki || !ki->dixdev || !ki->dixdev->kbdfeed || !ki->dixdev->key) | |||
1842 | return; | |||
1843 | ||||
1844 | if (scan_code >= ki->minScanCode && scan_code <= ki->maxScanCode) { | |||
1845 | key_code = scan_code + KD_MIN_KEYCODE8 - ki->minScanCode; | |||
1846 | ||||
1847 | /* | |||
1848 | * Set up this event -- the type may be modified below | |||
1849 | */ | |||
1850 | if (is_up) | |||
1851 | type = KeyRelease3; | |||
1852 | else | |||
1853 | type = KeyPress2; | |||
1854 | ||||
1855 | QueueKeyboardEvents(ki->dixdev, type, key_code); | |||
1856 | } | |||
1857 | else { | |||
1858 | ErrorF("driver %s wanted to post scancode %d outside of [%d, %d]!\n", | |||
1859 | ki->name, scan_code, ki->minScanCode, ki->maxScanCode); | |||
1860 | } | |||
1861 | } | |||
1862 | ||||
1863 | /* | |||
1864 | * kdEnqueuePointerEvent | |||
1865 | * | |||
1866 | * This function converts hardware mouse event information into X event | |||
1867 | * information. A mouse movement event is passed off to MI to generate | |||
1868 | * a MotionNotify event, if appropriate. Button events are created and | |||
1869 | * passed off to MI for enqueueing. | |||
1870 | */ | |||
1871 | ||||
1872 | /* FIXME do something a little more clever to deal with multiple axes here */ | |||
1873 | void | |||
1874 | KdEnqueuePointerEvent(KdPointerInfo * pi, unsigned long flags, int rx, int ry, | |||
1875 | int rz) | |||
1876 | { | |||
1877 | unsigned char buttons; | |||
1878 | int x, y, z; | |||
1879 | int (*matrix)[3] = kdPointerMatrix.matrix; | |||
1880 | unsigned long button; | |||
1881 | int n; | |||
1882 | int dixflags = 0; | |||
1883 | ||||
1884 | if (!pi) | |||
1885 | return; | |||
1886 | ||||
1887 | /* we don't need to transform z, so we don't. */ | |||
1888 | if (flags & KD_MOUSE_DELTA0x80000000) { | |||
1889 | if (pi->transformCoordinates) { | |||
1890 | x = matrix[0][0] * rx + matrix[0][1] * ry; | |||
1891 | y = matrix[1][0] * rx + matrix[1][1] * ry; | |||
1892 | } | |||
1893 | else { | |||
1894 | x = rx; | |||
1895 | y = ry; | |||
1896 | } | |||
1897 | } | |||
1898 | else { | |||
1899 | if (pi->transformCoordinates) { | |||
1900 | x = matrix[0][0] * rx + matrix[0][1] * ry + matrix[0][2]; | |||
1901 | y = matrix[1][0] * rx + matrix[1][1] * ry + matrix[1][2]; | |||
1902 | } | |||
1903 | else { | |||
1904 | x = rx; | |||
1905 | y = ry; | |||
1906 | } | |||
1907 | } | |||
1908 | z = rz; | |||
1909 | ||||
1910 | if (flags & KD_MOUSE_DELTA0x80000000) { | |||
1911 | if (x || y || z) { | |||
1912 | dixflags = POINTER_RELATIVE(1 << 1) | POINTER_ACCELERATE(1 << 3); | |||
1913 | _KdEnqueuePointerEvent(pi, MotionNotify6, x, y, z, 0, dixflags, | |||
1914 | FALSE0); | |||
1915 | } | |||
1916 | } | |||
1917 | else { | |||
1918 | dixflags = POINTER_ABSOLUTE(1 << 2); | |||
1919 | if (flags & KD_POINTER_DESKTOP0x40000000) | |||
1920 | dixflags |= POINTER_DESKTOP(1 << 7); | |||
1921 | if (x != pi->dixdev->last.valuators[0] || | |||
1922 | y != pi->dixdev->last.valuators[1]) | |||
1923 | _KdEnqueuePointerEvent(pi, MotionNotify6, x, y, z, 0, dixflags, | |||
1924 | FALSE0); | |||
1925 | } | |||
1926 | ||||
1927 | buttons = flags; | |||
1928 | ||||
1929 | for (button = KD_BUTTON_10x01, n = 1; n <= pi->nButtons; button <<= 1, n++) { | |||
1930 | if (((pi->buttonState & button) ^ (buttons & button)) && | |||
1931 | !(buttons & button)) { | |||
1932 | _KdEnqueuePointerEvent(pi, ButtonRelease5, x, y, z, n, | |||
1933 | dixflags, FALSE0); | |||
1934 | } | |||
1935 | } | |||
1936 | for (button = KD_BUTTON_10x01, n = 1; n <= pi->nButtons; button <<= 1, n++) { | |||
1937 | if (((pi->buttonState & button) ^ (buttons & button)) && | |||
1938 | (buttons & button)) { | |||
1939 | _KdEnqueuePointerEvent(pi, ButtonPress4, x, y, z, n, | |||
1940 | dixflags, FALSE0); | |||
1941 | } | |||
1942 | } | |||
1943 | ||||
1944 | pi->buttonState = buttons; | |||
1945 | } | |||
1946 | ||||
1947 | void | |||
1948 | _KdEnqueuePointerEvent(KdPointerInfo * pi, int type, int x, int y, int z, | |||
1949 | int b, int absrel, Bool force) | |||
1950 | { | |||
1951 | int valuators[3] = { x, y, z }; | |||
1952 | ValuatorMask mask; | |||
1953 | ||||
1954 | /* TRUE from KdHandlePointerEvent, means 'we swallowed the event'. */ | |||
1955 | if (!force && KdHandlePointerEvent(pi, type, x, y, z, b, absrel)) | |||
1956 | return; | |||
1957 | ||||
1958 | valuator_mask_set_range(&mask, 0, 3, valuators); | |||
1959 | ||||
1960 | QueuePointerEvents(pi->dixdev, type, b, absrel, &mask); | |||
1961 | } | |||
1962 | ||||
1963 | void | |||
1964 | KdBlockHandler(ScreenPtr pScreen, void *timeo, void *readmask) | |||
1965 | { | |||
1966 | KdPointerInfo *pi; | |||
1967 | int myTimeout = 0; | |||
1968 | ||||
1969 | for (pi = kdPointers; pi; pi = pi->next) { | |||
1970 | if (pi->timeoutPending) { | |||
1971 | int ms; | |||
1972 | ||||
1973 | ms = pi->emulationTimeout - GetTimeInMillis(); | |||
1974 | if (ms < 1) | |||
1975 | ms = 1; | |||
1976 | if (ms < myTimeout || myTimeout == 0) | |||
1977 | myTimeout = ms; | |||
1978 | } | |||
1979 | } | |||
1980 | /* if we need to poll for events, do that */ | |||
1981 | if (kdOsFuncs->pollEvents) { | |||
1982 | (*kdOsFuncs->pollEvents) (); | |||
1983 | myTimeout = 20; | |||
1984 | } | |||
1985 | if (myTimeout > 0) | |||
1986 | AdjustWaitForDelay(timeo, myTimeout); | |||
1987 | } | |||
1988 | ||||
1989 | void | |||
1990 | KdWakeupHandler(ScreenPtr pScreen, unsigned long lresult, void *readmask) | |||
1991 | { | |||
1992 | KdPointerInfo *pi; | |||
1993 | ||||
1994 | for (pi = kdPointers; pi; pi = pi->next) { | |||
1995 | if (pi->timeoutPending) { | |||
1996 | if ((long) (GetTimeInMillis() - pi->emulationTimeout) >= 0) { | |||
1997 | pi->timeoutPending = FALSE0; | |||
1998 | input_lock(); | |||
1999 | KdReceiveTimeout(pi); | |||
2000 | input_unlock(); | |||
2001 | } | |||
2002 | } | |||
2003 | } | |||
2004 | if (kdSwitchPending) | |||
2005 | KdProcessSwitch(); | |||
2006 | } | |||
2007 | ||||
2008 | #define KdScreenOrigin(pScreen)(&(((KdPrivScreenPtr) dixLookupPrivate(&(pScreen)-> devPrivates, (&kdScreenPrivateKeyRec)))->screen->origin )) (&(KdGetScreenPriv(pScreen)((KdPrivScreenPtr) dixLookupPrivate(&(pScreen)->devPrivates , (&kdScreenPrivateKeyRec)))->screen->origin)) | |||
2009 | ||||
2010 | static Bool | |||
2011 | KdCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y) | |||
2012 | { | |||
2013 | ScreenPtr pScreen = *ppScreen; | |||
2014 | ScreenPtr pNewScreen; | |||
2015 | int n; | |||
2016 | int dx, dy; | |||
2017 | int best_x, best_y; | |||
2018 | int n_best_x, n_best_y; | |||
2019 | CARD32 ms; | |||
2020 | ||||
2021 | if (kdDisableZaphod || screenInfo.numScreens <= 1) | |||
2022 | return FALSE0; | |||
2023 | ||||
2024 | if (0 <= *x && *x < pScreen->width && 0 <= *y && *y < pScreen->height) | |||
2025 | return FALSE0; | |||
2026 | ||||
2027 | ms = GetTimeInMillis(); | |||
2028 | if (kdOffScreen && (int) (ms - kdOffScreenTime) < 1000) | |||
2029 | return FALSE0; | |||
2030 | kdOffScreen = TRUE1; | |||
2031 | kdOffScreenTime = ms; | |||
2032 | n_best_x = -1; | |||
2033 | best_x = 32767; | |||
2034 | n_best_y = -1; | |||
2035 | best_y = 32767; | |||
2036 | for (n = 0; n < screenInfo.numScreens; n++) { | |||
2037 | pNewScreen = screenInfo.screens[n]; | |||
2038 | if (pNewScreen == pScreen) | |||
2039 | continue; | |||
2040 | dx = KdScreenOrigin(pNewScreen)(&(((KdPrivScreenPtr) dixLookupPrivate(&(pNewScreen)-> devPrivates, (&kdScreenPrivateKeyRec)))->screen->origin ))->x - KdScreenOrigin(pScreen)(&(((KdPrivScreenPtr) dixLookupPrivate(&(pScreen)-> devPrivates, (&kdScreenPrivateKeyRec)))->screen->origin ))->x; | |||
2041 | dy = KdScreenOrigin(pNewScreen)(&(((KdPrivScreenPtr) dixLookupPrivate(&(pNewScreen)-> devPrivates, (&kdScreenPrivateKeyRec)))->screen->origin ))->y - KdScreenOrigin(pScreen)(&(((KdPrivScreenPtr) dixLookupPrivate(&(pScreen)-> devPrivates, (&kdScreenPrivateKeyRec)))->screen->origin ))->y; | |||
2042 | if (*x < 0) { | |||
2043 | if (dx < 0 && -dx < best_x) { | |||
2044 | best_x = -dx; | |||
2045 | n_best_x = n; | |||
2046 | } | |||
2047 | } | |||
2048 | else if (*x >= pScreen->width) { | |||
2049 | if (dx > 0 && dx < best_x) { | |||
2050 | best_x = dx; | |||
2051 | n_best_x = n; | |||
2052 | } | |||
2053 | } | |||
2054 | if (*y < 0) { | |||
2055 | if (dy < 0 && -dy < best_y) { | |||
2056 | best_y = -dy; | |||
2057 | n_best_y = n; | |||
2058 | } | |||
2059 | } | |||
2060 | else if (*y >= pScreen->height) { | |||
2061 | if (dy > 0 && dy < best_y) { | |||
2062 | best_y = dy; | |||
2063 | n_best_y = n; | |||
2064 | } | |||
2065 | } | |||
2066 | } | |||
2067 | if (best_y < best_x) | |||
2068 | n_best_x = n_best_y; | |||
2069 | if (n_best_x == -1) | |||
2070 | return FALSE0; | |||
2071 | pNewScreen = screenInfo.screens[n_best_x]; | |||
2072 | ||||
2073 | if (*x < 0) | |||
2074 | *x += pNewScreen->width; | |||
2075 | if (*y < 0) | |||
2076 | *y += pNewScreen->height; | |||
2077 | ||||
2078 | if (*x >= pScreen->width) | |||
2079 | *x -= pScreen->width; | |||
2080 | if (*y >= pScreen->height) | |||
2081 | *y -= pScreen->height; | |||
2082 | ||||
2083 | *ppScreen = pNewScreen; | |||
2084 | return TRUE1; | |||
2085 | } | |||
2086 | ||||
2087 | static void | |||
2088 | KdCrossScreen(ScreenPtr pScreen, Bool entering) | |||
2089 | { | |||
2090 | } | |||
2091 | ||||
2092 | int KdCurScreen; /* current event screen */ | |||
2093 | ||||
2094 | static void | |||
2095 | KdWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) | |||
2096 | { | |||
2097 | input_lock(); | |||
2098 | KdCurScreen = pScreen->myNum; | |||
2099 | miPointerWarpCursor(pDev, pScreen, x, y); | |||
2100 | input_unlock(); | |||
2101 | } | |||
2102 | ||||
2103 | miPointerScreenFuncRec kdPointerScreenFuncs = { | |||
2104 | KdCursorOffScreen, | |||
2105 | KdCrossScreen, | |||
2106 | KdWarpCursor | |||
2107 | }; | |||
2108 | ||||
2109 | void | |||
2110 | ProcessInputEvents(void) | |||
2111 | { | |||
2112 | mieqProcessInputEvents(); | |||
2113 | if (kdSwitchPending) | |||
2114 | KdProcessSwitch(); | |||
2115 | KdCheckLock(); | |||
2116 | } | |||
2117 | ||||
2118 | /* At the moment, absolute/relative is up to the client. */ | |||
2119 | int | |||
2120 | SetDeviceMode(register ClientPtr client, DeviceIntPtr pDev, int mode) | |||
2121 | { | |||
2122 | return BadMatch8; | |||
2123 | } | |||
2124 | ||||
2125 | int | |||
2126 | SetDeviceValuators(register ClientPtr client, DeviceIntPtr pDev, | |||
2127 | int *valuators, int first_valuator, int num_valuators) | |||
2128 | { | |||
2129 | return BadMatch8; | |||
2130 | } | |||
2131 | ||||
2132 | int | |||
2133 | ChangeDeviceControl(register ClientPtr client, DeviceIntPtr pDev, | |||
2134 | xDeviceCtl * control) | |||
2135 | { | |||
2136 | switch (control->control) { | |||
2137 | case DEVICE_RESOLUTION1: | |||
2138 | /* FIXME do something more intelligent here */ | |||
2139 | return BadMatch8; | |||
2140 | ||||
2141 | case DEVICE_ABS_CALIB2: | |||
2142 | case DEVICE_ABS_AREA5: | |||
2143 | case DEVICE_CORE3: | |||
2144 | return BadMatch8; | |||
2145 | case DEVICE_ENABLE4: | |||
2146 | return Success0; | |||
2147 | ||||
2148 | default: | |||
2149 | return BadMatch8; | |||
2150 | } | |||
2151 | ||||
2152 | /* NOTREACHED */ | |||
2153 | return BadImplementation17; | |||
2154 | } | |||
2155 | ||||
2156 | int | |||
2157 | NewInputDeviceRequest(InputOption *options, InputAttributes * attrs, | |||
2158 | DeviceIntPtr *pdev) | |||
2159 | { | |||
2160 | InputOption *option = NULL((void*)0), *optionsdup = NULL((void*)0); | |||
2161 | KdPointerInfo *pi = NULL((void*)0); | |||
2162 | KdKeyboardInfo *ki = NULL((void*)0); | |||
2163 | ||||
2164 | nt_list_for_each_entry(option, options, list.next)for (option = options; option; option = (option)->list.next ) { | |||
2165 | const char *key = input_option_get_key(option); | |||
2166 | const char *value = input_option_get_value(option); | |||
2167 | optionsdup = input_option_new(optionsdup, key, value); | |||
2168 | ||||
2169 | if (strcmp(key, "type") == 0) { | |||
2170 | if (strcmp(value, "pointer") == 0) { | |||
2171 | pi = KdNewPointer(); | |||
2172 | if (!pi) { | |||
2173 | input_option_free_list(&optionsdup); | |||
2174 | return BadAlloc11; | |||
2175 | } | |||
2176 | } | |||
2177 | else if (strcmp(value, "keyboard") == 0) { | |||
2178 | ki = KdNewKeyboard(); | |||
2179 | if (!ki) { | |||
2180 | input_option_free_list(&optionsdup); | |||
2181 | return BadAlloc11; | |||
2182 | } | |||
2183 | } | |||
2184 | else { | |||
2185 | ErrorF("unrecognised device type!\n"); | |||
2186 | return BadValue2; | |||
2187 | } | |||
2188 | } | |||
2189 | #ifdef CONFIG_HAL | |||
2190 | else if (strcmp(key, "_source") == 0 && | |||
2191 | strcmp(value, "server/hal") == 0) { | |||
2192 | if (SeatId) { | |||
2193 | /* Input hot-plugging is enabled */ | |||
2194 | if (attrs->flags & ATTR_POINTER(1<<1)) { | |||
2195 | pi = KdNewPointer(); | |||
2196 | if (!pi) { | |||
2197 | input_option_free_list(&optionsdup); | |||
2198 | return BadAlloc11; | |||
2199 | } | |||
2200 | } | |||
2201 | else if (attrs->flags & ATTR_KEYBOARD(1<<0)) { | |||
2202 | ki = KdNewKeyboard(); | |||
2203 | if (!ki) { | |||
2204 | input_option_free_list(&optionsdup); | |||
2205 | return BadAlloc11; | |||
2206 | } | |||
2207 | } | |||
2208 | } | |||
2209 | else { | |||
2210 | ErrorF("Ignoring device from HAL.\n"); | |||
2211 | input_option_free_list(&optionsdup); | |||
2212 | return BadValue2; | |||
2213 | } | |||
2214 | } | |||
2215 | #endif | |||
2216 | #ifdef CONFIG_UDEV | |||
2217 | else if (strcmp(key, "_source") == 0 && | |||
2218 | strcmp(value, "server/udev") == 0) { | |||
2219 | if (SeatId) { | |||
2220 | /* Input hot-plugging is enabled */ | |||
2221 | if (attrs->flags & ATTR_POINTER(1<<1)) { | |||
2222 | pi = KdNewPointer(); | |||
2223 | if (!pi) { | |||
2224 | input_option_free_list(&optionsdup); | |||
2225 | return BadAlloc11; | |||
2226 | } | |||
2227 | } | |||
2228 | else if (attrs->flags & ATTR_KEYBOARD(1<<0)) { | |||
2229 | ki = KdNewKeyboard(); | |||
2230 | if (!ki) { | |||
2231 | input_option_free_list(&optionsdup); | |||
2232 | return BadAlloc11; | |||
2233 | } | |||
2234 | } | |||
2235 | } | |||
2236 | else { | |||
2237 | ErrorF("Ignoring device from udev.\n"); | |||
2238 | input_option_free_list(&optionsdup); | |||
2239 | return BadValue2; | |||
2240 | } | |||
2241 | } | |||
2242 | #endif | |||
2243 | } | |||
2244 | ||||
2245 | if (pi) { | |||
2246 | pi->options = optionsdup; | |||
2247 | KdParsePointerOptions(pi); | |||
2248 | ||||
2249 | if (!pi->driver) { | |||
2250 | ErrorF("couldn't find driver for pointer device \"%s\" (%s)\n", | |||
2251 | pi->name ? pi->name : "(unnamed)", pi->path); | |||
2252 | KdFreePointer(pi); | |||
2253 | return BadValue2; | |||
2254 | } | |||
2255 | ||||
2256 | if (KdAddPointer(pi) != Success0 || | |||
2257 | ActivateDevice(pi->dixdev, TRUE1) != Success0 || | |||
2258 | EnableDevice(pi->dixdev, TRUE1) != TRUE1) { | |||
2259 | ErrorF("couldn't add or enable pointer \"%s\" (%s)\n", | |||
2260 | pi->name ? pi->name : "(unnamed)", pi->path); | |||
2261 | KdFreePointer(pi); | |||
2262 | return BadImplementation17; | |||
2263 | } | |||
2264 | ||||
2265 | *pdev = pi->dixdev; | |||
2266 | } | |||
2267 | else if (ki) { | |||
2268 | ki->options = optionsdup; | |||
2269 | KdParseKbdOptions(ki); | |||
2270 | ||||
2271 | if (!ki->driver) { | |||
2272 | ErrorF("couldn't find driver for keyboard device \"%s\" (%s)\n", | |||
2273 | ki->name ? ki->name : "(unnamed)", ki->path); | |||
2274 | KdFreeKeyboard(ki); | |||
2275 | return BadValue2; | |||
2276 | } | |||
2277 | ||||
2278 | if (KdAddKeyboard(ki) != Success0 || | |||
2279 | ActivateDevice(ki->dixdev, TRUE1) != Success0 || | |||
2280 | EnableDevice(ki->dixdev, TRUE1) != TRUE1) { | |||
2281 | ErrorF("couldn't add or enable keyboard \"%s\" (%s)\n", | |||
2282 | ki->name ? ki->name : "(unnamed)", ki->path); | |||
2283 | KdFreeKeyboard(ki); | |||
2284 | return BadImplementation17; | |||
2285 | } | |||
2286 | ||||
2287 | *pdev = ki->dixdev; | |||
2288 | } | |||
2289 | else { | |||
2290 | ErrorF("unrecognised device identifier: %s\n", | |||
2291 | input_option_get_value(input_option_find(optionsdup, | |||
2292 | "device"))); | |||
2293 | input_option_free_list(&optionsdup); | |||
2294 | return BadValue2; | |||
2295 | } | |||
2296 | ||||
2297 | return Success0; | |||
2298 | } | |||
2299 | ||||
2300 | void | |||
2301 | DeleteInputDeviceRequest(DeviceIntPtr pDev) | |||
2302 | { | |||
2303 | RemoveDevice(pDev, TRUE1); | |||
2304 | } |