Commit | Line | Data |
---|---|---|
a09e091a JB |
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_H | |
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) | |
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; | |
63 | static KdPointerInfo *kdPointers = NULL; | |
64 | static struct KdConfigDevice *kdConfigKeyboards = NULL; | |
65 | static struct KdConfigDevice *kdConfigPointers = NULL; | |
66 | ||
67 | static KdKeyboardDriver *kdKeyboardDrivers = NULL; | |
68 | static KdPointerDriver *kdPointerDrivers = NULL; | |
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_FDS 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_FDS]; | |
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); | |
113 | sigprocmask(SIG_BLOCK, &set, &old); | |
114 | if (!sigismember(&old, SIGIO)) { | |
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 FNONBLOCK | |
129 | #define NOBLOCK FNONBLOCK | |
130 | #else | |
131 | #define NOBLOCK FNDELAY | |
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 = FALSE; | |
142 | } | |
143 | } | |
144 | ||
145 | static void | |
146 | KdNonBlockFd(int fd) | |
147 | { | |
148 | int flags; | |
149 | ||
150 | flags = fcntl(fd, F_GETFL); | |
151 | flags |= FASYNC | NOBLOCK; | |
152 | fcntl(fd, F_SETFL, 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_SETOWN, getpid()); | |
163 | KdNonBlockFd(fd); | |
164 | AddEnabledDevice(fd); | |
165 | memset(&act, '\0', sizeof act); | |
166 | act.sa_handler = KdSigio; | |
167 | sigemptyset(&act.sa_mask); | |
168 | sigaddset(&act.sa_mask, SIGIO); | |
169 | sigaddset(&act.sa_mask, SIGALRM); | |
170 | sigaddset(&act.sa_mask, SIGVTALRM); | |
171 | sigaction(SIGIO, &act, 0); | |
172 | sigemptyset(&set); | |
173 | sigprocmask(SIG_SETMASK, &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_GETFL); | |
185 | flags &= ~(FASYNC | NOBLOCK); | |
186 | fcntl(fd, F_SETFL, flags); | |
187 | if (kdnFds == 0) { | |
188 | memset(&act, '\0', sizeof act); | |
189 | act.sa_handler = SIG_IGN; | |
190 | sigemptyset(&act.sa_mask); | |
191 | sigaction(SIGIO, &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_FDS) | |
199 | return FALSE; | |
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 TRUE; | |
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 | kdNumInputFds--; | |
224 | for (j = i; j < (kdNumInputFds - 1); j++) | |
225 | kdInputFds[j] = kdInputFds[j + 1]; | |
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, TRUE); | |
296 | } | |
297 | } | |
298 | ||
299 | kdInputEnabled = FALSE; | |
300 | } | |
301 | ||
302 | void | |
303 | KdEnableInput(void) | |
304 | { | |
305 | InternalEvent ev; | |
306 | KdKeyboardInfo *ki; | |
307 | KdPointerInfo *pi; | |
308 | ||
309 | kdInputEnabled = TRUE; | |
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; | |
338 | ||
339 | for (ret = kdKeyboardDrivers; ret; ret = ret->next) { | |
340 | if (strcmp(ret->name, name) == 0) | |
341 | return ret; | |
342 | } | |
343 | ||
344 | return NULL; | |
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; | |
355 | ||
356 | for (ret = kdPointerDrivers; ret; ret = ret->next) { | |
357 | if (strcmp(ret->name, name) == 0) | |
358 | return ret; | |
359 | } | |
360 | ||
361 | return NULL; | |
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 BadImplementation; | |
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 BadImplementation; | |
385 | } | |
386 | ||
387 | switch (onoff) { | |
388 | case DEVICE_INIT: | |
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 BadImplementation; | |
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 !Success; | |
404 | } | |
405 | free(pi->driverPrivate); | |
406 | pi->driverPrivate = NULL; | |
407 | } | |
408 | ||
409 | if (!pi->driver->Init) { | |
410 | ErrorF("no init function\n"); | |
411 | return BadImplementation; | |
412 | } | |
413 | ||
414 | if ((*pi->driver->Init) (pi) != Success) { | |
415 | return !Success; | |
416 | } | |
417 | ||
418 | btn_labels = calloc(pi->nButtons, sizeof(Atom)); | |
419 | if (!btn_labels) | |
420 | return BadAlloc; | |
421 | axes_labels = calloc(pi->nAxes, sizeof(Atom)); | |
422 | if (!axes_labels) { | |
423 | free(btn_labels); | |
424 | return BadAlloc; | |
425 | } | |
426 | ||
427 | switch (pi->nAxes) { | |
428 | default: | |
429 | case 7: | |
430 | btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT); | |
431 | case 6: | |
432 | btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT); | |
433 | case 5: | |
434 | btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN); | |
435 | case 4: | |
436 | btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP); | |
437 | case 3: | |
438 | btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); | |
439 | case 2: | |
440 | btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); | |
441 | case 1: | |
442 | btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT); | |
443 | case 0: | |
444 | break; | |
445 | } | |
446 | ||
447 | if (pi->nAxes >= 2) { | |
448 | axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X); | |
449 | axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_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_TOUCHSCREEN) { | |
460 | xiclass = AtomFromName(XI_TOUCHSCREEN); | |
461 | } | |
462 | else { | |
463 | xiclass = AtomFromName(XI_MOUSE); | |
464 | } | |
465 | ||
466 | AssignTypeAndName(pi->dixdev, xiclass, | |
467 | pi->name ? pi->name : "Generic KDrive Pointer"); | |
468 | ||
469 | return Success; | |
470 | ||
471 | case DEVICE_ON: | |
472 | if (pDev->on == TRUE) | |
473 | return Success; | |
474 | ||
475 | if (!pi->driver->Enable) { | |
476 | ErrorF("no enable function\n"); | |
477 | return BadImplementation; | |
478 | } | |
479 | ||
480 | if ((*pi->driver->Enable) (pi) == Success) { | |
481 | pDev->on = TRUE; | |
482 | return Success; | |
483 | } | |
484 | else { | |
485 | return BadImplementation; | |
486 | } | |
487 | ||
488 | return Success; | |
489 | ||
490 | case DEVICE_OFF: | |
491 | if (pDev->on == FALSE) { | |
492 | return Success; | |
493 | } | |
494 | ||
495 | if (!pi->driver->Disable) { | |
496 | return BadImplementation; | |
497 | } | |
498 | else { | |
499 | (*pi->driver->Disable) (pi); | |
500 | pDev->on = FALSE; | |
501 | return Success; | |
502 | } | |
503 | ||
504 | return Success; | |
505 | ||
506 | case DEVICE_CLOSE: | |
507 | if (pDev->on) { | |
508 | if (!pi->driver->Disable) { | |
509 | return BadImplementation; | |
510 | } | |
511 | (*pi->driver->Disable) (pi); | |
512 | pDev->on = FALSE; | |
513 | } | |
514 | ||
515 | if (!pi->driver->Fini) | |
516 | return BadImplementation; | |
517 | ||
518 | (*pi->driver->Fini) (pi); | |
519 | ||
520 | KdRemovePointer(pi); | |
521 | ||
522 | return Success; | |
523 | } | |
524 | ||
525 | /* NOTREACHED */ | |
526 | return BadImplementation; | |
527 | } | |
528 | ||
529 | Bool | |
530 | LegalModifier(unsigned int key, DeviceIntPtr pDev) | |
531 | { | |
532 | return TRUE; | |
533 | } | |
534 | ||
535 | static void | |
536 | KdBell(int volume, DeviceIntPtr pDev, pointer arg, int something) | |
537 | { | |
538 | KeybdCtrl *ctrl = arg; | |
539 | KdKeyboardInfo *ki = NULL; | |
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; | |
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_X) | |
617 | x_dir = -1; | |
618 | if (randr & RR_Reflect_Y) | |
619 | y_dir = -1; | |
620 | switch (randr & (RR_Rotate_All)) { | |
621 | case RR_Rotate_0: | |
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_90: | |
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_180: | |
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_270: | |
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 BadImplementation; | |
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 BadImplementation; | |
705 | } | |
706 | ||
707 | switch (onoff) { | |
708 | case DEVICE_INIT: | |
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 BadImplementation; | |
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 !Success; | |
724 | } | |
725 | free(ki->driverPrivate); | |
726 | ki->driverPrivate = NULL; | |
727 | } | |
728 | ||
729 | if (!ki->driver->Init) { | |
730 | ErrorF("Keyboard %s: no init function\n", ki->name); | |
731 | return BadImplementation; | |
732 | } | |
733 | ||
734 | if ((*ki->driver->Init) (ki) != Success) { | |
735 | return !Success; | |
736 | } | |
737 | ||
738 | memset(&rmlvo, 0, sizeof(rmlvo)); | |
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 BadImplementation; | |
748 | } | |
749 | ||
750 | xiclass = AtomFromName(XI_KEYBOARD); | |
751 | AssignTypeAndName(pDevice, xiclass, | |
752 | ki->name ? ki->name : "Generic KDrive Keyboard"); | |
753 | ||
754 | KdResetInputMachine(); | |
755 | ||
756 | return Success; | |
757 | ||
758 | case DEVICE_ON: | |
759 | if (pDev->on == TRUE) | |
760 | return Success; | |
761 | ||
762 | if (!ki->driver->Enable) | |
763 | return BadImplementation; | |
764 | ||
765 | if ((*ki->driver->Enable) (ki) != Success) { | |
766 | return BadMatch; | |
767 | } | |
768 | ||
769 | pDev->on = TRUE; | |
770 | return Success; | |
771 | ||
772 | case DEVICE_OFF: | |
773 | if (pDev->on == FALSE) | |
774 | return Success; | |
775 | ||
776 | if (!ki->driver->Disable) | |
777 | return BadImplementation; | |
778 | ||
779 | (*ki->driver->Disable) (ki); | |
780 | pDev->on = FALSE; | |
781 | ||
782 | return Success; | |
783 | ||
784 | break; | |
785 | ||
786 | case DEVICE_CLOSE: | |
787 | if (pDev->on) { | |
788 | if (!ki->driver->Disable) | |
789 | return BadImplementation; | |
790 | ||
791 | (*ki->driver->Disable) (ki); | |
792 | pDev->on = FALSE; | |
793 | } | |
794 | ||
795 | if (!ki->driver->Fini) | |
796 | return BadImplementation; | |
797 | ||
798 | (*ki->driver->Fini) (ki); | |
799 | ||
800 | KdRemoveKeyboard(ki); | |
801 | ||
802 | return Success; | |
803 | } | |
804 | ||
805 | /* NOTREACHED */ | |
806 | return BadImplementation; | |
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; | |
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; | |
871 | } | |
872 | ||
873 | KdKeyboardInfo * | |
874 | KdNewKeyboard(void) | |
875 | { | |
876 | KdKeyboardInfo *ki = calloc(sizeof(KdKeyboardInfo), 1); | |
877 | ||
878 | if (!ki) | |
879 | return NULL; | |
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; | |
887 | ki->options = NULL; | |
888 | ki->xkbRules = strdup(XKB_DFLT_RULES); | |
889 | ki->xkbModel = strdup(XKB_DFLT_MODEL); | |
890 | ki->xkbLayout = strdup(XKB_DFLT_LAYOUT); | |
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 Success; | |
904 | ||
905 | new = (struct KdConfigDevice *) calloc(sizeof(struct KdConfigDevice), 1); | |
906 | if (!new) | |
907 | return BadAlloc; | |
908 | ||
909 | new->line = strdup(keyboard); | |
910 | new->next = NULL; | |
911 | ||
912 | for (prev = &kdConfigKeyboards; *prev; prev = &(*prev)->next); | |
913 | *prev = new; | |
914 | ||
915 | return Success; | |
916 | } | |
917 | ||
918 | int | |
919 | KdAddKeyboard(KdKeyboardInfo * ki) | |
920 | { | |
921 | KdKeyboardInfo **prev; | |
922 | ||
923 | if (!ki) | |
924 | return !Success; | |
925 | ||
926 | ki->dixdev = AddInputDevice(serverClient, KdKeyboardProc, TRUE); | |
927 | if (!ki->dixdev) { | |
928 | ErrorF("Couldn't register keyboard device %s\n", | |
929 | ki->name ? ki->name : "(unnamed)"); | |
930 | return !Success; | |
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 Success; | |
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 Success; | |
968 | ||
969 | new = (struct KdConfigDevice *) calloc(sizeof(struct KdConfigDevice), 1); | |
970 | if (!new) | |
971 | return BadAlloc; | |
972 | ||
973 | new->line = strdup(pointer); | |
974 | new->next = NULL; | |
975 | ||
976 | for (prev = &kdConfigPointers; *prev; prev = &(*prev)->next); | |
977 | *prev = new; | |
978 | ||
979 | return Success; | |
980 | } | |
981 | ||
982 | int | |
983 | KdAddPointer(KdPointerInfo * pi) | |
984 | { | |
985 | KdPointerInfo **prev; | |
986 | ||
987 | if (!pi) | |
988 | return Success; | |
989 | ||
990 | pi->mouseState = start; | |
991 | pi->eventHeld = FALSE; | |
992 | ||
993 | pi->dixdev = AddInputDevice(serverClient, KdPointerProc, TRUE); | |
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 Success; | |
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; | |
1033 | char *key = NULL, *value = NULL; | |
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; | |
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); | |
1060 | } | |
1061 | ||
1062 | static void | |
1063 | KdParseKbdOptions(KdKeyboardInfo * ki) | |
1064 | { | |
1065 | InputOption *option = NULL; | |
1066 | ||
1067 | nt_list_for_each_entry(option, ki->options, 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; | |
1095 | KdKeyboardInfo *ki = NULL; | |
1096 | ||
1097 | ki = KdNewKeyboard(); | |
1098 | if (!ki) | |
1099 | return NULL; | |
1100 | ||
1101 | ki->name = strdup("Unknown KDrive Keyboard"); | |
1102 | ki->path = NULL; | |
1103 | ki->driver = NULL; | |
1104 | ki->driverPrivate = NULL; | |
1105 | ki->next = NULL; | |
1106 | ||
1107 | if (!arg) { | |
1108 | ErrorF("keybd: no arg\n"); | |
1109 | KdFreeKeyboard(ki); | |
1110 | return NULL; | |
1111 | } | |
1112 | ||
1113 | if (strlen(arg) >= sizeof(save)) { | |
1114 | ErrorF("keybd: arg too long\n"); | |
1115 | KdFreeKeyboard(ki); | |
1116 | return NULL; | |
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; | |
1124 | } | |
1125 | ||
1126 | if (strcmp(save, "auto") == 0) | |
1127 | ki->driverPrivate = NULL; | |
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; | |
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; | |
1158 | ||
1159 | nt_list_for_each_entry(option, pi->options, 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 = TRUE; | |
1165 | else if (!strcmp(key, "noemulatemiddle")) | |
1166 | pi->emulateMiddleButton = FALSE; | |
1167 | else if (!strcmp(key, "transformcoord")) | |
1168 | pi->transformCoordinates = TRUE; | |
1169 | else if (!strcmp(key, "rawcoord")) | |
1170 | pi->transformCoordinates = FALSE; | |
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; | |
1187 | InputOption *options = NULL; | |
1188 | int i = 0; | |
1189 | ||
1190 | pi = KdNewPointer(); | |
1191 | if (!pi) | |
1192 | return NULL; | |
1193 | pi->emulateMiddleButton = kdEmulateMiddleButton; | |
1194 | pi->transformCoordinates = !kdRawPointerCoordinates; | |
1195 | pi->protocol = NULL; | |
1196 | pi->nButtons = 5; /* XXX should not be hardcoded */ | |
1197 | pi->inputClass = KD_MOUSE; | |
1198 | ||
1199 | if (!arg) { | |
1200 | ErrorF("mouse: no arg\n"); | |
1201 | KdFreePointer(pi); | |
1202 | return NULL; | |
1203 | } | |
1204 | ||
1205 | if (strlen(arg) >= sizeof(save)) { | |
1206 | ErrorF("mouse: arg too long\n"); | |
1207 | KdFreePointer(pi); | |
1208 | return NULL; | |
1209 | } | |
1210 | arg = KdParseFindNext(arg, ",", save, &delim); | |
1211 | if (!save[0]) { | |
1212 | ErrorF("failed on save[0]\n"); | |
1213 | KdFreePointer(pi); | |
1214 | return NULL; | |
1215 | } | |
1216 | ||
1217 | if (strcmp(save, "auto") == 0) | |
1218 | pi->driverPrivate = NULL; | |
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; | |
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 = TRUE; | |
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) != Success) | |
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) != Success) | |
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_ACTIONS 2 | |
1447 | ||
1448 | typedef struct _inputTransition { | |
1449 | KdInputAction actions[MAX_ACTIONS]; | |
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_WINDOW 10 | |
1593 | #define EMULATION_TIMEOUT 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_WINDOW && | |
1602 | abs(pi->emulationDy) < EMULATION_WINDOW); | |
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 ButtonPress: | |
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 ButtonRelease: | |
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 MotionNotify: | |
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 | #ifdef DEBUG | |
1645 | char *kdStateNames[] = { | |
1646 | "start", | |
1647 | "button_1_pend", | |
1648 | "button_1_down", | |
1649 | "button_2_down", | |
1650 | "button_3_pend", | |
1651 | "button_3_down", | |
1652 | "synth_2_down_13", | |
1653 | "synth_2_down_3", | |
1654 | "synthetic_2_down_1", | |
1655 | "num_input_states" | |
1656 | }; | |
1657 | ||
1658 | char *kdClassNames[] = { | |
1659 | "down_1", "up_1", | |
1660 | "down_2", "up_2", | |
1661 | "down_3", "up_3", | |
1662 | "motion", "ouside_box", | |
1663 | "keyboard", "timeout", | |
1664 | "num_input_class" | |
1665 | }; | |
1666 | ||
1667 | char *kdActionNames[] = { | |
1668 | "noop", | |
1669 | "hold", | |
1670 | "setto", | |
1671 | "deliver", | |
1672 | "release", | |
1673 | "clearto", | |
1674 | "gen_down_2", | |
1675 | "gen_up_2", | |
1676 | }; | |
1677 | #endif /* DEBUG */ | |
1678 | ||
1679 | /* We return true if we're stealing the event. */ | |
1680 | static Bool | |
1681 | KdRunMouseMachine(KdPointerInfo * pi, KdInputClass c, int type, int x, int y, | |
1682 | int z, int b, int absrel) | |
1683 | { | |
1684 | const KdInputTransition *t; | |
1685 | int a; | |
1686 | ||
1687 | c = KdClassifyInput(pi, type, x, y, z, b); | |
1688 | t = &kdInputMachine[pi->mouseState][c]; | |
1689 | for (a = 0; a < MAX_ACTIONS; a++) { | |
1690 | switch (t->actions[a]) { | |
1691 | case noop: | |
1692 | break; | |
1693 | case hold: | |
1694 | pi->eventHeld = TRUE; | |
1695 | pi->emulationDx = 0; | |
1696 | pi->emulationDy = 0; | |
1697 | pi->heldEvent.type = type; | |
1698 | pi->heldEvent.x = x; | |
1699 | pi->heldEvent.y = y; | |
1700 | pi->heldEvent.z = z; | |
1701 | pi->heldEvent.flags = b; | |
1702 | pi->heldEvent.absrel = absrel; | |
1703 | return TRUE; | |
1704 | break; | |
1705 | case setto: | |
1706 | pi->emulationTimeout = GetTimeInMillis() + EMULATION_TIMEOUT; | |
1707 | pi->timeoutPending = TRUE; | |
1708 | break; | |
1709 | case deliver: | |
1710 | _KdEnqueuePointerEvent(pi, pi->heldEvent.type, pi->heldEvent.x, | |
1711 | pi->heldEvent.y, pi->heldEvent.z, | |
1712 | pi->heldEvent.flags, pi->heldEvent.absrel, | |
1713 | TRUE); | |
1714 | break; | |
1715 | case release: | |
1716 | pi->eventHeld = FALSE; | |
1717 | pi->timeoutPending = FALSE; | |
1718 | _KdEnqueuePointerEvent(pi, pi->heldEvent.type, pi->heldEvent.x, | |
1719 | pi->heldEvent.y, pi->heldEvent.z, | |
1720 | pi->heldEvent.flags, pi->heldEvent.absrel, | |
1721 | TRUE); | |
1722 | return TRUE; | |
1723 | break; | |
1724 | case clearto: | |
1725 | pi->timeoutPending = FALSE; | |
1726 | break; | |
1727 | case gen_down_2: | |
1728 | _KdEnqueuePointerEvent(pi, ButtonPress, x, y, z, 2, absrel, TRUE); | |
1729 | pi->eventHeld = FALSE; | |
1730 | return TRUE; | |
1731 | break; | |
1732 | case gen_up_2: | |
1733 | _KdEnqueuePointerEvent(pi, ButtonRelease, x, y, z, 2, absrel, TRUE); | |
1734 | return TRUE; | |
1735 | break; | |
1736 | } | |
1737 | } | |
1738 | pi->mouseState = t->nextState; | |
1739 | return FALSE; | |
1740 | } | |
1741 | ||
1742 | static int | |
1743 | KdHandlePointerEvent(KdPointerInfo * pi, int type, int x, int y, int z, int b, | |
1744 | int absrel) | |
1745 | { | |
1746 | if (pi->emulateMiddleButton) | |
1747 | return KdRunMouseMachine(pi, KdClassifyInput(pi, type, x, y, z, b), | |
1748 | type, x, y, z, b, absrel); | |
1749 | return FALSE; | |
1750 | } | |
1751 | ||
1752 | static void | |
1753 | KdReceiveTimeout(KdPointerInfo * pi) | |
1754 | { | |
1755 | KdRunMouseMachine(pi, timeout, 0, 0, 0, 0, 0, 0); | |
1756 | } | |
1757 | ||
1758 | /* | |
1759 | * kdCheckTermination | |
1760 | * | |
1761 | * This function checks for the key sequence that terminates the server. When | |
1762 | * detected, it sets the dispatchException flag and returns. The key sequence | |
1763 | * is: | |
1764 | * Control-Alt | |
1765 | * It's assumed that the server will be waken up by the caller when this | |
1766 | * function returns. | |
1767 | */ | |
1768 | ||
1769 | extern int nClients; | |
1770 | ||
1771 | void | |
1772 | KdReleaseAllKeys(void) | |
1773 | { | |
1774 | #if 0 | |
1775 | int key; | |
1776 | KdKeyboardInfo *ki; | |
1777 | ||
1778 | OsBlockSIGIO(); | |
1779 | ||
1780 | for (ki = kdKeyboards; ki; ki = ki->next) { | |
1781 | for (key = ki->keySyms.minKeyCode; key < ki->keySyms.maxKeyCode; key++) { | |
1782 | if (key_is_down(ki->dixdev, key, KEY_POSTED | KEY_PROCESSED)) { | |
1783 | KdHandleKeyboardEvent(ki, KeyRelease, key); | |
1784 | QueueGetKeyboardEvents(ki->dixdev, KeyRelease, key, NULL); | |
1785 | } | |
1786 | } | |
1787 | } | |
1788 | ||
1789 | OsReleaseSIGIO(); | |
1790 | #endif | |
1791 | } | |
1792 | ||
1793 | static void | |
1794 | KdCheckLock(void) | |
1795 | { | |
1796 | KeyClassPtr keyc = NULL; | |
1797 | Bool isSet = FALSE, shouldBeSet = FALSE; | |
1798 | KdKeyboardInfo *tmp = NULL; | |
1799 | ||
1800 | for (tmp = kdKeyboards; tmp; tmp = tmp->next) { | |
1801 | if (tmp->LockLed && tmp->dixdev && tmp->dixdev->key) { | |
1802 | keyc = tmp->dixdev->key; | |
1803 | isSet = (tmp->leds & (1 << (tmp->LockLed - 1))) != 0; | |
1804 | /* FIXME: Just use XKB indicators! */ | |
1805 | shouldBeSet = | |
1806 | ! !(XkbStateFieldFromRec(&keyc->xkbInfo->state) & LockMask); | |
1807 | if (isSet != shouldBeSet) | |
1808 | KdSetLed(tmp, tmp->LockLed, shouldBeSet); | |
1809 | } | |
1810 | } | |
1811 | } | |
1812 | ||
1813 | void | |
1814 | KdEnqueueKeyboardEvent(KdKeyboardInfo * ki, | |
1815 | unsigned char scan_code, unsigned char is_up) | |
1816 | { | |
1817 | unsigned char key_code; | |
1818 | int type; | |
1819 | ||
1820 | if (!ki || !ki->dixdev || !ki->dixdev->kbdfeed || !ki->dixdev->key) | |
1821 | return; | |
1822 | ||
1823 | if (scan_code >= ki->minScanCode && scan_code <= ki->maxScanCode) { | |
1824 | key_code = scan_code + KD_MIN_KEYCODE - ki->minScanCode; | |
1825 | ||
1826 | /* | |
1827 | * Set up this event -- the type may be modified below | |
1828 | */ | |
1829 | if (is_up) | |
1830 | type = KeyRelease; | |
1831 | else | |
1832 | type = KeyPress; | |
1833 | ||
1834 | QueueKeyboardEvents(ki->dixdev, type, key_code, NULL); | |
1835 | } | |
1836 | else { | |
1837 | ErrorF("driver %s wanted to post scancode %d outside of [%d, %d]!\n", | |
1838 | ki->name, scan_code, ki->minScanCode, ki->maxScanCode); | |
1839 | } | |
1840 | } | |
1841 | ||
1842 | /* | |
1843 | * kdEnqueuePointerEvent | |
1844 | * | |
1845 | * This function converts hardware mouse event information into X event | |
1846 | * information. A mouse movement event is passed off to MI to generate | |
1847 | * a MotionNotify event, if appropriate. Button events are created and | |
1848 | * passed off to MI for enqueueing. | |
1849 | */ | |
1850 | ||
1851 | /* FIXME do something a little more clever to deal with multiple axes here */ | |
1852 | void | |
1853 | KdEnqueuePointerEvent(KdPointerInfo * pi, unsigned long flags, int rx, int ry, | |
1854 | int rz) | |
1855 | { | |
1856 | unsigned char buttons; | |
1857 | int x, y, z; | |
1858 | int (*matrix)[3] = kdPointerMatrix.matrix; | |
1859 | unsigned long button; | |
1860 | int n; | |
1861 | int dixflags = 0; | |
1862 | ||
1863 | if (!pi) | |
1864 | return; | |
1865 | ||
1866 | /* we don't need to transform z, so we don't. */ | |
1867 | if (flags & KD_MOUSE_DELTA) { | |
1868 | if (pi->transformCoordinates) { | |
1869 | x = matrix[0][0] * rx + matrix[0][1] * ry; | |
1870 | y = matrix[1][0] * rx + matrix[1][1] * ry; | |
1871 | } | |
1872 | else { | |
1873 | x = rx; | |
1874 | y = ry; | |
1875 | } | |
1876 | } | |
1877 | else { | |
1878 | if (pi->transformCoordinates) { | |
1879 | x = matrix[0][0] * rx + matrix[0][1] * ry + matrix[0][2]; | |
1880 | y = matrix[1][0] * rx + matrix[1][1] * ry + matrix[1][2]; | |
1881 | } | |
1882 | else { | |
1883 | x = rx; | |
1884 | y = ry; | |
1885 | } | |
1886 | } | |
1887 | z = rz; | |
1888 | ||
1889 | if (flags & KD_MOUSE_DELTA) { | |
1890 | if (x || y || z) { | |
1891 | dixflags = POINTER_RELATIVE | POINTER_ACCELERATE; | |
1892 | _KdEnqueuePointerEvent(pi, MotionNotify, x, y, z, 0, dixflags, | |
1893 | FALSE); | |
1894 | } | |
1895 | } | |
1896 | else { | |
1897 | dixflags = POINTER_ABSOLUTE; | |
1898 | if (flags & KD_POINTER_DESKTOP) | |
1899 | dixflags |= POINTER_DESKTOP; | |
1900 | if (x != pi->dixdev->last.valuators[0] || | |
1901 | y != pi->dixdev->last.valuators[1]) | |
1902 | _KdEnqueuePointerEvent(pi, MotionNotify, x, y, z, 0, dixflags, | |
1903 | FALSE); | |
1904 | } | |
1905 | ||
1906 | buttons = flags; | |
1907 | ||
1908 | for (button = KD_BUTTON_1, n = 1; n <= pi->nButtons; button <<= 1, n++) { | |
1909 | if (((pi->buttonState & button) ^ (buttons & button)) && | |
1910 | !(buttons & button)) { | |
1911 | _KdEnqueuePointerEvent(pi, ButtonRelease, x, y, z, n, | |
1912 | dixflags, FALSE); | |
1913 | } | |
1914 | } | |
1915 | for (button = KD_BUTTON_1, n = 1; n <= pi->nButtons; button <<= 1, n++) { | |
1916 | if (((pi->buttonState & button) ^ (buttons & button)) && | |
1917 | (buttons & button)) { | |
1918 | _KdEnqueuePointerEvent(pi, ButtonPress, x, y, z, n, | |
1919 | dixflags, FALSE); | |
1920 | } | |
1921 | } | |
1922 | ||
1923 | pi->buttonState = buttons; | |
1924 | } | |
1925 | ||
1926 | void | |
1927 | _KdEnqueuePointerEvent(KdPointerInfo * pi, int type, int x, int y, int z, | |
1928 | int b, int absrel, Bool force) | |
1929 | { | |
1930 | int valuators[3] = { x, y, z }; | |
1931 | ValuatorMask mask; | |
1932 | ||
1933 | /* TRUE from KdHandlePointerEvent, means 'we swallowed the event'. */ | |
1934 | if (!force && KdHandlePointerEvent(pi, type, x, y, z, b, absrel)) | |
1935 | return; | |
1936 | ||
1937 | valuator_mask_set_range(&mask, 0, 3, valuators); | |
1938 | ||
1939 | QueuePointerEvents(pi->dixdev, type, b, absrel, &mask); | |
1940 | } | |
1941 | ||
1942 | void | |
1943 | KdBlockHandler(ScreenPtr pScreen, pointer timeout, pointer readmask) | |
1944 | { | |
1945 | KdPointerInfo *pi; | |
1946 | int myTimeout = 0; | |
1947 | ||
1948 | for (pi = kdPointers; pi; pi = pi->next) { | |
1949 | if (pi->timeoutPending) { | |
1950 | int ms; | |
1951 | ||
1952 | ms = pi->emulationTimeout - GetTimeInMillis(); | |
1953 | if (ms < 1) | |
1954 | ms = 1; | |
1955 | if (ms < myTimeout || myTimeout == 0) | |
1956 | myTimeout = ms; | |
1957 | } | |
1958 | } | |
1959 | /* if we need to poll for events, do that */ | |
1960 | if (kdOsFuncs->pollEvents) { | |
1961 | (*kdOsFuncs->pollEvents) (); | |
1962 | myTimeout = 20; | |
1963 | } | |
1964 | if (myTimeout > 0) | |
1965 | AdjustWaitForDelay(timeout, myTimeout); | |
1966 | } | |
1967 | ||
1968 | void | |
1969 | KdWakeupHandler(ScreenPtr pScreen, unsigned long lresult, pointer readmask) | |
1970 | { | |
1971 | int result = (int) lresult; | |
1972 | fd_set *pReadmask = (fd_set *) readmask; | |
1973 | int i; | |
1974 | KdPointerInfo *pi; | |
1975 | ||
1976 | if (kdInputEnabled && result > 0) { | |
1977 | for (i = 0; i < kdNumInputFds; i++) | |
1978 | if (FD_ISSET(kdInputFds[i].fd, pReadmask)) { | |
1979 | OsBlockSIGIO(); | |
1980 | (*kdInputFds[i].read) (kdInputFds[i].fd, kdInputFds[i].closure); | |
1981 | OsReleaseSIGIO(); | |
1982 | } | |
1983 | } | |
1984 | for (pi = kdPointers; pi; pi = pi->next) { | |
1985 | if (pi->timeoutPending) { | |
1986 | if ((long) (GetTimeInMillis() - pi->emulationTimeout) >= 0) { | |
1987 | pi->timeoutPending = FALSE; | |
1988 | OsBlockSIGIO(); | |
1989 | KdReceiveTimeout(pi); | |
1990 | OsReleaseSIGIO(); | |
1991 | } | |
1992 | } | |
1993 | } | |
1994 | if (kdSwitchPending) | |
1995 | KdProcessSwitch(); | |
1996 | } | |
1997 | ||
1998 | #define KdScreenOrigin(pScreen) (&(KdGetScreenPriv(pScreen)->screen->origin)) | |
1999 | ||
2000 | static Bool | |
2001 | KdCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y) | |
2002 | { | |
2003 | ScreenPtr pScreen = *ppScreen; | |
2004 | ScreenPtr pNewScreen; | |
2005 | int n; | |
2006 | int dx, dy; | |
2007 | int best_x, best_y; | |
2008 | int n_best_x, n_best_y; | |
2009 | CARD32 ms; | |
2010 | ||
2011 | if (kdDisableZaphod || screenInfo.numScreens <= 1) | |
2012 | return FALSE; | |
2013 | ||
2014 | if (0 <= *x && *x < pScreen->width && 0 <= *y && *y < pScreen->height) | |
2015 | return FALSE; | |
2016 | ||
2017 | ms = GetTimeInMillis(); | |
2018 | if (kdOffScreen && (int) (ms - kdOffScreenTime) < 1000) | |
2019 | return FALSE; | |
2020 | kdOffScreen = TRUE; | |
2021 | kdOffScreenTime = ms; | |
2022 | n_best_x = -1; | |
2023 | best_x = 32767; | |
2024 | n_best_y = -1; | |
2025 | best_y = 32767; | |
2026 | for (n = 0; n < screenInfo.numScreens; n++) { | |
2027 | pNewScreen = screenInfo.screens[n]; | |
2028 | if (pNewScreen == pScreen) | |
2029 | continue; | |
2030 | dx = KdScreenOrigin(pNewScreen)->x - KdScreenOrigin(pScreen)->x; | |
2031 | dy = KdScreenOrigin(pNewScreen)->y - KdScreenOrigin(pScreen)->y; | |
2032 | if (*x < 0) { | |
2033 | if (dx < 0 && -dx < best_x) { | |
2034 | best_x = -dx; | |
2035 | n_best_x = n; | |
2036 | } | |
2037 | } | |
2038 | else if (*x >= pScreen->width) { | |
2039 | if (dx > 0 && dx < best_x) { | |
2040 | best_x = dx; | |
2041 | n_best_x = n; | |
2042 | } | |
2043 | } | |
2044 | if (*y < 0) { | |
2045 | if (dy < 0 && -dy < best_y) { | |
2046 | best_y = -dy; | |
2047 | n_best_y = n; | |
2048 | } | |
2049 | } | |
2050 | else if (*y >= pScreen->height) { | |
2051 | if (dy > 0 && dy < best_y) { | |
2052 | best_y = dy; | |
2053 | n_best_y = n; | |
2054 | } | |
2055 | } | |
2056 | } | |
2057 | if (best_y < best_x) | |
2058 | n_best_x = n_best_y; | |
2059 | if (n_best_x == -1) | |
2060 | return FALSE; | |
2061 | pNewScreen = screenInfo.screens[n_best_x]; | |
2062 | ||
2063 | if (*x < 0) | |
2064 | *x += pNewScreen->width; | |
2065 | if (*y < 0) | |
2066 | *y += pNewScreen->height; | |
2067 | ||
2068 | if (*x >= pScreen->width) | |
2069 | *x -= pScreen->width; | |
2070 | if (*y >= pScreen->height) | |
2071 | *y -= pScreen->height; | |
2072 | ||
2073 | *ppScreen = pNewScreen; | |
2074 | return TRUE; | |
2075 | } | |
2076 | ||
2077 | static void | |
2078 | KdCrossScreen(ScreenPtr pScreen, Bool entering) | |
2079 | { | |
2080 | } | |
2081 | ||
2082 | int KdCurScreen; /* current event screen */ | |
2083 | ||
2084 | static void | |
2085 | KdWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) | |
2086 | { | |
2087 | OsBlockSIGIO(); | |
2088 | KdCurScreen = pScreen->myNum; | |
2089 | miPointerWarpCursor(pDev, pScreen, x, y); | |
2090 | OsReleaseSIGIO(); | |
2091 | } | |
2092 | ||
2093 | miPointerScreenFuncRec kdPointerScreenFuncs = { | |
2094 | KdCursorOffScreen, | |
2095 | KdCrossScreen, | |
2096 | KdWarpCursor | |
2097 | }; | |
2098 | ||
2099 | void | |
2100 | ProcessInputEvents(void) | |
2101 | { | |
2102 | mieqProcessInputEvents(); | |
2103 | if (kdSwitchPending) | |
2104 | KdProcessSwitch(); | |
2105 | KdCheckLock(); | |
2106 | } | |
2107 | ||
2108 | /* At the moment, absolute/relative is up to the client. */ | |
2109 | int | |
2110 | SetDeviceMode(register ClientPtr client, DeviceIntPtr pDev, int mode) | |
2111 | { | |
2112 | return BadMatch; | |
2113 | } | |
2114 | ||
2115 | int | |
2116 | SetDeviceValuators(register ClientPtr client, DeviceIntPtr pDev, | |
2117 | int *valuators, int first_valuator, int num_valuators) | |
2118 | { | |
2119 | return BadMatch; | |
2120 | } | |
2121 | ||
2122 | int | |
2123 | ChangeDeviceControl(register ClientPtr client, DeviceIntPtr pDev, | |
2124 | xDeviceCtl * control) | |
2125 | { | |
2126 | switch (control->control) { | |
2127 | case DEVICE_RESOLUTION: | |
2128 | /* FIXME do something more intelligent here */ | |
2129 | return BadMatch; | |
2130 | ||
2131 | case DEVICE_ABS_CALIB: | |
2132 | case DEVICE_ABS_AREA: | |
2133 | case DEVICE_CORE: | |
2134 | return BadMatch; | |
2135 | case DEVICE_ENABLE: | |
2136 | return Success; | |
2137 | ||
2138 | default: | |
2139 | return BadMatch; | |
2140 | } | |
2141 | ||
2142 | /* NOTREACHED */ | |
2143 | return BadImplementation; | |
2144 | } | |
2145 | ||
2146 | int | |
2147 | NewInputDeviceRequest(InputOption *options, InputAttributes * attrs, | |
2148 | DeviceIntPtr *pdev) | |
2149 | { | |
2150 | InputOption *option = NULL; | |
2151 | KdPointerInfo *pi = NULL; | |
2152 | KdKeyboardInfo *ki = NULL; | |
2153 | ||
2154 | nt_list_for_each_entry(option, options, list.next) { | |
2155 | const char *key = input_option_get_key(option); | |
2156 | const char *value = input_option_get_value(option); | |
2157 | ||
2158 | if (strcmp(key, "type") == 0) { | |
2159 | if (strcmp(value, "pointer") == 0) { | |
2160 | pi = KdNewPointer(); | |
2161 | if (!pi) | |
2162 | return BadAlloc; | |
2163 | } | |
2164 | else if (strcmp(value, "keyboard") == 0) { | |
2165 | ki = KdNewKeyboard(); | |
2166 | if (!ki) | |
2167 | return BadAlloc; | |
2168 | } | |
2169 | else { | |
2170 | ErrorF("unrecognised device type!\n"); | |
2171 | return BadValue; | |
2172 | } | |
2173 | } | |
2174 | #ifdef CONFIG_HAL | |
2175 | else if (strcmp(key, "_source") == 0 && | |
2176 | strcmp(value, "server/hal") == 0) { | |
2177 | ErrorF("Ignoring device from HAL.\n"); | |
2178 | return BadValue; | |
2179 | } | |
2180 | #endif | |
2181 | #ifdef CONFIG_UDEV | |
2182 | else if (strcmp(key, "_source") == 0 && | |
2183 | strcmp(value, "server/udev") == 0) { | |
2184 | ErrorF("Ignoring device from udev.\n"); | |
2185 | return BadValue; | |
2186 | } | |
2187 | #endif | |
2188 | } | |
2189 | ||
2190 | if (!ki && !pi) { | |
2191 | ErrorF("unrecognised device identifier!\n"); | |
2192 | return BadValue; | |
2193 | } | |
2194 | ||
2195 | /* FIXME: change this code below to use KdParseKbdOptions and | |
2196 | * KdParsePointerOptions */ | |
2197 | nt_list_for_each_entry(option, options, list.next) { | |
2198 | const char *key = input_option_get_key(option); | |
2199 | const char *value = input_option_get_value(option); | |
2200 | ||
2201 | if (strcmp(key, "device") == 0) { | |
2202 | if (pi && value) | |
2203 | pi->path = strdup(value); | |
2204 | else if (ki && value) | |
2205 | ki->path = strdup(value); | |
2206 | } | |
2207 | else if (strcmp(key, "driver") == 0) { | |
2208 | if (pi) { | |
2209 | pi->driver = KdFindPointerDriver(value); | |
2210 | if (!pi->driver) { | |
2211 | ErrorF("couldn't find driver!\n"); | |
2212 | KdFreePointer(pi); | |
2213 | return BadValue; | |
2214 | } | |
2215 | pi->options = options; | |
2216 | } | |
2217 | else if (ki) { | |
2218 | ki->driver = KdFindKeyboardDriver(value); | |
2219 | if (!ki->driver) { | |
2220 | ErrorF("couldn't find driver!\n"); | |
2221 | KdFreeKeyboard(ki); | |
2222 | return BadValue; | |
2223 | } | |
2224 | ki->options = options; | |
2225 | } | |
2226 | } | |
2227 | } | |
2228 | ||
2229 | if (pi) { | |
2230 | if (KdAddPointer(pi) != Success || | |
2231 | ActivateDevice(pi->dixdev, TRUE) != Success || | |
2232 | EnableDevice(pi->dixdev, TRUE) != TRUE) { | |
2233 | ErrorF("couldn't add or enable pointer\n"); | |
2234 | return BadImplementation; | |
2235 | } | |
2236 | } | |
2237 | else if (ki) { | |
2238 | if (KdAddKeyboard(ki) != Success || | |
2239 | ActivateDevice(ki->dixdev, TRUE) != Success || | |
2240 | EnableDevice(ki->dixdev, TRUE) != TRUE) { | |
2241 | ErrorF("couldn't add or enable keyboard\n"); | |
2242 | return BadImplementation; | |
2243 | } | |
2244 | } | |
2245 | ||
2246 | if (pi) { | |
2247 | *pdev = pi->dixdev; | |
2248 | } | |
2249 | else if (ki) { | |
2250 | *pdev = ki->dixdev; | |
2251 | } | |
2252 | ||
2253 | return Success; | |
2254 | } | |
2255 | ||
2256 | void | |
2257 | DeleteInputDeviceRequest(DeviceIntPtr pDev) | |
2258 | { | |
2259 | RemoveDevice(pDev, TRUE); | |
2260 | } |