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