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