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