First import
[xorg_rtime.git] / xorg-server-1.4 / hw / kdrive / src / kinput.c
blob6c247c185f6ce8983d11c12f0e55af4d5dbd00ec
1 /*
2 * Copyright © 1999 Keith Packard
3 * Copyright © 2006 Nokia Corporation
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.
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.
24 #ifdef HAVE_CONFIG_H
25 #include <kdrive-config.h>
26 #endif
27 #include "kdrive.h"
28 #include "inputstr.h"
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
41 #ifdef XKB
42 #include <xkbsrv.h>
43 #endif
45 #include <X11/extensions/XI.h>
46 #include <X11/extensions/XIproto.h>
47 #include "XIstubs.h" /* even though we don't use stubs. cute, no? */
48 #include "exevents.h"
49 #include "extinit.h"
50 #include "exglobals.h"
52 #define AtomFromName(x) MakeAtom(x, strlen(x), 1)
54 struct KdConfigDevice {
55 char *line;
56 struct KdConfigDevice *next;
59 /* kdKeyboards and kdPointers hold all the real devices. */
60 static KdKeyboardInfo *kdKeyboards = NULL;
61 static KdPointerInfo *kdPointers = NULL;
62 static struct KdConfigDevice *kdConfigKeyboards = NULL;
63 static struct KdConfigDevice *kdConfigPointers = NULL;
65 static KdKeyboardDriver *kdKeyboardDrivers = NULL;
66 static KdPointerDriver *kdPointerDrivers = NULL;
68 static xEvent *kdEvents = NULL;
70 static Bool kdInputEnabled;
71 static Bool kdOffScreen;
72 static unsigned long kdOffScreenTime;
73 static KdPointerMatrix kdPointerMatrix = {
74 { { 1, 0, 0 },
75 { 0, 1, 0 } }
78 void KdResetInputMachine (void);
80 #define IsKeyDown(ki, key) ((ki->keyState[(key) >> 3] >> ((key) & 7)) & 1)
81 #define KEYMAP(ki) (ki->dixdev->key->curKeySyms)
82 #define KEYMAPDDX(ki) (ki->keySyms)
83 #define KEYCOL1(ki, k) (KEYMAP(ki).map[((k)-(KEYMAP(ki).minKeyCode))*KEYMAP(ki).mapWidth])
84 #define KEYCOL1DDX(ki, k) (KEYMAPDDX(ki).map[((k)-(KEYMAPDDX(ki).minKeyCode))*KEYMAPDDX(ki).mapWidth])
86 #define KD_MAX_INPUT_FDS 8
88 typedef struct _kdInputFd {
89 int fd;
90 void (*read) (int fd, void *closure);
91 int (*enable) (int fd, void *closure);
92 void (*disable) (int fd, void *closure);
93 void *closure;
94 } KdInputFd;
96 static KdInputFd kdInputFds[KD_MAX_INPUT_FDS];
97 static int kdNumInputFds;
99 extern Bool kdRawPointerCoordinates;
101 static void
102 KdSigio (int sig)
104 int i;
106 for (i = 0; i < kdNumInputFds; i++)
107 (*kdInputFds[i].read) (kdInputFds[i].fd, kdInputFds[i].closure);
110 static void
111 KdBlockSigio (void)
113 sigset_t set;
115 sigemptyset (&set);
116 sigaddset (&set, SIGIO);
117 sigprocmask (SIG_BLOCK, &set, 0);
120 static void
121 KdUnblockSigio (void)
123 sigset_t set;
125 sigemptyset (&set);
126 sigaddset (&set, SIGIO);
127 sigprocmask (SIG_UNBLOCK, &set, 0);
130 #ifdef DEBUG_SIGIO
132 void
133 KdAssertSigioBlocked (char *where)
135 sigset_t set, old;
137 sigemptyset (&set);
138 sigprocmask (SIG_BLOCK, &set, &old);
139 if (!sigismember (&old, SIGIO)) {
140 ErrorF ("SIGIO not blocked at %s\n", where);
141 KdBacktrace(0);
145 #else
147 #define KdAssertSigioBlocked(s)
149 #endif
151 static int kdnFds;
153 #ifdef FNONBLOCK
154 #define NOBLOCK FNONBLOCK
155 #else
156 #define NOBLOCK FNDELAY
157 #endif
159 void
160 KdResetInputMachine (void)
162 KdPointerInfo *pi;
164 for (pi = kdPointers; pi; pi = pi->next) {
165 pi->mouseState = start;
166 pi->eventHeld = FALSE;
170 static void
171 KdNonBlockFd (int fd)
173 int flags;
174 flags = fcntl (fd, F_GETFL);
175 flags |= FASYNC|NOBLOCK;
176 fcntl (fd, F_SETFL, flags);
179 static void
180 KdAddFd (int fd)
182 struct sigaction act;
183 sigset_t set;
185 kdnFds++;
186 fcntl (fd, F_SETOWN, getpid());
187 KdNonBlockFd (fd);
188 AddEnabledDevice (fd);
189 memset (&act, '\0', sizeof act);
190 act.sa_handler = KdSigio;
191 sigemptyset (&act.sa_mask);
192 sigaddset (&act.sa_mask, SIGIO);
193 sigaddset (&act.sa_mask, SIGALRM);
194 sigaddset (&act.sa_mask, SIGVTALRM);
195 sigaction (SIGIO, &act, 0);
196 sigemptyset (&set);
197 sigprocmask (SIG_SETMASK, &set, 0);
200 static void
201 KdRemoveFd (int fd)
203 struct sigaction act;
204 int flags;
206 kdnFds--;
207 RemoveEnabledDevice (fd);
208 flags = fcntl (fd, F_GETFL);
209 flags &= ~(FASYNC|NOBLOCK);
210 fcntl (fd, F_SETFL, flags);
211 if (kdnFds == 0)
213 memset (&act, '\0', sizeof act);
214 act.sa_handler = SIG_IGN;
215 sigemptyset (&act.sa_mask);
216 sigaction (SIGIO, &act, 0);
220 Bool
221 KdRegisterFd (int fd, void (*read) (int fd, void *closure), void *closure)
223 if (kdNumInputFds == KD_MAX_INPUT_FDS)
224 return FALSE;
225 kdInputFds[kdNumInputFds].fd = fd;
226 kdInputFds[kdNumInputFds].read = read;
227 kdInputFds[kdNumInputFds].enable = 0;
228 kdInputFds[kdNumInputFds].disable = 0;
229 kdInputFds[kdNumInputFds].closure = closure;
230 kdNumInputFds++;
231 if (kdInputEnabled)
232 KdAddFd (fd);
233 return TRUE;
236 void
237 KdUnregisterFd (void *closure, int fd, Bool do_close)
239 int i, j;
241 for (i = 0; i < kdNumInputFds; i++) {
242 if (kdInputFds[i].closure == closure &&
243 (fd == -1 || kdInputFds[i].fd == fd)) {
244 if (kdInputEnabled)
245 KdRemoveFd (kdInputFds[i].fd);
246 if (do_close)
247 close (kdInputFds[i].fd);
248 kdNumInputFds--;
249 for (j = i; j < kdNumInputFds; j++)
250 kdInputFds[j] = kdInputFds[j+1];
251 break;
256 void
257 KdUnregisterFds (void *closure, Bool do_close)
259 KdUnregisterFd(closure, -1, do_close);
262 void
263 KdDisableInput (void)
265 KdKeyboardInfo *ki;
266 KdPointerInfo *pi;
267 int found = 0, i = 0;
269 KdBlockSigio();
271 for (ki = kdKeyboards; ki; ki = ki->next) {
272 if (ki->driver && ki->driver->Disable)
273 (*ki->driver->Disable) (ki);
276 for (pi = kdPointers; pi; pi = pi->next) {
277 if (pi->driver && pi->driver->Disable)
278 (*pi->driver->Disable) (pi);
281 if (kdNumInputFds) {
282 ErrorF("[KdDisableInput] Buggy drivers: still %d input fds left!",
283 kdNumInputFds);
284 i = 0;
285 while (i < kdNumInputFds) {
286 found = 0;
287 for (ki = kdKeyboards; ki; ki = ki->next) {
288 if (ki == kdInputFds[i].closure) {
289 ErrorF(" fd %d belongs to keybd driver %s\n",
290 kdInputFds[i].fd,
291 ki->driver && ki->driver->name ?
292 ki->driver->name : "(unnamed!)");
293 found = 1;
294 break;
298 if (found) {
299 i++;
300 continue;
303 for (pi = kdPointers; pi; pi = pi->next) {
304 if (pi == kdInputFds[i].closure) {
305 ErrorF(" fd %d belongs to pointer driver %s\n",
306 kdInputFds[i].fd,
307 pi->driver && pi->driver->name ?
308 pi->driver->name : "(unnamed!)");
309 break;
313 if (found) {
314 i++;
315 continue;
318 ErrorF(" fd %d not claimed by any active device!\n",
319 kdInputFds[i].fd);
320 KdUnregisterFd(kdInputFds[i].closure, kdInputFds[i].fd, TRUE);
324 kdInputEnabled = FALSE;
327 void
328 KdEnableInput (void)
330 xEvent xE;
331 KdKeyboardInfo *ki;
332 KdPointerInfo *pi;
334 kdInputEnabled = TRUE;
336 for (ki = kdKeyboards; ki; ki = ki->next) {
337 if (ki->driver && ki->driver->Enable)
338 (*ki->driver->Enable) (ki);
341 for (pi = kdPointers; pi; pi = pi->next) {
342 if (pi->driver && pi->driver->Enable)
343 (*pi->driver->Enable) (pi);
346 /* reset screen saver */
347 xE.u.keyButtonPointer.time = GetTimeInMillis ();
348 NoticeEventTime (&xE);
350 KdUnblockSigio ();
353 static KdKeyboardDriver *
354 KdFindKeyboardDriver (char *name)
356 KdKeyboardDriver *ret;
358 /* ask a stupid question ... */
359 if (!name)
360 return NULL;
362 for (ret = kdKeyboardDrivers; ret; ret = ret->next) {
363 if (strcmp(ret->name, name) == 0)
364 return ret;
367 return NULL;
370 static KdPointerDriver *
371 KdFindPointerDriver (char *name)
373 KdPointerDriver *ret;
375 /* ask a stupid question ... */
376 if (!name)
377 return NULL;
379 for (ret = kdPointerDrivers; ret; ret = ret->next) {
380 if (strcmp(ret->name, name) == 0)
381 return ret;
384 return NULL;
387 static int
388 KdPointerProc(DeviceIntPtr pDevice, int onoff)
390 DevicePtr pDev = (DevicePtr)pDevice;
391 KdPointerInfo *pi;
392 Atom xiclass;
394 if (!pDev)
395 return BadImplementation;
397 for (pi = kdPointers; pi; pi = pi->next) {
398 if (pi->dixdev && pi->dixdev->id == pDevice->id)
399 break;
402 if (!pi || !pi->dixdev || pi->dixdev->id != pDevice->id) {
403 ErrorF("[KdPointerProc] Failed to find pointer for device %d!\n",
404 pDevice->id);
405 return BadImplementation;
408 switch (onoff)
410 case DEVICE_INIT:
411 #ifdef DEBUG
412 ErrorF("initialising pointer %s ...\n", pi->name);
413 #endif
414 if (!pi->driver) {
415 if (!pi->driverPrivate) {
416 ErrorF("no driver specified for %s\n", pi->name);
417 return BadImplementation;
420 pi->driver = KdFindPointerDriver(pi->driverPrivate);
421 if (!pi->driver) {
422 ErrorF("Couldn't find pointer driver %s\n",
423 pi->driverPrivate ? (char *) pi->driverPrivate :
424 "(unnamed)");
425 return !Success;
427 xfree(pi->driverPrivate);
428 pi->driverPrivate = NULL;
431 if (!pi->driver->Init) {
432 ErrorF("no init function\n");
433 return BadImplementation;
436 if ((*pi->driver->Init) (pi) != Success) {
437 return !Success;
440 InitPointerDeviceStruct(pDev, pi->map, pi->nButtons,
441 GetMotionHistory,
442 (PtrCtrlProcPtr)NoopDDA,
443 GetMotionHistorySize(), pi->nAxes);
445 if (pi->inputClass == KD_TOUCHSCREEN) {
446 InitAbsoluteClassDeviceStruct(pDevice);
447 xiclass = AtomFromName(XI_TOUCHSCREEN);
449 else {
450 xiclass = AtomFromName(XI_MOUSE);
453 AssignTypeAndName(pi->dixdev, xiclass,
454 pi->name ? pi->name : "Generic KDrive Pointer");
456 return Success;
458 case DEVICE_ON:
459 if (pDev->on == TRUE)
460 return Success;
462 if (!pi->driver->Enable) {
463 ErrorF("no enable function\n");
464 return BadImplementation;
467 if ((*pi->driver->Enable) (pi) == Success) {
468 pDev->on = TRUE;
469 return Success;
471 else {
472 return BadImplementation;
475 return Success;
477 case DEVICE_OFF:
478 if (pDev->on == FALSE) {
479 return Success;
482 if (!pi->driver->Disable) {
483 return BadImplementation;
485 else {
486 (*pi->driver->Disable) (pi);
487 pDev->on = FALSE;
488 return Success;
491 return Success;
493 case DEVICE_CLOSE:
494 if (pDev->on) {
495 if (!pi->driver->Disable) {
496 return BadImplementation;
498 (*pi->driver->Disable) (pi);
499 pDev->on = FALSE;
502 if (!pi->driver->Fini)
503 return BadImplementation;
505 (*pi->driver->Fini) (pi);
507 KdRemovePointer(pi);
509 return Success;
512 /* NOTREACHED */
513 return BadImplementation;
516 Bool
517 LegalModifier(unsigned int key, DeviceIntPtr pDev)
519 return TRUE;
522 static void
523 KdBell (int volume, DeviceIntPtr pDev, pointer arg, int something)
525 KeybdCtrl *ctrl = arg;
526 KdKeyboardInfo *ki = NULL;
528 for (ki = kdKeyboards; ki; ki = ki->next) {
529 if (ki->dixdev && ki->dixdev->id == pDev->id)
530 break;
533 if (!ki || !ki->dixdev || ki->dixdev->id != pDev->id || !ki->driver)
534 return;
536 KdRingBell(ki, volume, ctrl->bell_pitch, ctrl->bell_duration);
539 void
540 DDXRingBell(int volume, int pitch, int duration)
542 KdKeyboardInfo *ki = NULL;
544 if (kdOsFuncs->Bell) {
545 (*kdOsFuncs->Bell)(volume, pitch, duration);
547 else {
548 for (ki = kdKeyboards; ki; ki = ki->next) {
549 if (ki->dixdev->coreEvents)
550 KdRingBell(ki, volume, pitch, duration);
555 void
556 KdRingBell(KdKeyboardInfo *ki, int volume, int pitch, int duration)
558 if (!ki || !ki->driver || !ki->driver->Bell)
559 return;
561 if (kdInputEnabled)
562 (*ki->driver->Bell) (ki, volume, pitch, duration);
566 static void
567 KdSetLeds (KdKeyboardInfo *ki, int leds)
569 if (!ki || !ki->driver)
570 return;
572 if (kdInputEnabled) {
573 if (ki->driver->Leds)
574 (*ki->driver->Leds) (ki, leds);
578 void
579 KdSetLed (KdKeyboardInfo *ki, int led, Bool on)
581 if (!ki || !ki->dixdev || !ki->dixdev->kbdfeed)
582 return;
584 NoteLedState (ki->dixdev, led, on);
585 KdSetLeds (ki, ki->dixdev->kbdfeed->ctrl.leds);
588 void
589 KdSetPointerMatrix (KdPointerMatrix *matrix)
591 kdPointerMatrix = *matrix;
594 void
595 KdComputePointerMatrix (KdPointerMatrix *m, Rotation randr, int width,
596 int height)
598 int x_dir = 1, y_dir = 1;
599 int i, j;
600 int size[2];
602 size[0] = width; size[1] = height;
603 if (randr & RR_Reflect_X)
604 x_dir = -1;
605 if (randr & RR_Reflect_Y)
606 y_dir = -1;
607 switch (randr & (RR_Rotate_All)) {
608 case RR_Rotate_0:
609 m->matrix[0][0] = x_dir; m->matrix[0][1] = 0;
610 m->matrix[1][0] = 0; m->matrix[1][1] = y_dir;
611 break;
612 case RR_Rotate_90:
613 m->matrix[0][0] = 0; m->matrix[0][1] = -x_dir;
614 m->matrix[1][0] = y_dir; m->matrix[1][1] = 0;
615 break;
616 case RR_Rotate_180:
617 m->matrix[0][0] = -x_dir; m->matrix[0][1] = 0;
618 m->matrix[1][0] = 0; m->matrix[1][1] = -y_dir;
619 break;
620 case RR_Rotate_270:
621 m->matrix[0][0] = 0; m->matrix[0][1] = x_dir;
622 m->matrix[1][0] = -y_dir; m->matrix[1][1] = 0;
623 break;
625 for (i = 0; i < 2; i++)
627 m->matrix[i][2] = 0;
628 for (j = 0 ; j < 2; j++)
629 if (m->matrix[i][j] < 0)
630 m->matrix[i][2] = size[j] - 1;
634 static void
635 KdKbdCtrl (DeviceIntPtr pDevice, KeybdCtrl *ctrl)
637 KdKeyboardInfo *ki;
639 for (ki = kdKeyboards; ki; ki = ki->next) {
640 if (ki->dixdev && ki->dixdev->id == pDevice->id)
641 break;
644 if (!ki || !ki->dixdev || ki->dixdev->id != pDevice->id || !ki->driver)
645 return;
647 KdSetLeds(ki, ctrl->leds);
648 ki->bellPitch = ctrl->bell_pitch;
649 ki->bellDuration = ctrl->bell_duration;
652 extern KeybdCtrl defaultKeyboardControl;
654 static void
655 KdInitAutoRepeats (KdKeyboardInfo *ki)
657 int key_code;
658 unsigned char mask;
659 int i;
660 unsigned char *repeats;
662 repeats = defaultKeyboardControl.autoRepeats;
663 memset (repeats, '\0', 32);
664 for (key_code = KD_MIN_KEYCODE; key_code <= KD_MAX_KEYCODE; key_code++)
666 if (!ki->modmap[key_code])
668 i = key_code >> 3;
669 mask = 1 << (key_code & 7);
670 repeats[i] |= mask;
675 const KdKeySymModsRec kdKeySymMods[] = {
676 { XK_Control_L, ControlMask },
677 { XK_Control_R, ControlMask },
678 { XK_Shift_L, ShiftMask },
679 { XK_Shift_R, ShiftMask },
680 { XK_Caps_Lock, LockMask },
681 { XK_Shift_Lock, LockMask },
682 { XK_Alt_L, Mod1Mask },
683 { XK_Alt_R, Mod1Mask },
684 { XK_Meta_L, Mod1Mask },
685 { XK_Meta_R, Mod1Mask },
686 { XK_Num_Lock, Mod2Mask },
687 { XK_Super_L, Mod3Mask },
688 { XK_Super_R, Mod3Mask },
689 { XK_Hyper_L, Mod3Mask },
690 { XK_Hyper_R, Mod3Mask },
691 { XK_Mode_switch, Mod4Mask },
692 /* PDA specific hacks */
693 #ifdef XF86XK_Start
694 { XF86XK_Start, ControlMask },
695 #endif
696 { XK_Menu, ShiftMask },
697 { XK_telephone, Mod1Mask },
698 #ifdef XF86XK_AudioRecord
699 { XF86XK_AudioRecord, Mod2Mask },
700 #endif
701 #ifdef XF86XK_Calendar
702 { XF86XK_Calendar, Mod3Mask }
703 #endif
706 #define NUM_SYM_MODS (sizeof(kdKeySymMods) / sizeof(kdKeySymMods[0]))
708 static void
709 KdInitModMap (KdKeyboardInfo *ki)
711 int key_code;
712 int row;
713 int width;
714 KeySym *syms;
715 int i;
717 width = ki->keySyms.mapWidth;
718 for (key_code = ki->keySyms.minKeyCode; key_code <= ki->keySyms.maxKeyCode; key_code++)
720 ki->modmap[key_code] = 0;
721 syms = ki->keySyms.map + (key_code - ki->keySyms.minKeyCode) * width;
722 for (row = 0; row < width; row++, syms++)
724 for (i = 0; i < NUM_SYM_MODS; i++)
726 if (*syms == kdKeySymMods[i].modsym)
727 ki->modmap[key_code] |= kdKeySymMods[i].modbit;
733 static int
734 KdKeyboardProc(DeviceIntPtr pDevice, int onoff)
736 Bool ret;
737 DevicePtr pDev = (DevicePtr)pDevice;
738 KdKeyboardInfo *ki;
739 Atom xiclass;
740 #ifdef XKB
741 XkbComponentNamesRec names;
742 #endif
744 if (!pDev)
745 return BadImplementation;
747 for (ki = kdKeyboards; ki; ki = ki->next) {
748 if (ki->dixdev && ki->dixdev->id == pDevice->id)
749 break;
752 if (!ki || !ki->dixdev || ki->dixdev->id != pDevice->id) {
753 return BadImplementation;
756 switch (onoff)
758 case DEVICE_INIT:
759 #ifdef DEBUG
760 ErrorF("initialising keyboard %s\n", ki->name);
761 #endif
762 if (!ki->driver) {
763 if (!ki->driverPrivate) {
764 ErrorF("no driver specified!\n");
765 return BadImplementation;
768 ki->driver = KdFindKeyboardDriver(ki->driverPrivate);
769 if (!ki->driver) {
770 ErrorF("Couldn't find keyboard driver %s\n",
771 ki->driverPrivate ? (char *) ki->driverPrivate :
772 "(unnamed)");
773 return !Success;
775 xfree(ki->driverPrivate);
776 ki->driverPrivate = NULL;
779 if (!ki->driver->Init) {
780 ErrorF("Keyboard %s: no init function\n", ki->name);
781 return BadImplementation;
784 if ((*ki->driver->Init) (ki) != Success) {
785 return !Success;
788 KdInitModMap(ki);
789 KdInitAutoRepeats(ki);
791 #ifdef XKB
792 if (!noXkbExtension) {
793 memset(&names, 0, sizeof(XkbComponentNamesRec));
795 XkbSetRulesDflts (ki->xkbRules, ki->xkbModel, ki->xkbLayout,
796 ki->xkbVariant, ki->xkbOptions);
798 ret = XkbInitKeyboardDeviceStruct (pDevice,
799 &names,
800 &ki->keySyms,
801 ki->modmap,
802 KdBell, KdKbdCtrl);
804 else
805 #endif
806 ret = InitKeyboardDeviceStruct(pDev,
807 &ki->keySyms,
808 ki->modmap,
809 KdBell, KdKbdCtrl);
810 if (!ret) {
811 ErrorF("Couldn't initialise keyboard %s\n", ki->name);
812 return BadImplementation;
815 xiclass = AtomFromName(XI_KEYBOARD);
816 AssignTypeAndName(pDevice, xiclass,
817 ki->name ? ki->name : "Generic KDrive Keyboard");
819 KdResetInputMachine();
821 return Success;
823 case DEVICE_ON:
824 if (pDev->on == TRUE)
825 return Success;
827 if (!ki->driver->Enable)
828 return BadImplementation;
830 if ((*ki->driver->Enable) (ki) != Success) {
831 return BadMatch;
834 pDev->on = TRUE;
835 return Success;
837 case DEVICE_OFF:
838 if (pDev->on == FALSE)
839 return Success;
841 if (!ki->driver->Disable)
842 return BadImplementation;
844 (*ki->driver->Disable) (ki);
845 pDev->on = FALSE;
847 return Success;
849 break;
851 case DEVICE_CLOSE:
852 if (pDev->on) {
853 if (!ki->driver->Disable)
854 return BadImplementation;
856 (*ki->driver->Disable) (ki);
857 pDev->on = FALSE;
860 if (!ki->driver->Fini)
861 return BadImplementation;
863 (*ki->driver->Fini) (ki);
865 KdRemoveKeyboard(ki);
867 return Success;
870 /* NOTREACHED */
871 return BadImplementation;
874 void
875 KdAddPointerDriver (KdPointerDriver *driver)
877 KdPointerDriver **prev;
879 if (!driver)
880 return;
882 for (prev = &kdPointerDrivers; *prev; prev = &(*prev)->next) {
883 if (*prev == driver)
884 return;
886 *prev = driver;
889 void
890 KdRemovePointerDriver (KdPointerDriver *driver)
892 KdPointerDriver *tmp;
894 if (!driver)
895 return;
897 /* FIXME remove all pointers using this driver */
898 for (tmp = kdPointerDrivers; tmp; tmp = tmp->next) {
899 if (tmp->next == driver)
900 tmp->next = driver->next;
902 if (tmp == driver)
903 tmp = NULL;
906 void
907 KdAddKeyboardDriver (KdKeyboardDriver *driver)
909 KdKeyboardDriver **prev;
911 if (!driver)
912 return;
914 for (prev = &kdKeyboardDrivers; *prev; prev = &(*prev)->next) {
915 if (*prev == driver)
916 return;
918 *prev = driver;
921 void
922 KdRemoveKeyboardDriver (KdKeyboardDriver *driver)
924 KdKeyboardDriver *tmp;
926 if (!driver)
927 return;
929 /* FIXME remove all keyboards using this driver */
930 for (tmp = kdKeyboardDrivers; tmp; tmp = tmp->next) {
931 if (tmp->next == driver)
932 tmp->next = driver->next;
934 if (tmp == driver)
935 tmp = NULL;
938 KdKeyboardInfo *
939 KdNewKeyboard (void)
941 KdKeyboardInfo *ki = xcalloc(sizeof(KdKeyboardInfo), 1);
943 if (!ki)
944 return NULL;
946 ki->keySyms.map = (KeySym *)xcalloc(sizeof(KeySym),
947 KD_MAX_LENGTH *
948 kdDefaultKeySyms.mapWidth);
949 if (!ki->keySyms.map) {
950 xfree(ki);
951 return NULL;
954 memcpy(ki->keySyms.map, kdDefaultKeySyms.map,
955 sizeof(KeySym) * (KD_MAX_LENGTH * kdDefaultKeySyms.mapWidth));
956 ki->keySyms.minKeyCode = kdDefaultKeySyms.minKeyCode;
957 ki->keySyms.maxKeyCode = kdDefaultKeySyms.maxKeyCode;
958 ki->keySyms.mapWidth = kdDefaultKeySyms.mapWidth;
959 ki->minScanCode = 0;
960 ki->maxScanCode = 0;
961 ki->leds = 0;
962 ki->bellPitch = 1000;
963 ki->bellDuration = 200;
964 ki->next = NULL;
965 ki->options = NULL;
966 #ifdef XKB
967 ki->xkbRules = KdSaveString("base");
968 ki->xkbModel = KdSaveString("pc105");
969 ki->xkbLayout = KdSaveString("us");
970 ki->xkbVariant = NULL;
971 ki->xkbOptions = NULL;
972 #endif
974 return ki;
978 KdAddConfigKeyboard (char *keyboard)
980 struct KdConfigDevice **prev, *new;
982 if (!keyboard)
983 return Success;
985 new = (struct KdConfigDevice *) xcalloc(sizeof(struct KdConfigDevice), 1);
986 if (!new)
987 return BadAlloc;
989 new->line = xstrdup(keyboard);
990 new->next = NULL;
992 for (prev = &kdConfigKeyboards; *prev; prev = &(*prev)->next);
993 *prev = new;
995 return Success;
999 KdAddKeyboard (KdKeyboardInfo *ki)
1001 KdKeyboardInfo **prev;
1003 if (!ki)
1004 return !Success;
1006 ki->dixdev = AddInputDevice(KdKeyboardProc, TRUE);
1007 if (!ki->dixdev) {
1008 ErrorF("Couldn't register keyboard device %s\n",
1009 ki->name ? ki->name : "(unnamed)");
1010 return !Success;
1013 RegisterOtherDevice(ki->dixdev);
1015 #ifdef DEBUG
1016 ErrorF("added keyboard %s with dix id %d\n", ki->name, ki->dixdev->id);
1017 #endif
1019 for (prev = &kdKeyboards; *prev; prev = &(*prev)->next);
1020 *prev = ki;
1022 return Success;
1025 void
1026 KdRemoveKeyboard (KdKeyboardInfo *ki)
1028 KdKeyboardInfo **prev;
1030 if (!ki)
1031 return;
1033 for (prev = &kdKeyboards; *prev; prev = &(*prev)->next) {
1034 if (*prev == ki) {
1035 *prev = ki->next;
1036 break;
1040 KdFreeKeyboard(ki);
1044 KdAddConfigPointer (char *pointer)
1046 struct KdConfigDevice **prev, *new;
1048 if (!pointer)
1049 return Success;
1051 new = (struct KdConfigDevice *) xcalloc(sizeof(struct KdConfigDevice), 1);
1052 if (!new)
1053 return BadAlloc;
1055 new->line = xstrdup(pointer);
1056 new->next = NULL;
1058 for (prev = &kdConfigPointers; *prev; prev = &(*prev)->next);
1059 *prev = new;
1061 return Success;
1065 KdAddPointer (KdPointerInfo *pi)
1067 KdPointerInfo **prev;
1069 if (!pi)
1070 return Success;
1072 pi->mouseState = start;
1073 pi->eventHeld = FALSE;
1075 pi->dixdev = AddInputDevice(KdPointerProc, TRUE);
1076 if (!pi->dixdev) {
1077 ErrorF("Couldn't add pointer device %s\n",
1078 pi->name ? pi->name : "(unnamed)");
1079 return BadDevice;
1082 RegisterOtherDevice(pi->dixdev);
1084 for (prev = &kdPointers; *prev; prev = &(*prev)->next);
1085 *prev = pi;
1087 return Success;
1090 void
1091 KdRemovePointer (KdPointerInfo *pi)
1093 KdPointerInfo **prev;
1095 if (!pi)
1096 return;
1098 for (prev = &kdPointers; *prev; prev = &(*prev)->next) {
1099 if (*prev == pi) {
1100 *prev = pi->next;
1101 break;
1105 KdFreePointer(pi);
1109 * You can call your kdriver server with something like:
1110 * $ ./hw/kdrive/yourserver/X :1 -mouse evdev,,device=/dev/input/event4 -keybd
1111 * evdev,,device=/dev/input/event1,xkbmodel=abnt2,xkblayout=br
1113 static Bool
1114 KdGetOptions (InputOption **options, char *string)
1116 InputOption *newopt = NULL, **tmpo = NULL;
1117 int tam_key = 0;
1119 newopt = (InputOption *) xalloc(sizeof (InputOption));
1120 if (!newopt)
1121 return FALSE;
1123 bzero(newopt, sizeof (InputOption));
1125 for (tmpo = options; *tmpo; tmpo = &(*tmpo)->next)
1126 ; /* Hello, I'm here */
1127 *tmpo = newopt;
1129 if (strchr(string, '='))
1131 tam_key = (strchr(string, '=') - string);
1132 newopt->key = (char *)xalloc(tam_key);
1133 strncpy(newopt->key, string, tam_key);
1134 newopt->key[tam_key] = '\0';
1135 newopt->value = xstrdup(strchr(string, '=') + 1);
1137 else
1139 newopt->key = xstrdup(string);
1140 newopt->value = NULL;
1142 newopt->next = NULL;
1144 return TRUE;
1147 static void
1148 KdParseKbdOptions (KdKeyboardInfo *ki)
1150 InputOption *option = NULL;
1152 for (option = ki->options; option; option = option->next)
1154 #ifdef XKB
1155 if (strcasecmp(option->key, "XkbRules") == 0)
1156 ki->xkbRules = option->value;
1157 else if (strcasecmp(option->key, "XkbModel") == 0)
1158 ki->xkbModel = option->value;
1159 else if (strcasecmp(option->key, "XkbLayout") == 0)
1160 ki->xkbLayout = option->value;
1161 else if (strcasecmp(option->key, "XkbVariant") == 0)
1162 ki->xkbVariant = option->value;
1163 else if (strcasecmp(option->key, "XkbOptions") == 0)
1164 ki->xkbOptions = option->value;
1165 else if (!strcasecmp (option->key, "device"))
1166 ki->path = KdSaveString(option->value);
1167 else
1168 #endif
1169 ErrorF("Kbd option key (%s) of value (%s) not assigned!\n",
1170 option->key, option->value);
1174 KdKeyboardInfo *
1175 KdParseKeyboard (char *arg)
1177 char save[1024];
1178 char delim;
1179 InputOption *options = NULL;
1180 KdKeyboardInfo *ki = NULL;
1182 ki = KdNewKeyboard();
1183 if (!ki)
1184 return NULL;
1186 ki->name = strdup("Unknown KDrive Keyboard");
1187 ki->path = NULL;
1188 ki->driver = NULL;
1189 ki->driverPrivate = NULL;
1190 #ifdef XKB
1191 ki->xkb = NULL;
1192 #endif
1193 ki->next = NULL;
1195 if (!arg)
1197 ErrorF("keybd: no arg\n");
1198 KdFreeKeyboard (ki);
1199 return NULL;
1202 if (strlen (arg) >= sizeof (save))
1204 ErrorF("keybd: arg too long\n");
1205 KdFreeKeyboard (ki);
1206 return NULL;
1209 arg = KdParseFindNext (arg, ",", save, &delim);
1210 if (!save[0])
1212 ErrorF("keybd: failed on save[0]\n");
1213 KdFreeKeyboard (ki);
1214 return NULL;
1217 if (strcmp (save, "auto") == 0)
1218 ki->driverPrivate = NULL;
1219 else
1220 ki->driverPrivate = xstrdup(save);
1222 if (delim != ',')
1224 return ki;
1227 arg = KdParseFindNext (arg, ",", save, &delim);
1229 while (delim == ',')
1231 arg = KdParseFindNext (arg, ",", save, &delim);
1233 if (!KdGetOptions(&options, save))
1235 KdFreeKeyboard(ki);
1236 return NULL;
1240 if (options)
1242 ki->options = options;
1243 KdParseKbdOptions(ki);
1246 return ki;
1249 static void
1250 KdParsePointerOptions (KdPointerInfo *pi)
1252 InputOption *option = NULL;
1254 for (option = pi->options; option; option = option->next)
1256 if (!strcmp (option->key, "emulatemiddle"))
1257 pi->emulateMiddleButton = TRUE;
1258 else if (!strcmp (option->key, "noemulatemiddle"))
1259 pi->emulateMiddleButton = FALSE;
1260 else if (!strcmp (option->key, "transformcoord"))
1261 pi->transformCoordinates = TRUE;
1262 else if (!strcmp (option->key, "rawcoord"))
1263 pi->transformCoordinates = FALSE;
1264 else if (!strcasecmp (option->key, "device"))
1265 pi->path = KdSaveString(option->value);
1266 else
1267 ErrorF("Pointer option key (%s) of value (%s) not assigned!\n",
1268 option->key, option->value);
1272 KdPointerInfo *
1273 KdParsePointer (char *arg)
1275 char save[1024];
1276 char delim;
1277 KdPointerInfo *pi = NULL;
1278 InputOption *options = NULL;
1279 int i = 0;
1281 pi = KdNewPointer();
1282 if (!pi)
1283 return NULL;
1284 pi->emulateMiddleButton = kdEmulateMiddleButton;
1285 pi->transformCoordinates = !kdRawPointerCoordinates;
1286 pi->nButtons = 3;
1287 pi->inputClass = KD_MOUSE;
1289 if (!arg)
1291 ErrorF("mouse: no arg\n");
1292 KdFreePointer (pi);
1293 return NULL;
1296 if (strlen (arg) >= sizeof (save))
1298 ErrorF("mouse: arg too long\n");
1299 KdFreePointer (pi);
1300 return NULL;
1302 arg = KdParseFindNext (arg, ",", save, &delim);
1303 if (!save[0])
1305 ErrorF("failed on save[0]\n");
1306 KdFreePointer (pi);
1307 return NULL;
1310 if (strcmp(save, "auto") == 0)
1311 pi->driverPrivate = NULL;
1312 else
1313 pi->driverPrivate = xstrdup(save);
1315 if (delim != ',')
1317 return pi;
1320 arg = KdParseFindNext (arg, ",", save, &delim);
1322 while (delim == ',')
1324 arg = KdParseFindNext (arg, ",", save, &delim);
1325 if (save[0] == '{')
1327 char *s = save + 1;
1328 i = 0;
1329 while (*s && *s != '}')
1331 if ('1' <= *s && *s <= '0' + pi->nButtons)
1332 pi->map[i] = *s - '0';
1333 else
1334 UseMsg ();
1335 s++;
1338 else
1340 if (!KdGetOptions(&options, save))
1342 KdFreePointer(pi);
1343 return NULL;
1348 if (options)
1350 pi->options = options;
1351 KdParsePointerOptions(pi);
1354 return pi;
1358 void
1359 KdInitInput (void)
1361 KdPointerInfo *pi;
1362 KdKeyboardInfo *ki;
1363 struct KdConfigDevice *dev;
1365 kdInputEnabled = TRUE;
1367 for (dev = kdConfigPointers; dev; dev = dev->next) {
1368 pi = KdParsePointer(dev->line);
1369 if (!pi)
1370 ErrorF("Failed to parse pointer\n");
1371 if (KdAddPointer(pi) != Success)
1372 ErrorF("Failed to add pointer!\n");
1374 for (dev = kdConfigKeyboards; dev; dev = dev->next) {
1375 ki = KdParseKeyboard(dev->line);
1376 if (!ki)
1377 ErrorF("Failed to parse keyboard\n");
1378 if (KdAddKeyboard(ki) != Success)
1379 ErrorF("Failed to add keyboard!\n");
1382 if (!kdEvents)
1383 kdEvents = (xEvent *)xcalloc(sizeof(xEvent), GetMaximumEventsNum());
1384 if (!kdEvents)
1385 FatalError("Couldn't allocate event buffer\n");
1387 mieqInit();
1391 * Middle button emulation state machine
1393 * Possible transitions:
1394 * Button 1 press v1
1395 * Button 1 release ^1
1396 * Button 2 press v2
1397 * Button 2 release ^2
1398 * Button 3 press v3
1399 * Button 3 release ^3
1400 * Button other press vo
1401 * Button other release ^o
1402 * Mouse motion <>
1403 * Keyboard event k
1404 * timeout ...
1405 * outside box <->
1407 * States:
1408 * start
1409 * button_1_pend
1410 * button_1_down
1411 * button_2_down
1412 * button_3_pend
1413 * button_3_down
1414 * synthetic_2_down_13
1415 * synthetic_2_down_3
1416 * synthetic_2_down_1
1418 * Transition diagram
1420 * start
1421 * v1 -> (hold) (settimeout) button_1_pend
1422 * ^1 -> (deliver) start
1423 * v2 -> (deliver) button_2_down
1424 * ^2 -> (deliever) start
1425 * v3 -> (hold) (settimeout) button_3_pend
1426 * ^3 -> (deliver) start
1427 * vo -> (deliver) start
1428 * ^o -> (deliver) start
1429 * <> -> (deliver) start
1430 * k -> (deliver) start
1432 * button_1_pend (button 1 is down, timeout pending)
1433 * ^1 -> (release) (deliver) start
1434 * v2 -> (release) (deliver) button_1_down
1435 * ^2 -> (release) (deliver) button_1_down
1436 * v3 -> (cleartimeout) (generate v2) synthetic_2_down_13
1437 * ^3 -> (release) (deliver) button_1_down
1438 * vo -> (release) (deliver) button_1_down
1439 * ^o -> (release) (deliver) button_1_down
1440 * <-> -> (release) (deliver) button_1_down
1441 * <> -> (deliver) button_1_pend
1442 * k -> (release) (deliver) button_1_down
1443 * ... -> (release) button_1_down
1445 * button_1_down (button 1 is down)
1446 * ^1 -> (deliver) start
1447 * v2 -> (deliver) button_1_down
1448 * ^2 -> (deliver) button_1_down
1449 * v3 -> (deliver) button_1_down
1450 * ^3 -> (deliver) button_1_down
1451 * vo -> (deliver) button_1_down
1452 * ^o -> (deliver) button_1_down
1453 * <> -> (deliver) button_1_down
1454 * k -> (deliver) button_1_down
1456 * button_2_down (button 2 is down)
1457 * v1 -> (deliver) button_2_down
1458 * ^1 -> (deliver) button_2_down
1459 * ^2 -> (deliver) start
1460 * v3 -> (deliver) button_2_down
1461 * ^3 -> (deliver) button_2_down
1462 * vo -> (deliver) button_2_down
1463 * ^o -> (deliver) button_2_down
1464 * <> -> (deliver) button_2_down
1465 * k -> (deliver) button_2_down
1467 * button_3_pend (button 3 is down, timeout pending)
1468 * v1 -> (generate v2) synthetic_2_down
1469 * ^1 -> (release) (deliver) button_3_down
1470 * v2 -> (release) (deliver) button_3_down
1471 * ^2 -> (release) (deliver) button_3_down
1472 * ^3 -> (release) (deliver) start
1473 * vo -> (release) (deliver) button_3_down
1474 * ^o -> (release) (deliver) button_3_down
1475 * <-> -> (release) (deliver) button_3_down
1476 * <> -> (deliver) button_3_pend
1477 * k -> (release) (deliver) button_3_down
1478 * ... -> (release) button_3_down
1480 * button_3_down (button 3 is down)
1481 * v1 -> (deliver) button_3_down
1482 * ^1 -> (deliver) button_3_down
1483 * v2 -> (deliver) button_3_down
1484 * ^2 -> (deliver) button_3_down
1485 * ^3 -> (deliver) start
1486 * vo -> (deliver) button_3_down
1487 * ^o -> (deliver) button_3_down
1488 * <> -> (deliver) button_3_down
1489 * k -> (deliver) button_3_down
1491 * synthetic_2_down_13 (button 1 and 3 are down)
1492 * ^1 -> (generate ^2) synthetic_2_down_3
1493 * v2 -> synthetic_2_down_13
1494 * ^2 -> synthetic_2_down_13
1495 * ^3 -> (generate ^2) synthetic_2_down_1
1496 * vo -> (deliver) synthetic_2_down_13
1497 * ^o -> (deliver) synthetic_2_down_13
1498 * <> -> (deliver) synthetic_2_down_13
1499 * k -> (deliver) synthetic_2_down_13
1501 * synthetic_2_down_3 (button 3 is down)
1502 * v1 -> (deliver) synthetic_2_down_3
1503 * ^1 -> (deliver) synthetic_2_down_3
1504 * v2 -> synthetic_2_down_3
1505 * ^2 -> synthetic_2_down_3
1506 * ^3 -> start
1507 * vo -> (deliver) synthetic_2_down_3
1508 * ^o -> (deliver) synthetic_2_down_3
1509 * <> -> (deliver) synthetic_2_down_3
1510 * k -> (deliver) synthetic_2_down_3
1512 * synthetic_2_down_1 (button 1 is down)
1513 * ^1 -> start
1514 * v2 -> synthetic_2_down_1
1515 * ^2 -> synthetic_2_down_1
1516 * v3 -> (deliver) synthetic_2_down_1
1517 * ^3 -> (deliver) synthetic_2_down_1
1518 * vo -> (deliver) synthetic_2_down_1
1519 * ^o -> (deliver) synthetic_2_down_1
1520 * <> -> (deliver) synthetic_2_down_1
1521 * k -> (deliver) synthetic_2_down_1
1524 typedef enum _inputClass {
1525 down_1, up_1,
1526 down_2, up_2,
1527 down_3, up_3,
1528 down_o, up_o,
1529 motion, outside_box,
1530 keyboard, timeout,
1531 num_input_class
1532 } KdInputClass;
1534 typedef enum _inputAction {
1535 noop,
1536 hold,
1537 setto,
1538 deliver,
1539 release,
1540 clearto,
1541 gen_down_2,
1542 gen_up_2
1543 } KdInputAction;
1545 #define MAX_ACTIONS 2
1547 typedef struct _inputTransition {
1548 KdInputAction actions[MAX_ACTIONS];
1549 KdPointerState nextState;
1550 } KdInputTransition;
1552 static const
1553 KdInputTransition kdInputMachine[num_input_states][num_input_class] = {
1554 /* start */
1556 { { hold, setto }, button_1_pend }, /* v1 */
1557 { { deliver, noop }, start }, /* ^1 */
1558 { { deliver, noop }, button_2_down }, /* v2 */
1559 { { deliver, noop }, start }, /* ^2 */
1560 { { hold, setto }, button_3_pend }, /* v3 */
1561 { { deliver, noop }, start }, /* ^3 */
1562 { { deliver, noop }, start }, /* vo */
1563 { { deliver, noop }, start }, /* ^o */
1564 { { deliver, noop }, start }, /* <> */
1565 { { deliver, noop }, start }, /* <-> */
1566 { { noop, noop }, start }, /* k */
1567 { { noop, noop }, start }, /* ... */
1569 /* button_1_pend */
1571 { { noop, noop }, button_1_pend }, /* v1 */
1572 { { release, deliver }, start }, /* ^1 */
1573 { { release, deliver }, button_1_down }, /* v2 */
1574 { { release, deliver }, button_1_down }, /* ^2 */
1575 { { clearto, gen_down_2 }, synth_2_down_13 }, /* v3 */
1576 { { release, deliver }, button_1_down }, /* ^3 */
1577 { { release, deliver }, button_1_down }, /* vo */
1578 { { release, deliver }, button_1_down }, /* ^o */
1579 { { deliver, noop }, button_1_pend }, /* <> */
1580 { { release, deliver }, button_1_down }, /* <-> */
1581 { { noop, noop }, button_1_down }, /* k */
1582 { { release, noop }, button_1_down }, /* ... */
1584 /* button_1_down */
1586 { { noop, noop }, button_1_down }, /* v1 */
1587 { { deliver, noop }, start }, /* ^1 */
1588 { { deliver, noop }, button_1_down }, /* v2 */
1589 { { deliver, noop }, button_1_down }, /* ^2 */
1590 { { deliver, noop }, button_1_down }, /* v3 */
1591 { { deliver, noop }, button_1_down }, /* ^3 */
1592 { { deliver, noop }, button_1_down }, /* vo */
1593 { { deliver, noop }, button_1_down }, /* ^o */
1594 { { deliver, noop }, button_1_down }, /* <> */
1595 { { deliver, noop }, button_1_down }, /* <-> */
1596 { { noop, noop }, button_1_down }, /* k */
1597 { { noop, noop }, button_1_down }, /* ... */
1599 /* button_2_down */
1601 { { deliver, noop }, button_2_down }, /* v1 */
1602 { { deliver, noop }, button_2_down }, /* ^1 */
1603 { { noop, noop }, button_2_down }, /* v2 */
1604 { { deliver, noop }, start }, /* ^2 */
1605 { { deliver, noop }, button_2_down }, /* v3 */
1606 { { deliver, noop }, button_2_down }, /* ^3 */
1607 { { deliver, noop }, button_2_down }, /* vo */
1608 { { deliver, noop }, button_2_down }, /* ^o */
1609 { { deliver, noop }, button_2_down }, /* <> */
1610 { { deliver, noop }, button_2_down }, /* <-> */
1611 { { noop, noop }, button_2_down }, /* k */
1612 { { noop, noop }, button_2_down }, /* ... */
1614 /* button_3_pend */
1616 { { clearto, gen_down_2 }, synth_2_down_13 }, /* v1 */
1617 { { release, deliver }, button_3_down }, /* ^1 */
1618 { { release, deliver }, button_3_down }, /* v2 */
1619 { { release, deliver }, button_3_down }, /* ^2 */
1620 { { release, deliver }, button_3_down }, /* v3 */
1621 { { release, deliver }, start }, /* ^3 */
1622 { { release, deliver }, button_3_down }, /* vo */
1623 { { release, deliver }, button_3_down }, /* ^o */
1624 { { deliver, noop }, button_3_pend }, /* <> */
1625 { { release, deliver }, button_3_down }, /* <-> */
1626 { { release, noop }, button_3_down }, /* k */
1627 { { release, noop }, button_3_down }, /* ... */
1629 /* button_3_down */
1631 { { deliver, noop }, button_3_down }, /* v1 */
1632 { { deliver, noop }, button_3_down }, /* ^1 */
1633 { { deliver, noop }, button_3_down }, /* v2 */
1634 { { deliver, noop }, button_3_down }, /* ^2 */
1635 { { noop, noop }, button_3_down }, /* v3 */
1636 { { deliver, noop }, start }, /* ^3 */
1637 { { deliver, noop }, button_3_down }, /* vo */
1638 { { deliver, noop }, button_3_down }, /* ^o */
1639 { { deliver, noop }, button_3_down }, /* <> */
1640 { { deliver, noop }, button_3_down }, /* <-> */
1641 { { noop, noop }, button_3_down }, /* k */
1642 { { noop, noop }, button_3_down }, /* ... */
1644 /* synthetic_2_down_13 */
1646 { { noop, noop }, synth_2_down_13 }, /* v1 */
1647 { { gen_up_2, noop }, synth_2_down_3 }, /* ^1 */
1648 { { noop, noop }, synth_2_down_13 }, /* v2 */
1649 { { noop, noop }, synth_2_down_13 }, /* ^2 */
1650 { { noop, noop }, synth_2_down_13 }, /* v3 */
1651 { { gen_up_2, noop }, synth_2_down_1 }, /* ^3 */
1652 { { deliver, noop }, synth_2_down_13 }, /* vo */
1653 { { deliver, noop }, synth_2_down_13 }, /* ^o */
1654 { { deliver, noop }, synth_2_down_13 }, /* <> */
1655 { { deliver, noop }, synth_2_down_13 }, /* <-> */
1656 { { noop, noop }, synth_2_down_13 }, /* k */
1657 { { noop, noop }, synth_2_down_13 }, /* ... */
1659 /* synthetic_2_down_3 */
1661 { { deliver, noop }, synth_2_down_3 }, /* v1 */
1662 { { deliver, noop }, synth_2_down_3 }, /* ^1 */
1663 { { deliver, noop }, synth_2_down_3 }, /* v2 */
1664 { { deliver, noop }, synth_2_down_3 }, /* ^2 */
1665 { { noop, noop }, synth_2_down_3 }, /* v3 */
1666 { { noop, noop }, start }, /* ^3 */
1667 { { deliver, noop }, synth_2_down_3 }, /* vo */
1668 { { deliver, noop }, synth_2_down_3 }, /* ^o */
1669 { { deliver, noop }, synth_2_down_3 }, /* <> */
1670 { { deliver, noop }, synth_2_down_3 }, /* <-> */
1671 { { noop, noop }, synth_2_down_3 }, /* k */
1672 { { noop, noop }, synth_2_down_3 }, /* ... */
1674 /* synthetic_2_down_1 */
1676 { { noop, noop }, synth_2_down_1 }, /* v1 */
1677 { { noop, noop }, start }, /* ^1 */
1678 { { deliver, noop }, synth_2_down_1 }, /* v2 */
1679 { { deliver, noop }, synth_2_down_1 }, /* ^2 */
1680 { { deliver, noop }, synth_2_down_1 }, /* v3 */
1681 { { deliver, noop }, synth_2_down_1 }, /* ^3 */
1682 { { deliver, noop }, synth_2_down_1 }, /* vo */
1683 { { deliver, noop }, synth_2_down_1 }, /* ^o */
1684 { { deliver, noop }, synth_2_down_1 }, /* <> */
1685 { { deliver, noop }, synth_2_down_1 }, /* <-> */
1686 { { noop, noop }, synth_2_down_1 }, /* k */
1687 { { noop, noop }, synth_2_down_1 }, /* ... */
1691 #define EMULATION_WINDOW 10
1692 #define EMULATION_TIMEOUT 100
1694 static int
1695 KdInsideEmulationWindow (KdPointerInfo *pi, int x, int y, int z)
1697 pi->emulationDx = pi->heldEvent.x - x;
1698 pi->emulationDy = pi->heldEvent.y - y;
1700 return (abs (pi->emulationDx) < EMULATION_WINDOW &&
1701 abs (pi->emulationDy) < EMULATION_WINDOW);
1704 static KdInputClass
1705 KdClassifyInput (KdPointerInfo *pi, int type, int x, int y, int z, int b)
1707 switch (type) {
1708 case ButtonPress:
1709 switch (b) {
1710 case 1: return down_1;
1711 case 2: return down_2;
1712 case 3: return down_3;
1713 default: return down_o;
1715 break;
1716 case ButtonRelease:
1717 switch (b) {
1718 case 1: return up_1;
1719 case 2: return up_2;
1720 case 3: return up_3;
1721 default: return up_o;
1723 break;
1724 case MotionNotify:
1725 if (pi->eventHeld && !KdInsideEmulationWindow(pi, x, y, z))
1726 return outside_box;
1727 else
1728 return motion;
1729 default:
1730 return keyboard;
1732 return keyboard;
1735 #ifndef NDEBUG
1736 char *kdStateNames[] = {
1737 "start",
1738 "button_1_pend",
1739 "button_1_down",
1740 "button_2_down",
1741 "button_3_pend",
1742 "button_3_down",
1743 "synth_2_down_13",
1744 "synth_2_down_3",
1745 "synthetic_2_down_1",
1746 "num_input_states"
1749 char *kdClassNames[] = {
1750 "down_1", "up_1",
1751 "down_2", "up_2",
1752 "down_3", "up_3",
1753 "motion", "ouside_box",
1754 "keyboard", "timeout",
1755 "num_input_class"
1758 char *kdActionNames[] = {
1759 "noop",
1760 "hold",
1761 "setto",
1762 "deliver",
1763 "release",
1764 "clearto",
1765 "gen_down_2",
1766 "gen_up_2",
1768 #endif
1770 static void
1771 KdQueueEvent (DeviceIntPtr pDev, xEvent *ev)
1773 KdAssertSigioBlocked ("KdQueueEvent");
1774 mieqEnqueue (pDev, ev);
1777 /* We return true if we're stealing the event. */
1778 static Bool
1779 KdRunMouseMachine (KdPointerInfo *pi, KdInputClass c, int type, int x, int y,
1780 int z, int b, int absrel)
1782 const KdInputTransition *t;
1783 int a;
1785 c = KdClassifyInput(pi, type, x, y, z, b);
1786 t = &kdInputMachine[pi->mouseState][c];
1787 for (a = 0; a < MAX_ACTIONS; a++)
1789 switch (t->actions[a]) {
1790 case noop:
1791 break;
1792 case hold:
1793 pi->eventHeld = TRUE;
1794 pi->emulationDx = 0;
1795 pi->emulationDy = 0;
1796 pi->heldEvent.type = type;
1797 pi->heldEvent.x = x;
1798 pi->heldEvent.y = y;
1799 pi->heldEvent.z = z;
1800 pi->heldEvent.flags = b;
1801 pi->heldEvent.absrel = absrel;
1802 return TRUE;
1803 break;
1804 case setto:
1805 pi->emulationTimeout = GetTimeInMillis () + EMULATION_TIMEOUT;
1806 pi->timeoutPending = TRUE;
1807 break;
1808 case deliver:
1809 _KdEnqueuePointerEvent (pi, pi->heldEvent.type, pi->heldEvent.x,
1810 pi->heldEvent.y, pi->heldEvent.z,
1811 pi->heldEvent.flags, pi->heldEvent.absrel,
1812 TRUE);
1813 break;
1814 case release:
1815 pi->eventHeld = FALSE;
1816 pi->timeoutPending = FALSE;
1817 _KdEnqueuePointerEvent (pi, pi->heldEvent.type, pi->heldEvent.x,
1818 pi->heldEvent.y, pi->heldEvent.z,
1819 pi->heldEvent.flags, pi->heldEvent.absrel,
1820 TRUE);
1821 return TRUE;
1822 break;
1823 case clearto:
1824 pi->timeoutPending = FALSE;
1825 break;
1826 case gen_down_2:
1827 _KdEnqueuePointerEvent (pi, ButtonPress, x, y, z, 2, absrel,
1828 TRUE);
1829 pi->eventHeld = FALSE;
1830 return TRUE;
1831 break;
1832 case gen_up_2:
1833 _KdEnqueuePointerEvent (pi, ButtonRelease, x, y, z, 2, absrel,
1834 TRUE);
1835 return TRUE;
1836 break;
1839 pi->mouseState = t->nextState;
1840 return FALSE;
1843 static int
1844 KdHandlePointerEvent (KdPointerInfo *pi, int type, int x, int y, int z, int b,
1845 int absrel)
1847 if (pi->emulateMiddleButton)
1848 return KdRunMouseMachine (pi, KdClassifyInput(pi, type, x, y, z, b),
1849 type, x, y, z, b, absrel);
1850 return FALSE;
1853 static void
1854 KdReceiveTimeout (KdPointerInfo *pi)
1856 KdRunMouseMachine (pi, timeout, 0, 0, 0, 0, 0, 0);
1859 #define KILL_SEQUENCE ((1L << KK_CONTROL)|(1L << KK_ALT)|(1L << KK_F8)|(1L << KK_F10))
1860 #define SPECIAL_SEQUENCE ((1L << KK_CONTROL) | (1L << KK_ALT))
1861 #define SETKILLKEY(b) (KdSpecialKeys |= (1L << (b)))
1862 #define CLEARKILLKEY(b) (KdSpecialKeys &= ~(1L << (b)))
1864 CARD32 KdSpecialKeys = 0;
1867 * kdCheckTermination
1869 * This function checks for the key sequence that terminates the server. When
1870 * detected, it sets the dispatchException flag and returns. The key sequence
1871 * is:
1872 * Control-Alt
1873 * It's assumed that the server will be waken up by the caller when this
1874 * function returns.
1877 extern int nClients;
1879 static void
1880 KdCheckSpecialKeys(KdKeyboardInfo *ki, int type, int sym)
1882 if (!ki)
1883 return;
1886 * Ignore key releases
1889 if (type == KeyRelease)
1890 return;
1892 /* Some iPaq keyboard -> mouse button mapping used to be here, but I
1893 * refuse to perpetuate this madness. -daniels */
1896 * Check for control/alt pressed
1898 if ((ki->dixdev->key->state & (ControlMask|Mod1Mask)) !=
1899 (ControlMask|Mod1Mask))
1900 return;
1903 * Let OS function see keysym first
1906 if (kdOsFuncs->SpecialKey)
1907 if ((*kdOsFuncs->SpecialKey) (sym))
1908 return;
1911 * Now check for backspace or delete; these signal the
1912 * X server to terminate
1914 * I can't believe it's not XKB. -daniels
1916 switch (sym) {
1917 case XK_BackSpace:
1918 case XK_Delete:
1919 case XK_KP_Delete:
1921 * Set the dispatch exception flag so the server will terminate the
1922 * next time through the dispatch loop.
1924 if (kdDontZap == FALSE)
1925 dispatchException |= DE_TERMINATE;
1926 break;
1931 * kdEnqueueKeyboardEvent
1933 * This function converts hardware keyboard event information into an X event
1934 * and enqueues it using MI. It wakes up the server before returning so that
1935 * the event will be processed normally.
1939 static void
1940 KdHandleKeyboardEvent (KdKeyboardInfo *ki, int type, int key)
1942 int byte;
1943 CARD8 bit;
1944 KdPointerInfo *pi;
1946 byte = key >> 3;
1947 bit = 1 << (key & 7);
1949 switch (type) {
1950 case KeyPress:
1951 ki->keyState[byte] |= bit;
1952 break;
1953 case KeyRelease:
1954 ki->keyState[byte] &= ~bit;
1955 break;
1958 for (pi = kdPointers; pi; pi = pi->next)
1959 KdRunMouseMachine (pi, keyboard, 0, 0, 0, 0, 0, 0);
1962 void
1963 KdReleaseAllKeys (void)
1965 int key, nEvents, i;
1966 KdKeyboardInfo *ki;
1968 KdBlockSigio ();
1970 for (ki = kdKeyboards; ki; ki = ki->next) {
1971 for (key = ki->keySyms.minKeyCode; key < ki->keySyms.maxKeyCode;
1972 key++) {
1973 if (IsKeyDown(ki, key)) {
1974 KdHandleKeyboardEvent(ki, KeyRelease, key);
1975 nEvents = GetKeyboardEvents(kdEvents, ki->dixdev, KeyRelease, key);
1976 for (i = 0; i < nEvents; i++)
1977 KdQueueEvent (ki->dixdev, kdEvents + i);
1982 KdUnblockSigio ();
1985 static void
1986 KdCheckLock (void)
1988 KeyClassPtr keyc = NULL;
1989 Bool isSet = FALSE, shouldBeSet = FALSE;
1990 KdKeyboardInfo *tmp = NULL;
1992 for (tmp = kdKeyboards; tmp; tmp = tmp->next) {
1993 if (tmp->LockLed && tmp->dixdev && tmp->dixdev->key) {
1994 keyc = tmp->dixdev->key;
1995 isSet = (tmp->leds & (1 << (tmp->LockLed-1))) != 0;
1996 shouldBeSet = (keyc->state & LockMask) != 0;
1997 if (isSet != shouldBeSet)
1998 KdSetLed (tmp, tmp->LockLed, shouldBeSet);
2003 void
2004 KdEnqueueKeyboardEvent(KdKeyboardInfo *ki,
2005 unsigned char scan_code,
2006 unsigned char is_up)
2008 unsigned char key_code;
2009 KeyClassPtr keyc = NULL;
2010 KeybdCtrl *ctrl = NULL;
2011 int type, nEvents, i;
2013 if (!ki || !ki->dixdev || !ki->dixdev->kbdfeed || !ki->dixdev->key)
2014 return;
2016 keyc = ki->dixdev->key;
2017 ctrl = &ki->dixdev->kbdfeed->ctrl;
2019 if (scan_code >= ki->minScanCode && scan_code <= ki->maxScanCode)
2021 key_code = scan_code + KD_MIN_KEYCODE - ki->minScanCode;
2024 * Set up this event -- the type may be modified below
2026 if (is_up)
2027 type = KeyRelease;
2028 else
2029 type = KeyPress;
2031 #ifdef XKB
2032 if (noXkbExtension)
2033 #endif
2035 KdCheckSpecialKeys(ki, type, key_code);
2036 KdHandleKeyboardEvent(ki, type, key_code);
2039 nEvents = GetKeyboardEvents(kdEvents, ki->dixdev, type, key_code);
2040 for (i = 0; i < nEvents; i++)
2041 KdQueueEvent(ki->dixdev, kdEvents + i);
2043 else {
2044 ErrorF("driver %s wanted to post scancode %d outside of [%d, %d]!\n",
2045 ki->name, scan_code, ki->minScanCode, ki->maxScanCode);
2050 * kdEnqueuePointerEvent
2052 * This function converts hardware mouse event information into X event
2053 * information. A mouse movement event is passed off to MI to generate
2054 * a MotionNotify event, if appropriate. Button events are created and
2055 * passed off to MI for enqueueing.
2058 /* FIXME do something a little more clever to deal with multiple axes here */
2059 void
2060 KdEnqueuePointerEvent(KdPointerInfo *pi, unsigned long flags, int rx, int ry,
2061 int rz)
2063 CARD32 ms;
2064 unsigned char buttons;
2065 int x, y, z;
2066 int (*matrix)[3] = kdPointerMatrix.matrix;
2067 unsigned long button;
2068 int n;
2069 int dixflags;
2071 if (!pi)
2072 return;
2074 ms = GetTimeInMillis();
2076 /* we don't need to transform z, so we don't. */
2077 if (flags & KD_MOUSE_DELTA) {
2078 if (pi->transformCoordinates) {
2079 x = matrix[0][0] * rx + matrix[0][1] * ry;
2080 y = matrix[1][0] * rx + matrix[1][1] * ry;
2082 else {
2083 x = rx;
2084 y = ry;
2087 else {
2088 if (pi->transformCoordinates) {
2089 x = matrix[0][0] * rx + matrix[0][1] * ry;
2090 y = matrix[1][0] * rx + matrix[1][1] * ry;
2092 else {
2093 x = rx;
2094 y = ry;
2097 z = rz;
2099 if (flags & KD_MOUSE_DELTA)
2100 dixflags = POINTER_RELATIVE & POINTER_ACCELERATE;
2101 else
2102 dixflags = POINTER_ABSOLUTE;
2104 _KdEnqueuePointerEvent(pi, MotionNotify, x, y, z, 0, dixflags, FALSE);
2106 buttons = flags;
2108 for (button = KD_BUTTON_1, n = 1; n <= pi->nButtons;
2109 button <<= 1, n++) {
2110 if (((pi->buttonState & button) ^ (buttons & button)) &&
2111 !(buttons & button)) {
2112 _KdEnqueuePointerEvent(pi, ButtonRelease, x, y, z, n,
2113 dixflags, FALSE);
2116 for (button = KD_BUTTON_1, n = 1; n <= pi->nButtons;
2117 button <<= 1, n++) {
2118 if (((pi->buttonState & button) ^ (buttons & button)) &&
2119 (buttons & button)) {
2120 _KdEnqueuePointerEvent(pi, ButtonPress, x, y, z, n,
2121 dixflags, FALSE);
2125 pi->buttonState = buttons;
2128 void
2129 _KdEnqueuePointerEvent (KdPointerInfo *pi, int type, int x, int y, int z,
2130 int b, int absrel, Bool force)
2132 int nEvents = 0, i = 0;
2133 int valuators[3] = { x, y, z };
2135 /* TRUE from KdHandlePointerEvent, means 'we swallowed the event'. */
2136 if (!force && KdHandlePointerEvent(pi, type, x, y, z, b, absrel))
2137 return;
2139 nEvents = GetPointerEvents(kdEvents, pi->dixdev, type, b, absrel, 0, 3,
2140 valuators);
2141 for (i = 0; i < nEvents; i++)
2142 KdQueueEvent(pi->dixdev, kdEvents + i);
2145 void
2146 KdBlockHandler (int screen,
2147 pointer blockData,
2148 pointer timeout,
2149 pointer readmask)
2151 KdPointerInfo *pi;
2152 int myTimeout=0;
2154 for (pi = kdPointers; pi; pi = pi->next)
2156 if (pi->timeoutPending)
2158 int ms;
2160 ms = pi->emulationTimeout - GetTimeInMillis ();
2161 if (ms < 1)
2162 ms = 1;
2163 if(ms<myTimeout || myTimeout==0)
2164 myTimeout=ms;
2167 /* if we need to poll for events, do that */
2168 if(kdOsFuncs->pollEvents)
2170 (*kdOsFuncs->pollEvents)();
2171 myTimeout=20;
2173 if(myTimeout>0)
2174 AdjustWaitForDelay (timeout, myTimeout);
2177 void
2178 KdWakeupHandler (int screen,
2179 pointer data,
2180 unsigned long lresult,
2181 pointer readmask)
2183 int result = (int) lresult;
2184 fd_set *pReadmask = (fd_set *) readmask;
2185 int i;
2186 KdPointerInfo *pi;
2188 if (kdInputEnabled && result > 0)
2190 for (i = 0; i < kdNumInputFds; i++)
2191 if (FD_ISSET (kdInputFds[i].fd, pReadmask))
2193 KdBlockSigio ();
2194 (*kdInputFds[i].read) (kdInputFds[i].fd, kdInputFds[i].closure);
2195 KdUnblockSigio ();
2198 for (pi = kdPointers; pi; pi = pi->next)
2200 if (pi->timeoutPending)
2202 if ((long) (GetTimeInMillis () - pi->emulationTimeout) >= 0)
2204 pi->timeoutPending = FALSE;
2205 KdBlockSigio ();
2206 KdReceiveTimeout (pi);
2207 KdUnblockSigio ();
2211 if (kdSwitchPending)
2212 KdProcessSwitch ();
2215 #define KdScreenOrigin(pScreen) (&(KdGetScreenPriv(pScreen)->screen->origin))
2217 static Bool
2218 KdCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y)
2220 ScreenPtr pScreen = *ppScreen;
2221 ScreenPtr pNewScreen;
2222 int n;
2223 int dx, dy;
2224 int best_x, best_y;
2225 int n_best_x, n_best_y;
2226 CARD32 ms;
2228 if (kdDisableZaphod || screenInfo.numScreens <= 1)
2229 return FALSE;
2231 if (0 <= *x && *x < pScreen->width && 0 <= *y && *y < pScreen->height)
2232 return FALSE;
2234 ms = GetTimeInMillis ();
2235 if (kdOffScreen && (int) (ms - kdOffScreenTime) < 1000)
2236 return FALSE;
2237 kdOffScreen = TRUE;
2238 kdOffScreenTime = ms;
2239 n_best_x = -1;
2240 best_x = 32767;
2241 n_best_y = -1;
2242 best_y = 32767;
2243 for (n = 0; n < screenInfo.numScreens; n++)
2245 pNewScreen = screenInfo.screens[n];
2246 if (pNewScreen == pScreen)
2247 continue;
2248 dx = KdScreenOrigin(pNewScreen)->x - KdScreenOrigin(pScreen)->x;
2249 dy = KdScreenOrigin(pNewScreen)->y - KdScreenOrigin(pScreen)->y;
2250 if (*x < 0)
2252 if (dx <= 0 && -dx < best_x)
2254 best_x = -dx;
2255 n_best_x = n;
2258 else if (*x >= pScreen->width)
2260 if (dx >= 0 && dx < best_x)
2262 best_x = dx;
2263 n_best_x = n;
2266 if (*y < 0)
2268 if (dy <= 0 && -dy < best_y)
2270 best_y = -dy;
2271 n_best_y = n;
2274 else if (*y >= pScreen->height)
2276 if (dy >= 0 && dy < best_y)
2278 best_y = dy;
2279 n_best_y = n;
2283 if (best_y < best_x)
2284 n_best_x = n_best_y;
2285 if (n_best_x == -1)
2286 return FALSE;
2287 pNewScreen = screenInfo.screens[n_best_x];
2289 if (*x < 0)
2290 *x += pNewScreen->width;
2291 if (*y < 0)
2292 *y += pNewScreen->height;
2294 if (*x >= pScreen->width)
2295 *x -= pScreen->width;
2296 if (*y >= pScreen->height)
2297 *y -= pScreen->height;
2299 *ppScreen = pNewScreen;
2300 return TRUE;
2303 static void
2304 KdCrossScreen(ScreenPtr pScreen, Bool entering)
2306 #ifndef XIPAQ
2307 if (entering)
2308 KdEnableScreen (pScreen);
2309 else
2310 KdDisableScreen (pScreen);
2311 #endif
2314 int KdCurScreen; /* current event screen */
2316 static void
2317 KdWarpCursor (ScreenPtr pScreen, int x, int y)
2319 KdBlockSigio ();
2320 KdCurScreen = pScreen->myNum;
2321 miPointerWarpCursor (pScreen, x, y);
2322 KdUnblockSigio ();
2325 miPointerScreenFuncRec kdPointerScreenFuncs =
2327 KdCursorOffScreen,
2328 KdCrossScreen,
2329 KdWarpCursor
2332 void
2333 ProcessInputEvents ()
2335 mieqProcessInputEvents();
2336 miPointerUpdate();
2337 if (kdSwitchPending)
2338 KdProcessSwitch ();
2339 KdCheckLock ();
2342 /* FIXME use XSECURITY to work out whether the client should be allowed to
2343 * open and close. */
2344 void
2345 OpenInputDevice(DeviceIntPtr pDev, ClientPtr client, int *status)
2347 if (!pDev)
2348 *status = BadDevice;
2349 else
2350 *status = Success;
2353 void
2354 CloseInputDevice(DeviceIntPtr pDev, ClientPtr client)
2356 return;
2359 /* We initialise all input devices at startup. */
2360 void
2361 AddOtherInputDevices(void)
2363 return;
2366 /* At the moment, absolute/relative is up to the client. */
2368 SetDeviceMode(register ClientPtr client, DeviceIntPtr pDev, int mode)
2370 return BadMatch;
2374 SetDeviceValuators(register ClientPtr client, DeviceIntPtr pDev,
2375 int *valuators, int first_valuator, int num_valuators)
2377 return BadMatch;
2381 ChangeDeviceControl(register ClientPtr client, DeviceIntPtr pDev,
2382 xDeviceCtl *control)
2384 switch (control->control) {
2385 case DEVICE_RESOLUTION:
2386 /* FIXME do something more intelligent here */
2387 return BadMatch;
2389 case DEVICE_ABS_CALIB:
2390 case DEVICE_ABS_AREA:
2391 return Success;
2393 case DEVICE_CORE:
2394 case DEVICE_ENABLE:
2395 return Success;
2397 default:
2398 return BadMatch;
2401 /* NOTREACHED */
2402 return BadImplementation;
2406 NewInputDeviceRequest(InputOption *options, DeviceIntPtr *pdev)
2408 InputOption *option = NULL;
2409 KdPointerInfo *pi = NULL;
2410 KdKeyboardInfo *ki = NULL;
2412 for (option = options; option; option = option->next) {
2413 if (strcmp(option->key, "type") == 0) {
2414 if (strcmp(option->value, "pointer") == 0) {
2415 pi = KdNewPointer();
2416 if (!pi)
2417 return BadAlloc;
2419 else if (strcmp(option->value, "keyboard") == 0) {
2420 ki = KdNewKeyboard();
2421 if (!ki)
2422 return BadAlloc;
2424 else {
2425 ErrorF("unrecognised device type!\n");
2426 return BadValue;
2431 if (!ki && !pi) {
2432 ErrorF("unrecognised device identifier!\n");
2433 return BadValue;
2436 /* FIXME: change this code below to use KdParseKbdOptions and
2437 * KdParsePointerOptions */
2438 for (option = options; option; option = option->next) {
2439 if (strcmp(option->key, "device") == 0) {
2440 if (pi && option->value)
2441 pi->path = KdSaveString(option->value);
2442 else if (ki && option->value)
2443 ki->path = KdSaveString(option->value);
2445 else if (strcmp(option->key, "driver") == 0) {
2446 if (pi) {
2447 pi->driver = KdFindPointerDriver(option->value);
2448 if (!pi->driver) {
2449 ErrorF("couldn't find driver!\n");
2450 KdFreePointer(pi);
2451 return BadValue;
2453 pi->options = options;
2455 else if (ki) {
2456 ki->driver = KdFindKeyboardDriver(option->value);
2457 if (!ki->driver) {
2458 ErrorF("couldn't find driver!\n");
2459 KdFreeKeyboard(ki);
2460 return BadValue;
2462 ki->options = options;
2467 if (pi) {
2468 if (KdAddPointer(pi) != Success ||
2469 ActivateDevice(pi->dixdev) != Success ||
2470 EnableDevice(pi->dixdev) != TRUE) {
2471 ErrorF("couldn't add or enable pointer\n");
2472 return BadImplementation;
2475 else if (ki) {
2476 if (KdAddKeyboard(ki) != Success ||
2477 ActivateDevice(ki->dixdev) != Success ||
2478 EnableDevice(ki->dixdev) != TRUE) {
2479 ErrorF("couldn't add or enable keyboard\n");
2480 return BadImplementation;
2484 if (pi) {
2485 *pdev = pi->dixdev;
2486 } else if(ki) {
2487 *pdev = ki->dixdev;
2490 return Success;
2493 void
2494 DeleteInputDeviceRequest(DeviceIntPtr pDev)
2496 RemoveDevice(pDev);