kinput.c revision 4642e01f
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    RegisterOtherDevice(ki->dixdev);
1025
1026#ifdef DEBUG
1027    ErrorF("added keyboard %s with dix id %d\n", ki->name, ki->dixdev->id);
1028#endif
1029
1030    for (prev = &kdKeyboards; *prev; prev = &(*prev)->next);
1031    *prev = ki;
1032
1033    return Success;
1034}
1035
1036void
1037KdRemoveKeyboard (KdKeyboardInfo *ki)
1038{
1039    KdKeyboardInfo **prev;
1040
1041    if (!ki)
1042        return;
1043
1044    for (prev = &kdKeyboards; *prev; prev = &(*prev)->next) {
1045        if (*prev == ki) {
1046            *prev = ki->next;
1047            break;
1048        }
1049    }
1050
1051    KdFreeKeyboard(ki);
1052}
1053
1054int
1055KdAddConfigPointer (char *pointer)
1056{
1057    struct KdConfigDevice **prev, *new;
1058
1059    if (!pointer)
1060        return Success;
1061
1062    new = (struct KdConfigDevice *) xcalloc(sizeof(struct KdConfigDevice), 1);
1063    if (!new)
1064        return BadAlloc;
1065
1066    new->line = xstrdup(pointer);
1067    new->next = NULL;
1068
1069    for (prev = &kdConfigPointers; *prev; prev = &(*prev)->next);
1070    *prev = new;
1071
1072    return Success;
1073}
1074
1075int
1076KdAddPointer (KdPointerInfo *pi)
1077{
1078    KdPointerInfo **prev;
1079
1080    if (!pi)
1081        return Success;
1082
1083    pi->mouseState = start;
1084    pi->eventHeld = FALSE;
1085
1086    pi->dixdev = AddInputDevice(serverClient, KdPointerProc, TRUE);
1087    if (!pi->dixdev) {
1088        ErrorF("Couldn't add pointer device %s\n",
1089               pi->name ? pi->name : "(unnamed)");
1090        return BadDevice;
1091    }
1092
1093    RegisterOtherDevice(pi->dixdev);
1094
1095    for (prev = &kdPointers; *prev; prev = &(*prev)->next);
1096    *prev = pi;
1097
1098    return Success;
1099}
1100
1101void
1102KdRemovePointer (KdPointerInfo *pi)
1103{
1104    KdPointerInfo **prev;
1105
1106    if (!pi)
1107        return;
1108
1109    for (prev = &kdPointers; *prev; prev = &(*prev)->next) {
1110        if (*prev == pi) {
1111            *prev = pi->next;
1112            break;
1113        }
1114    }
1115
1116    KdFreePointer(pi);
1117}
1118
1119/*
1120 * You can call your kdriver server with something like:
1121 * $ ./hw/kdrive/yourserver/X :1 -mouse evdev,,device=/dev/input/event4 -keybd
1122 * evdev,,device=/dev/input/event1,xkbmodel=abnt2,xkblayout=br
1123 */
1124static Bool
1125KdGetOptions (InputOption **options, char *string)
1126{
1127    InputOption     *newopt = NULL, **tmpo = NULL;
1128    int             tam_key = 0;
1129
1130    newopt = xcalloc(1, sizeof (InputOption));
1131    if (!newopt)
1132        return FALSE;
1133
1134    for (tmpo = options; *tmpo; tmpo = &(*tmpo)->next)
1135        ; /* Hello, I'm here */
1136    *tmpo = newopt;
1137
1138    if (strchr(string, '='))
1139    {
1140        tam_key = (strchr(string, '=') - string);
1141        newopt->key = (char *)xalloc(tam_key);
1142        strncpy(newopt->key, string, tam_key);
1143        newopt->key[tam_key] = '\0';
1144        newopt->value = xstrdup(strchr(string, '=') + 1);
1145    }
1146    else
1147    {
1148        newopt->key = xstrdup(string);
1149        newopt->value = NULL;
1150    }
1151    newopt->next = NULL;
1152
1153    return TRUE;
1154}
1155
1156static void
1157KdParseKbdOptions (KdKeyboardInfo *ki)
1158{
1159    InputOption *option = NULL;
1160
1161    for (option = ki->options; option; option = option->next)
1162    {
1163#ifdef XKB
1164        if (strcasecmp(option->key, "XkbRules") == 0)
1165            ki->xkbRules = option->value;
1166        else if (strcasecmp(option->key, "XkbModel") == 0)
1167            ki->xkbModel = option->value;
1168        else if (strcasecmp(option->key, "XkbLayout") == 0)
1169            ki->xkbLayout = option->value;
1170        else if (strcasecmp(option->key, "XkbVariant") == 0)
1171            ki->xkbVariant = option->value;
1172        else if (strcasecmp(option->key, "XkbOptions") == 0)
1173            ki->xkbOptions = option->value;
1174        else if (!strcasecmp (option->key, "device"))
1175            ki->path = KdSaveString(option->value);
1176        else
1177#endif
1178           ErrorF("Kbd option key (%s) of value (%s) not assigned!\n",
1179                    option->key, option->value);
1180    }
1181}
1182
1183KdKeyboardInfo *
1184KdParseKeyboard (char *arg)
1185{
1186    char            save[1024];
1187    char            delim;
1188    InputOption     *options = NULL;
1189    KdKeyboardInfo     *ki = NULL;
1190
1191    ki = KdNewKeyboard();
1192    if (!ki)
1193        return NULL;
1194
1195    ki->name = strdup("Unknown KDrive Keyboard");
1196    ki->path = NULL;
1197    ki->driver = NULL;
1198    ki->driverPrivate = NULL;
1199#ifdef XKB
1200    ki->xkb = NULL;
1201#endif
1202    ki->next = NULL;
1203
1204    if (!arg)
1205    {
1206        ErrorF("keybd: no arg\n");
1207        KdFreeKeyboard (ki);
1208        return NULL;
1209    }
1210
1211    if (strlen (arg) >= sizeof (save))
1212    {
1213        ErrorF("keybd: arg too long\n");
1214        KdFreeKeyboard (ki);
1215        return NULL;
1216    }
1217
1218    arg = KdParseFindNext (arg, ",", save, &delim);
1219    if (!save[0])
1220    {
1221        ErrorF("keybd: failed on save[0]\n");
1222        KdFreeKeyboard (ki);
1223        return NULL;
1224    }
1225
1226    if (strcmp (save, "auto") == 0)
1227        ki->driverPrivate = NULL;
1228    else
1229        ki->driverPrivate = xstrdup(save);
1230
1231    if (delim != ',')
1232    {
1233        return ki;
1234    }
1235
1236    arg = KdParseFindNext (arg, ",", save, &delim);
1237
1238    while (delim == ',')
1239    {
1240        arg = KdParseFindNext (arg, ",", save, &delim);
1241
1242	if (!KdGetOptions(&options, save))
1243	{
1244	    KdFreeKeyboard(ki);
1245	    return NULL;
1246        }
1247    }
1248
1249    if (options)
1250    {
1251        ki->options = options;
1252        KdParseKbdOptions(ki);
1253    }
1254
1255    return ki;
1256}
1257
1258static void
1259KdParsePointerOptions (KdPointerInfo *pi)
1260{
1261    InputOption *option = NULL;
1262
1263    for (option = pi->options; option; option = option->next)
1264    {
1265        if (!strcmp (option->key, "emulatemiddle"))
1266            pi->emulateMiddleButton = TRUE;
1267        else if (!strcmp (option->key, "noemulatemiddle"))
1268            pi->emulateMiddleButton = FALSE;
1269        else if (!strcmp (option->key, "transformcoord"))
1270            pi->transformCoordinates = TRUE;
1271        else if (!strcmp (option->key, "rawcoord"))
1272            pi->transformCoordinates = FALSE;
1273        else if (!strcasecmp (option->key, "device"))
1274            pi->path = KdSaveString(option->value);
1275        else
1276            ErrorF("Pointer option key (%s) of value (%s) not assigned!\n",
1277                    option->key, option->value);
1278    }
1279}
1280
1281KdPointerInfo *
1282KdParsePointer (char *arg)
1283{
1284    char            save[1024];
1285    char            delim;
1286    KdPointerInfo   *pi = NULL;
1287    InputOption     *options = NULL;
1288    int             i = 0;
1289
1290    pi = KdNewPointer();
1291    if (!pi)
1292        return NULL;
1293    pi->emulateMiddleButton = kdEmulateMiddleButton;
1294    pi->transformCoordinates = !kdRawPointerCoordinates;
1295    pi->nButtons = 5; /* XXX should not be hardcoded */
1296    pi->inputClass = KD_MOUSE;
1297
1298    if (!arg)
1299    {
1300        ErrorF("mouse: no arg\n");
1301        KdFreePointer (pi);
1302        return NULL;
1303    }
1304
1305    if (strlen (arg) >= sizeof (save))
1306    {
1307        ErrorF("mouse: arg too long\n");
1308        KdFreePointer (pi);
1309        return NULL;
1310    }
1311    arg = KdParseFindNext (arg, ",", save, &delim);
1312    if (!save[0])
1313    {
1314        ErrorF("failed on save[0]\n");
1315        KdFreePointer (pi);
1316        return NULL;
1317    }
1318
1319    if (strcmp(save, "auto") == 0)
1320        pi->driverPrivate = NULL;
1321    else
1322        pi->driverPrivate = xstrdup(save);
1323
1324    if (delim != ',')
1325    {
1326        return pi;
1327    }
1328
1329    arg = KdParseFindNext (arg, ",", save, &delim);
1330
1331    while (delim == ',')
1332    {
1333        arg = KdParseFindNext (arg, ",", save, &delim);
1334        if (save[0] == '{')
1335        {
1336            char *s = save + 1;
1337             i = 0;
1338             while (*s && *s != '}')
1339             {
1340                if ('1' <= *s && *s <= '0' + pi->nButtons)
1341                    pi->map[i] = *s - '0';
1342                else
1343                    UseMsg ();
1344                s++;
1345             }
1346        }
1347        else
1348        {
1349            if (!KdGetOptions(&options, save))
1350            {
1351                KdFreePointer(pi);
1352                return NULL;
1353            }
1354        }
1355    }
1356
1357    if (options)
1358    {
1359        pi->options = options;
1360        KdParsePointerOptions(pi);
1361    }
1362
1363    return pi;
1364}
1365
1366
1367void
1368KdInitInput (void)
1369{
1370    KdPointerInfo *pi;
1371    KdKeyboardInfo *ki;
1372    struct KdConfigDevice *dev;
1373
1374    kdInputEnabled = TRUE;
1375
1376    for (dev = kdConfigPointers; dev; dev = dev->next) {
1377        pi = KdParsePointer(dev->line);
1378        if (!pi)
1379            ErrorF("Failed to parse pointer\n");
1380        if (KdAddPointer(pi) != Success)
1381            ErrorF("Failed to add pointer!\n");
1382    }
1383    for (dev = kdConfigKeyboards; dev; dev = dev->next) {
1384        ki = KdParseKeyboard(dev->line);
1385        if (!ki)
1386            ErrorF("Failed to parse keyboard\n");
1387        if (KdAddKeyboard(ki) != Success)
1388            ErrorF("Failed to add keyboard!\n");
1389    }
1390
1391    mieqInit();
1392}
1393
1394/*
1395 * Middle button emulation state machine
1396 *
1397 *  Possible transitions:
1398 *	Button 1 press	    v1
1399 *	Button 1 release    ^1
1400 *	Button 2 press	    v2
1401 *	Button 2 release    ^2
1402 *	Button 3 press	    v3
1403 *	Button 3 release    ^3
1404 *	Button other press  vo
1405 *	Button other release ^o
1406 *	Mouse motion	    <>
1407 *	Keyboard event	    k
1408 *	timeout		    ...
1409 *	outside box	    <->
1410 *
1411 *  States:
1412 *	start
1413 *	button_1_pend
1414 *	button_1_down
1415 *	button_2_down
1416 *	button_3_pend
1417 *	button_3_down
1418 *	synthetic_2_down_13
1419 *	synthetic_2_down_3
1420 *	synthetic_2_down_1
1421 *
1422 *  Transition diagram
1423 *
1424 *  start
1425 *	v1  -> (hold) (settimeout) button_1_pend
1426 *	^1  -> (deliver) start
1427 *	v2  -> (deliver) button_2_down
1428 *	^2  -> (deliever) start
1429 *	v3  -> (hold) (settimeout) button_3_pend
1430 *	^3  -> (deliver) start
1431 *	vo  -> (deliver) start
1432 *	^o  -> (deliver) start
1433 *	<>  -> (deliver) start
1434 *	k   -> (deliver) start
1435 *
1436 *  button_1_pend	(button 1 is down, timeout pending)
1437 *	^1  -> (release) (deliver) start
1438 *	v2  -> (release) (deliver) button_1_down
1439 *	^2  -> (release) (deliver) button_1_down
1440 *	v3  -> (cleartimeout) (generate v2) synthetic_2_down_13
1441 *	^3  -> (release) (deliver) button_1_down
1442 *	vo  -> (release) (deliver) button_1_down
1443 *	^o  -> (release) (deliver) button_1_down
1444 *	<-> -> (release) (deliver) button_1_down
1445 *	<>  -> (deliver) button_1_pend
1446 *	k   -> (release) (deliver) button_1_down
1447 *	... -> (release) button_1_down
1448 *
1449 *  button_1_down	(button 1 is down)
1450 *	^1  -> (deliver) start
1451 *	v2  -> (deliver) button_1_down
1452 *	^2  -> (deliver) button_1_down
1453 *	v3  -> (deliver) button_1_down
1454 *	^3  -> (deliver) button_1_down
1455 *	vo  -> (deliver) button_1_down
1456 *	^o  -> (deliver) button_1_down
1457 *	<>  -> (deliver) button_1_down
1458 *	k   -> (deliver) button_1_down
1459 *
1460 *  button_2_down	(button 2 is down)
1461 *	v1  -> (deliver) button_2_down
1462 *	^1  -> (deliver) button_2_down
1463 *	^2  -> (deliver) start
1464 *	v3  -> (deliver) button_2_down
1465 *	^3  -> (deliver) button_2_down
1466 *	vo  -> (deliver) button_2_down
1467 *	^o  -> (deliver) button_2_down
1468 *	<>  -> (deliver) button_2_down
1469 *	k   -> (deliver) button_2_down
1470 *
1471 *  button_3_pend	(button 3 is down, timeout pending)
1472 *	v1  -> (generate v2) synthetic_2_down
1473 *	^1  -> (release) (deliver) button_3_down
1474 *	v2  -> (release) (deliver) button_3_down
1475 *	^2  -> (release) (deliver) button_3_down
1476 *	^3  -> (release) (deliver) start
1477 *	vo  -> (release) (deliver) button_3_down
1478 *	^o  -> (release) (deliver) button_3_down
1479 *	<-> -> (release) (deliver) button_3_down
1480 *	<>  -> (deliver) button_3_pend
1481 *	k   -> (release) (deliver) button_3_down
1482 *	... -> (release) button_3_down
1483 *
1484 *  button_3_down	(button 3 is down)
1485 *	v1  -> (deliver) button_3_down
1486 *	^1  -> (deliver) button_3_down
1487 *	v2  -> (deliver) button_3_down
1488 *	^2  -> (deliver) button_3_down
1489 *	^3  -> (deliver) start
1490 *	vo  -> (deliver) button_3_down
1491 *	^o  -> (deliver) button_3_down
1492 *	<>  -> (deliver) button_3_down
1493 *	k   -> (deliver) button_3_down
1494 *
1495 *  synthetic_2_down_13	(button 1 and 3 are down)
1496 *	^1  -> (generate ^2) synthetic_2_down_3
1497 *	v2  -> synthetic_2_down_13
1498 *	^2  -> synthetic_2_down_13
1499 *	^3  -> (generate ^2) synthetic_2_down_1
1500 *	vo  -> (deliver) synthetic_2_down_13
1501 *	^o  -> (deliver) synthetic_2_down_13
1502 *	<>  -> (deliver) synthetic_2_down_13
1503 *	k   -> (deliver) synthetic_2_down_13
1504 *
1505 *  synthetic_2_down_3 (button 3 is down)
1506 *	v1  -> (deliver) synthetic_2_down_3
1507 *	^1  -> (deliver) synthetic_2_down_3
1508 *	v2  -> synthetic_2_down_3
1509 *	^2  -> synthetic_2_down_3
1510 *	^3  -> start
1511 *	vo  -> (deliver) synthetic_2_down_3
1512 *	^o  -> (deliver) synthetic_2_down_3
1513 *	<>  -> (deliver) synthetic_2_down_3
1514 *	k   -> (deliver) synthetic_2_down_3
1515 *
1516 *  synthetic_2_down_1 (button 1 is down)
1517 *	^1  -> start
1518 *	v2  -> synthetic_2_down_1
1519 *	^2  -> synthetic_2_down_1
1520 *	v3  -> (deliver) synthetic_2_down_1
1521 *	^3  -> (deliver) synthetic_2_down_1
1522 *	vo  -> (deliver) synthetic_2_down_1
1523 *	^o  -> (deliver) synthetic_2_down_1
1524 *	<>  -> (deliver) synthetic_2_down_1
1525 *	k   -> (deliver) synthetic_2_down_1
1526 */
1527
1528typedef enum _inputClass {
1529    down_1, up_1,
1530    down_2, up_2,
1531    down_3, up_3,
1532    down_o, up_o,
1533    motion, outside_box,
1534    keyboard, timeout,
1535    num_input_class
1536} KdInputClass;
1537
1538typedef enum _inputAction {
1539    noop,
1540    hold,
1541    setto,
1542    deliver,
1543    release,
1544    clearto,
1545    gen_down_2,
1546    gen_up_2
1547} KdInputAction;
1548
1549#define MAX_ACTIONS 2
1550
1551typedef struct _inputTransition {
1552    KdInputAction  actions[MAX_ACTIONS];
1553    KdPointerState nextState;
1554} KdInputTransition;
1555
1556static const
1557KdInputTransition  kdInputMachine[num_input_states][num_input_class] = {
1558    /* start */
1559    {
1560	{ { hold, setto },	    button_1_pend },	/* v1 */
1561	{ { deliver, noop },	    start },		/* ^1 */
1562	{ { deliver, noop },	    button_2_down },	/* v2 */
1563	{ { deliver, noop },	    start },		/* ^2 */
1564	{ { hold, setto },	    button_3_pend },	/* v3 */
1565	{ { deliver, noop },	    start },		/* ^3 */
1566	{ { deliver, noop },	    start },		/* vo */
1567	{ { deliver, noop },	    start },		/* ^o */
1568	{ { deliver, noop },	    start },		/* <> */
1569	{ { deliver, noop },	    start },		/* <-> */
1570	{ { noop, noop },	    start },		/* k */
1571	{ { noop, noop },	    start },		/* ... */
1572    },
1573    /* button_1_pend */
1574    {
1575	{ { noop, noop },	    button_1_pend },	/* v1 */
1576	{ { release, deliver },	    start },		/* ^1 */
1577	{ { release, deliver },	    button_1_down },	/* v2 */
1578	{ { release, deliver },	    button_1_down },	/* ^2 */
1579	{ { clearto, gen_down_2 },  synth_2_down_13 },	/* v3 */
1580	{ { release, deliver },	    button_1_down },	/* ^3 */
1581	{ { release, deliver },	    button_1_down },	/* vo */
1582	{ { release, deliver },	    button_1_down },	/* ^o */
1583	{ { deliver, noop },	    button_1_pend },	/* <> */
1584	{ { release, deliver },	    button_1_down },	/* <-> */
1585	{ { noop, noop },	    button_1_down },	/* k */
1586	{ { release, noop },	    button_1_down },	/* ... */
1587    },
1588    /* button_1_down */
1589    {
1590	{ { noop, noop },	    button_1_down },	/* v1 */
1591	{ { deliver, noop },	    start },		/* ^1 */
1592	{ { deliver, noop },	    button_1_down },	/* v2 */
1593	{ { deliver, noop },	    button_1_down },	/* ^2 */
1594	{ { deliver, noop },	    button_1_down },	/* v3 */
1595	{ { deliver, noop },	    button_1_down },	/* ^3 */
1596	{ { deliver, noop },	    button_1_down },	/* vo */
1597	{ { deliver, noop },	    button_1_down },	/* ^o */
1598	{ { deliver, noop },	    button_1_down },	/* <> */
1599	{ { deliver, noop },	    button_1_down },	/* <-> */
1600	{ { noop, noop },	    button_1_down },	/* k */
1601	{ { noop, noop },	    button_1_down },	/* ... */
1602    },
1603    /* button_2_down */
1604    {
1605	{ { deliver, noop },	    button_2_down },	/* v1 */
1606	{ { deliver, noop },	    button_2_down },	/* ^1 */
1607	{ { noop, noop },	    button_2_down },	/* v2 */
1608	{ { deliver, noop },	    start },		/* ^2 */
1609	{ { deliver, noop },	    button_2_down },	/* v3 */
1610	{ { deliver, noop },	    button_2_down },	/* ^3 */
1611	{ { deliver, noop },	    button_2_down },	/* vo */
1612	{ { deliver, noop },	    button_2_down },	/* ^o */
1613	{ { deliver, noop },	    button_2_down },	/* <> */
1614	{ { deliver, noop },	    button_2_down },	/* <-> */
1615	{ { noop, noop },	    button_2_down },	/* k */
1616	{ { noop, noop },	    button_2_down },	/* ... */
1617    },
1618    /* button_3_pend */
1619    {
1620	{ { clearto, gen_down_2 },  synth_2_down_13 },	/* v1 */
1621	{ { release, deliver },	    button_3_down },	/* ^1 */
1622	{ { release, deliver },	    button_3_down },	/* v2 */
1623	{ { release, deliver },	    button_3_down },	/* ^2 */
1624	{ { release, deliver },	    button_3_down },	/* v3 */
1625	{ { release, deliver },	    start },		/* ^3 */
1626	{ { release, deliver },	    button_3_down },	/* vo */
1627	{ { release, deliver },	    button_3_down },	/* ^o */
1628	{ { deliver, noop },	    button_3_pend },	/* <> */
1629	{ { release, deliver },	    button_3_down },	/* <-> */
1630	{ { release, noop },	    button_3_down },	/* k */
1631	{ { release, noop },	    button_3_down },	/* ... */
1632    },
1633    /* button_3_down */
1634    {
1635	{ { deliver, noop },	    button_3_down },	/* v1 */
1636	{ { deliver, noop },	    button_3_down },	/* ^1 */
1637	{ { deliver, noop },	    button_3_down },	/* v2 */
1638	{ { deliver, noop },	    button_3_down },	/* ^2 */
1639	{ { noop, noop },	    button_3_down },	/* v3 */
1640	{ { deliver, noop },	    start },		/* ^3 */
1641	{ { deliver, noop },	    button_3_down },	/* vo */
1642	{ { deliver, noop },	    button_3_down },	/* ^o */
1643	{ { deliver, noop },	    button_3_down },	/* <> */
1644	{ { deliver, noop },	    button_3_down },	/* <-> */
1645	{ { noop, noop },	    button_3_down },	/* k */
1646	{ { noop, noop },	    button_3_down },	/* ... */
1647    },
1648    /* synthetic_2_down_13 */
1649    {
1650	{ { noop, noop },	    synth_2_down_13 },	/* v1 */
1651	{ { gen_up_2, noop },	    synth_2_down_3 },	/* ^1 */
1652	{ { noop, noop },	    synth_2_down_13 },	/* v2 */
1653	{ { noop, noop },	    synth_2_down_13 },	/* ^2 */
1654	{ { noop, noop },	    synth_2_down_13 },	/* v3 */
1655	{ { gen_up_2, noop },	    synth_2_down_1 },	/* ^3 */
1656	{ { deliver, noop },	    synth_2_down_13 },	/* vo */
1657	{ { deliver, noop },	    synth_2_down_13 },	/* ^o */
1658	{ { deliver, noop },	    synth_2_down_13 },	/* <> */
1659	{ { deliver, noop },	    synth_2_down_13 },	/* <-> */
1660	{ { noop, noop },	    synth_2_down_13 },	/* k */
1661	{ { noop, noop },	    synth_2_down_13 },	/* ... */
1662    },
1663    /* synthetic_2_down_3 */
1664    {
1665	{ { deliver, noop },	    synth_2_down_3 },	/* v1 */
1666	{ { deliver, noop },	    synth_2_down_3 },	/* ^1 */
1667	{ { deliver, noop },	    synth_2_down_3 },	/* v2 */
1668	{ { deliver, noop },	    synth_2_down_3 },	/* ^2 */
1669	{ { noop, noop },	    synth_2_down_3 },	/* v3 */
1670	{ { noop, noop },	    start },		/* ^3 */
1671	{ { deliver, noop },	    synth_2_down_3 },	/* vo */
1672	{ { deliver, noop },	    synth_2_down_3 },	/* ^o */
1673	{ { deliver, noop },	    synth_2_down_3 },	/* <> */
1674	{ { deliver, noop },	    synth_2_down_3 },	/* <-> */
1675	{ { noop, noop },	    synth_2_down_3 },	/* k */
1676	{ { noop, noop },	    synth_2_down_3 },	/* ... */
1677    },
1678    /* synthetic_2_down_1 */
1679    {
1680	{ { noop, noop },	    synth_2_down_1 },	/* v1 */
1681	{ { noop, noop },	    start },		/* ^1 */
1682	{ { deliver, noop },	    synth_2_down_1 },	/* v2 */
1683	{ { deliver, noop },	    synth_2_down_1 },	/* ^2 */
1684	{ { deliver, noop },	    synth_2_down_1 },	/* v3 */
1685	{ { deliver, noop },	    synth_2_down_1 },	/* ^3 */
1686	{ { deliver, noop },	    synth_2_down_1 },	/* vo */
1687	{ { deliver, noop },	    synth_2_down_1 },	/* ^o */
1688	{ { deliver, noop },	    synth_2_down_1 },	/* <> */
1689	{ { deliver, noop },	    synth_2_down_1 },	/* <-> */
1690	{ { noop, noop },	    synth_2_down_1 },	/* k */
1691	{ { noop, noop },	    synth_2_down_1 },	/* ... */
1692    },
1693};
1694
1695#define EMULATION_WINDOW    10
1696#define EMULATION_TIMEOUT   100
1697
1698static int
1699KdInsideEmulationWindow (KdPointerInfo *pi, int x, int y, int z)
1700{
1701    pi->emulationDx = pi->heldEvent.x - x;
1702    pi->emulationDy = pi->heldEvent.y - y;
1703
1704    return (abs (pi->emulationDx) < EMULATION_WINDOW &&
1705	    abs (pi->emulationDy) < EMULATION_WINDOW);
1706}
1707
1708static KdInputClass
1709KdClassifyInput (KdPointerInfo *pi, int type, int x, int y, int z, int b)
1710{
1711    switch (type) {
1712    case ButtonPress:
1713	switch (b) {
1714	case 1: return down_1;
1715	case 2: return down_2;
1716	case 3: return down_3;
1717	default: return down_o;
1718	}
1719	break;
1720    case ButtonRelease:
1721	switch (b) {
1722	case 1: return up_1;
1723	case 2: return up_2;
1724	case 3: return up_3;
1725	default: return up_o;
1726	}
1727	break;
1728    case MotionNotify:
1729	if (pi->eventHeld && !KdInsideEmulationWindow(pi, x, y, z))
1730	    return outside_box;
1731	else
1732	    return motion;
1733    default:
1734	return keyboard;
1735    }
1736    return keyboard;
1737}
1738
1739#ifdef DEBUG
1740char	*kdStateNames[] = {
1741    "start",
1742    "button_1_pend",
1743    "button_1_down",
1744    "button_2_down",
1745    "button_3_pend",
1746    "button_3_down",
1747    "synth_2_down_13",
1748    "synth_2_down_3",
1749    "synthetic_2_down_1",
1750    "num_input_states"
1751};
1752
1753char	*kdClassNames[] = {
1754    "down_1", "up_1",
1755    "down_2", "up_2",
1756    "down_3", "up_3",
1757    "motion", "ouside_box",
1758    "keyboard", "timeout",
1759    "num_input_class"
1760};
1761
1762char *kdActionNames[] = {
1763    "noop",
1764    "hold",
1765    "setto",
1766    "deliver",
1767    "release",
1768    "clearto",
1769    "gen_down_2",
1770    "gen_up_2",
1771};
1772#endif /* DEBUG */
1773
1774static void
1775KdQueueEvent (DeviceIntPtr pDev, xEvent *ev)
1776{
1777    KdAssertSigioBlocked ("KdQueueEvent");
1778    mieqEnqueue (pDev, ev);
1779}
1780
1781/* We return true if we're stealing the event. */
1782static Bool
1783KdRunMouseMachine (KdPointerInfo *pi, KdInputClass c, int type, int x, int y,
1784                   int z, int b, int absrel)
1785{
1786    const KdInputTransition *t;
1787    int	a;
1788
1789    c = KdClassifyInput(pi, type, x, y, z, b);
1790    t = &kdInputMachine[pi->mouseState][c];
1791    for (a = 0; a < MAX_ACTIONS; a++)
1792    {
1793	switch (t->actions[a]) {
1794	case noop:
1795	    break;
1796	case hold:
1797	    pi->eventHeld = TRUE;
1798	    pi->emulationDx = 0;
1799	    pi->emulationDy = 0;
1800	    pi->heldEvent.type = type;
1801            pi->heldEvent.x = x;
1802            pi->heldEvent.y = y;
1803            pi->heldEvent.z = z;
1804            pi->heldEvent.flags = b;
1805            pi->heldEvent.absrel = absrel;
1806            return TRUE;
1807	    break;
1808	case setto:
1809	    pi->emulationTimeout = GetTimeInMillis () + EMULATION_TIMEOUT;
1810	    pi->timeoutPending = TRUE;
1811	    break;
1812	case deliver:
1813            _KdEnqueuePointerEvent (pi, pi->heldEvent.type, pi->heldEvent.x,
1814                                    pi->heldEvent.y, pi->heldEvent.z,
1815                                    pi->heldEvent.flags, pi->heldEvent.absrel,
1816                                    TRUE);
1817	    break;
1818	case release:
1819	    pi->eventHeld = FALSE;
1820	    pi->timeoutPending = FALSE;
1821            _KdEnqueuePointerEvent (pi, pi->heldEvent.type, pi->heldEvent.x,
1822                                    pi->heldEvent.y, pi->heldEvent.z,
1823                                    pi->heldEvent.flags, pi->heldEvent.absrel,
1824                                    TRUE);
1825            return TRUE;
1826	    break;
1827	case clearto:
1828	    pi->timeoutPending = FALSE;
1829	    break;
1830	case gen_down_2:
1831            _KdEnqueuePointerEvent (pi, ButtonPress, x, y, z, 2, absrel,
1832                                    TRUE);
1833	    pi->eventHeld = FALSE;
1834            return TRUE;
1835	    break;
1836	case gen_up_2:
1837            _KdEnqueuePointerEvent (pi, ButtonRelease, x, y, z, 2, absrel,
1838                                    TRUE);
1839            return TRUE;
1840	    break;
1841	}
1842    }
1843    pi->mouseState = t->nextState;
1844    return FALSE;
1845}
1846
1847static int
1848KdHandlePointerEvent (KdPointerInfo *pi, int type, int x, int y, int z, int b,
1849                      int absrel)
1850{
1851    if (pi->emulateMiddleButton)
1852        return KdRunMouseMachine (pi, KdClassifyInput(pi, type, x, y, z, b),
1853                                  type, x, y, z, b, absrel);
1854    return FALSE;
1855}
1856
1857static void
1858KdReceiveTimeout (KdPointerInfo *pi)
1859{
1860    KdRunMouseMachine (pi, timeout, 0, 0, 0, 0, 0, 0);
1861}
1862
1863#define KILL_SEQUENCE     ((1L << KK_CONTROL)|(1L << KK_ALT)|(1L << KK_F8)|(1L << KK_F10))
1864#define SPECIAL_SEQUENCE  ((1L << KK_CONTROL) | (1L << KK_ALT))
1865#define SETKILLKEY(b)     (KdSpecialKeys |= (1L << (b)))
1866#define CLEARKILLKEY(b)   (KdSpecialKeys &= ~(1L << (b)))
1867
1868CARD32	KdSpecialKeys = 0;
1869
1870/*
1871 * kdCheckTermination
1872 *
1873 * This function checks for the key sequence that terminates the server.  When
1874 * detected, it sets the dispatchException flag and returns.  The key sequence
1875 * is:
1876 *	Control-Alt
1877 * It's assumed that the server will be waken up by the caller when this
1878 * function returns.
1879 */
1880
1881extern int nClients;
1882
1883static void
1884KdCheckSpecialKeys(KdKeyboardInfo *ki, int type, int sym)
1885{
1886    if (!ki)
1887        return;
1888
1889    /*
1890     * Ignore key releases
1891     */
1892
1893    if (type == KeyRelease)
1894        return;
1895
1896    /* Some iPaq keyboard -> mouse button mapping used to be here, but I
1897     * refuse to perpetuate this madness. -daniels */
1898
1899    /*
1900     * Check for control/alt pressed
1901     */
1902    if ((ki->dixdev->key->state & (ControlMask|Mod1Mask)) !=
1903	(ControlMask|Mod1Mask))
1904	return;
1905
1906    /*
1907     * Let OS function see keysym first
1908     */
1909
1910    if (kdOsFuncs->SpecialKey)
1911	if ((*kdOsFuncs->SpecialKey) (sym))
1912	    return;
1913
1914    /*
1915     * Now check for backspace or delete; these signal the
1916     * X server to terminate
1917     *
1918     * I can't believe it's not XKB. -daniels
1919     */
1920    switch (sym) {
1921    case XK_BackSpace:
1922    case XK_Delete:
1923    case XK_KP_Delete:
1924	/*
1925	 * Set the dispatch exception flag so the server will terminate the
1926	 * next time through the dispatch loop.
1927	 */
1928	if (kdAllowZap || party_like_its_1989)
1929	    dispatchException |= DE_TERMINATE;
1930	break;
1931    }
1932}
1933
1934/*
1935 * kdEnqueueKeyboardEvent
1936 *
1937 * This function converts hardware keyboard event information into an X event
1938 * and enqueues it using MI.  It wakes up the server before returning so that
1939 * the event will be processed normally.
1940 *
1941 */
1942
1943static void
1944KdHandleKeyboardEvent (KdKeyboardInfo *ki, int type, int key)
1945{
1946    int           byte;
1947    CARD8         bit;
1948    KdPointerInfo *pi;
1949
1950    byte = key >> 3;
1951    bit = 1 << (key & 7);
1952
1953    switch (type) {
1954    case KeyPress:
1955	ki->keyState[byte] |= bit;
1956	break;
1957    case KeyRelease:
1958	ki->keyState[byte] &= ~bit;
1959	break;
1960    }
1961
1962    for (pi = kdPointers; pi; pi = pi->next)
1963	KdRunMouseMachine (pi, keyboard, 0, 0, 0, 0, 0, 0);
1964}
1965
1966void
1967KdReleaseAllKeys (void)
1968{
1969    int	key, nEvents, i;
1970    KdKeyboardInfo *ki;
1971
1972    KdBlockSigio ();
1973
1974    for (ki = kdKeyboards; ki; ki = ki->next) {
1975        for (key = ki->keySyms.minKeyCode; key < ki->keySyms.maxKeyCode;
1976             key++) {
1977            if (IsKeyDown(ki, key)) {
1978                KdHandleKeyboardEvent(ki, KeyRelease, key);
1979                GetEventList(&kdEvents);
1980                nEvents = GetKeyboardEvents(kdEvents, ki->dixdev, KeyRelease, key);
1981                for (i = 0; i < nEvents; i++)
1982                    KdQueueEvent (ki->dixdev, (kdEvents + i)->event);
1983            }
1984        }
1985    }
1986
1987    KdUnblockSigio ();
1988}
1989
1990static void
1991KdCheckLock (void)
1992{
1993    KeyClassPtr	    keyc = NULL;
1994    Bool	    isSet = FALSE, shouldBeSet = FALSE;
1995    KdKeyboardInfo     *tmp = NULL;
1996
1997    for (tmp = kdKeyboards; tmp; tmp = tmp->next) {
1998        if (tmp->LockLed && tmp->dixdev && tmp->dixdev->key) {
1999            keyc = tmp->dixdev->key;
2000            isSet = (tmp->leds & (1 << (tmp->LockLed-1))) != 0;
2001            shouldBeSet = (keyc->state & LockMask) != 0;
2002            if (isSet != shouldBeSet)
2003                KdSetLed (tmp, tmp->LockLed, shouldBeSet);
2004        }
2005    }
2006}
2007
2008void
2009KdEnqueueKeyboardEvent(KdKeyboardInfo   *ki,
2010                       unsigned char scan_code,
2011		       unsigned char is_up)
2012{
2013    unsigned char key_code;
2014    KeyClassPtr	keyc = NULL;
2015    KeybdCtrl *ctrl = NULL;
2016    int type, nEvents, i;
2017
2018    if (!ki || !ki->dixdev || !ki->dixdev->kbdfeed || !ki->dixdev->key)
2019	return;
2020
2021    keyc = ki->dixdev->key;
2022    ctrl = &ki->dixdev->kbdfeed->ctrl;
2023
2024    if (scan_code >= ki->minScanCode && scan_code <= ki->maxScanCode)
2025    {
2026	key_code = scan_code + KD_MIN_KEYCODE - ki->minScanCode;
2027
2028	/*
2029	 * Set up this event -- the type may be modified below
2030	 */
2031	if (is_up)
2032	    type = KeyRelease;
2033	else
2034	    type = KeyPress;
2035
2036#ifdef XKB
2037        if (noXkbExtension)
2038#endif
2039        {
2040            KdCheckSpecialKeys(ki, type, key_code);
2041            KdHandleKeyboardEvent(ki, type, key_code);
2042	}
2043
2044        GetEventList(&kdEvents);
2045        nEvents = GetKeyboardEvents(kdEvents, ki->dixdev, type, key_code);
2046        for (i = 0; i < nEvents; i++)
2047            KdQueueEvent(ki->dixdev, (kdEvents + i)->event);
2048    }
2049    else {
2050        ErrorF("driver %s wanted to post scancode %d outside of [%d, %d]!\n",
2051               ki->name, scan_code, ki->minScanCode, ki->maxScanCode);
2052    }
2053}
2054
2055/*
2056 * kdEnqueuePointerEvent
2057 *
2058 * This function converts hardware mouse event information into X event
2059 * information.  A mouse movement event is passed off to MI to generate
2060 * a MotionNotify event, if appropriate.  Button events are created and
2061 * passed off to MI for enqueueing.
2062 */
2063
2064/* FIXME do something a little more clever to deal with multiple axes here */
2065void
2066KdEnqueuePointerEvent(KdPointerInfo *pi, unsigned long flags, int rx, int ry,
2067                      int rz)
2068{
2069    CARD32        ms;
2070    unsigned char buttons;
2071    int           x, y, z;
2072    int           (*matrix)[3] = kdPointerMatrix.matrix;
2073    unsigned long button;
2074    int           n;
2075    int           dixflags = 0;
2076
2077    if (!pi)
2078	return;
2079
2080    ms = GetTimeInMillis();
2081
2082    /* we don't need to transform z, so we don't. */
2083    if (flags & KD_MOUSE_DELTA) {
2084	if (pi->transformCoordinates) {
2085	    x = matrix[0][0] * rx + matrix[0][1] * ry;
2086	    y = matrix[1][0] * rx + matrix[1][1] * ry;
2087	}
2088	else {
2089	    x = rx;
2090	    y = ry;
2091	}
2092    }
2093    else {
2094	if (pi->transformCoordinates) {
2095	    x = matrix[0][0] * rx + matrix[0][1] * ry;
2096	    y = matrix[1][0] * rx + matrix[1][1] * ry;
2097	}
2098	else {
2099	    x = rx;
2100	    y = ry;
2101	}
2102    }
2103    z = rz;
2104
2105    if (flags & KD_MOUSE_DELTA)
2106    {
2107        if (x || y || z)
2108        {
2109            dixflags = POINTER_RELATIVE | POINTER_ACCELERATE;
2110            _KdEnqueuePointerEvent(pi, MotionNotify, x, y, z, 0, dixflags, FALSE);
2111        }
2112    } else
2113    {
2114        dixflags = POINTER_ABSOLUTE;
2115        if (x != pi->dixdev->last.valuators[0] ||
2116            y != pi->dixdev->last.valuators[1])
2117            _KdEnqueuePointerEvent(pi, MotionNotify, x, y, z, 0, dixflags, FALSE);
2118    }
2119
2120    buttons = flags;
2121
2122    for (button = KD_BUTTON_1, n = 1; n <= pi->nButtons;
2123         button <<= 1, n++) {
2124        if (((pi->buttonState & button) ^ (buttons & button)) &&
2125           !(buttons & button)) {
2126            _KdEnqueuePointerEvent(pi, ButtonRelease, x, y, z, n,
2127                                   dixflags, FALSE);
2128	}
2129    }
2130    for (button = KD_BUTTON_1, n = 1; n <= pi->nButtons;
2131         button <<= 1, n++) {
2132	if (((pi->buttonState & button) ^ (buttons & button)) &&
2133	    (buttons & button)) {
2134            _KdEnqueuePointerEvent(pi, ButtonPress, x, y, z, n,
2135                                   dixflags, FALSE);
2136        }
2137    }
2138
2139    pi->buttonState = buttons;
2140}
2141
2142void
2143_KdEnqueuePointerEvent (KdPointerInfo *pi, int type, int x, int y, int z,
2144                        int b, int absrel, Bool force)
2145{
2146    int nEvents = 0, i = 0;
2147    int valuators[3] = { x, y, z };
2148
2149    /* TRUE from KdHandlePointerEvent, means 'we swallowed the event'. */
2150    if (!force && KdHandlePointerEvent(pi, type, x, y, z, b, absrel))
2151        return;
2152
2153    GetEventList(&kdEvents);
2154    nEvents = GetPointerEvents(kdEvents, pi->dixdev, type, b, absrel,
2155                               0, 3, valuators);
2156    for (i = 0; i < nEvents; i++)
2157        KdQueueEvent(pi->dixdev, (kdEvents + i)->event);
2158}
2159
2160void
2161KdBlockHandler (int		screen,
2162		pointer		blockData,
2163		pointer		timeout,
2164		pointer		readmask)
2165{
2166    KdPointerInfo		    *pi;
2167    int myTimeout=0;
2168
2169    for (pi = kdPointers; pi; pi = pi->next)
2170    {
2171	if (pi->timeoutPending)
2172	{
2173	    int	ms;
2174
2175	    ms = pi->emulationTimeout - GetTimeInMillis ();
2176	    if (ms < 1)
2177		ms = 1;
2178	    if(ms<myTimeout || myTimeout==0)
2179		    myTimeout=ms;
2180	}
2181    }
2182    /* if we need to poll for events, do that */
2183    if(kdOsFuncs->pollEvents)
2184    {
2185	    (*kdOsFuncs->pollEvents)();
2186	    myTimeout=20;
2187    }
2188    if(myTimeout>0)
2189    	AdjustWaitForDelay (timeout, myTimeout);
2190}
2191
2192void
2193KdWakeupHandler (int		screen,
2194		 pointer    	data,
2195		 unsigned long	lresult,
2196		 pointer	readmask)
2197{
2198    int		result = (int) lresult;
2199    fd_set	*pReadmask = (fd_set *) readmask;
2200    int		i;
2201    KdPointerInfo	*pi;
2202
2203    if (kdInputEnabled && result > 0)
2204    {
2205	for (i = 0; i < kdNumInputFds; i++)
2206	    if (FD_ISSET (kdInputFds[i].fd, pReadmask))
2207	    {
2208		KdBlockSigio ();
2209		(*kdInputFds[i].read) (kdInputFds[i].fd, kdInputFds[i].closure);
2210		KdUnblockSigio ();
2211	    }
2212    }
2213    for (pi = kdPointers; pi; pi = pi->next)
2214    {
2215	if (pi->timeoutPending)
2216	{
2217	    if ((long) (GetTimeInMillis () - pi->emulationTimeout) >= 0)
2218	    {
2219		pi->timeoutPending = FALSE;
2220		KdBlockSigio ();
2221		KdReceiveTimeout (pi);
2222		KdUnblockSigio ();
2223	    }
2224	}
2225    }
2226    if (kdSwitchPending)
2227	KdProcessSwitch ();
2228}
2229
2230#define KdScreenOrigin(pScreen) (&(KdGetScreenPriv(pScreen)->screen->origin))
2231
2232static Bool
2233KdCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y)
2234{
2235    ScreenPtr	pScreen  = *ppScreen;
2236    ScreenPtr	pNewScreen;
2237    int		n;
2238    int		dx, dy;
2239    int		best_x, best_y;
2240    int		n_best_x, n_best_y;
2241    CARD32	ms;
2242
2243    if (kdDisableZaphod || screenInfo.numScreens <= 1)
2244	return FALSE;
2245
2246    if (0 <= *x && *x < pScreen->width && 0 <= *y && *y < pScreen->height)
2247	return FALSE;
2248
2249    ms = GetTimeInMillis ();
2250    if (kdOffScreen && (int) (ms - kdOffScreenTime) < 1000)
2251	return FALSE;
2252    kdOffScreen = TRUE;
2253    kdOffScreenTime = ms;
2254    n_best_x = -1;
2255    best_x = 32767;
2256    n_best_y = -1;
2257    best_y = 32767;
2258    for (n = 0; n < screenInfo.numScreens; n++)
2259    {
2260	pNewScreen = screenInfo.screens[n];
2261	if (pNewScreen == pScreen)
2262	    continue;
2263	dx = KdScreenOrigin(pNewScreen)->x - KdScreenOrigin(pScreen)->x;
2264	dy = KdScreenOrigin(pNewScreen)->y - KdScreenOrigin(pScreen)->y;
2265	if (*x < 0)
2266	{
2267	    if (dx <= 0 && -dx < best_x)
2268	    {
2269		best_x = -dx;
2270		n_best_x = n;
2271	    }
2272	}
2273	else if (*x >= pScreen->width)
2274	{
2275	    if (dx >= 0 && dx < best_x)
2276	    {
2277		best_x = dx;
2278		n_best_x = n;
2279	    }
2280	}
2281	if (*y < 0)
2282	{
2283	    if (dy <= 0 && -dy < best_y)
2284	    {
2285		best_y = -dy;
2286		n_best_y = n;
2287	    }
2288	}
2289	else if (*y >= pScreen->height)
2290	{
2291	    if (dy >= 0 && dy < best_y)
2292	    {
2293		best_y = dy;
2294		n_best_y = n;
2295	    }
2296	}
2297    }
2298    if (best_y < best_x)
2299	n_best_x = n_best_y;
2300    if (n_best_x == -1)
2301	return FALSE;
2302    pNewScreen = screenInfo.screens[n_best_x];
2303
2304    if (*x < 0)
2305	*x += pNewScreen->width;
2306    if (*y < 0)
2307	*y += pNewScreen->height;
2308
2309    if (*x >= pScreen->width)
2310	*x -= pScreen->width;
2311    if (*y >= pScreen->height)
2312	*y -= pScreen->height;
2313
2314    *ppScreen = pNewScreen;
2315    return TRUE;
2316}
2317
2318static void
2319KdCrossScreen(ScreenPtr pScreen, Bool entering)
2320{
2321#ifndef XIPAQ
2322    if (entering)
2323	KdEnableScreen (pScreen);
2324    else
2325	KdDisableScreen (pScreen);
2326#endif
2327}
2328
2329int KdCurScreen;	/* current event screen */
2330
2331static void
2332KdWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
2333{
2334    KdBlockSigio ();
2335    KdCurScreen = pScreen->myNum;
2336    miPointerWarpCursor(pDev, pScreen, x, y);
2337    KdUnblockSigio ();
2338}
2339
2340miPointerScreenFuncRec kdPointerScreenFuncs =
2341{
2342    KdCursorOffScreen,
2343    KdCrossScreen,
2344    KdWarpCursor
2345};
2346
2347void
2348ProcessInputEvents ()
2349{
2350    mieqProcessInputEvents();
2351    miPointerUpdateSprite(inputInfo.pointer);
2352    if (kdSwitchPending)
2353	KdProcessSwitch ();
2354    KdCheckLock ();
2355}
2356
2357/* FIXME use XSECURITY to work out whether the client should be allowed to
2358 * open and close. */
2359void
2360OpenInputDevice(DeviceIntPtr pDev, ClientPtr client, int *status)
2361{
2362    if (!pDev)
2363        *status = BadDevice;
2364    else
2365        *status = Success;
2366}
2367
2368void
2369CloseInputDevice(DeviceIntPtr pDev, ClientPtr client)
2370{
2371    return;
2372}
2373
2374/* We initialise all input devices at startup. */
2375void
2376AddOtherInputDevices(void)
2377{
2378    return;
2379}
2380
2381/* At the moment, absolute/relative is up to the client. */
2382int
2383SetDeviceMode(register ClientPtr client, DeviceIntPtr pDev, int mode)
2384{
2385    return BadMatch;
2386}
2387
2388int
2389SetDeviceValuators(register ClientPtr client, DeviceIntPtr pDev,
2390                   int *valuators, int first_valuator, int num_valuators)
2391{
2392    return BadMatch;
2393}
2394
2395int
2396ChangeDeviceControl(register ClientPtr client, DeviceIntPtr pDev,
2397                        xDeviceCtl *control)
2398{
2399    switch (control->control) {
2400    case DEVICE_RESOLUTION:
2401        /* FIXME do something more intelligent here */
2402        return BadMatch;
2403
2404    case DEVICE_ABS_CALIB:
2405    case DEVICE_ABS_AREA:
2406        return Success;
2407
2408    case DEVICE_CORE:
2409        return BadMatch;
2410    case DEVICE_ENABLE:
2411        return Success;
2412
2413    default:
2414        return BadMatch;
2415    }
2416
2417    /* NOTREACHED */
2418    return BadImplementation;
2419}
2420
2421int
2422NewInputDeviceRequest(InputOption *options, DeviceIntPtr *pdev)
2423{
2424    InputOption *option = NULL;
2425    KdPointerInfo *pi = NULL;
2426    KdKeyboardInfo *ki = NULL;
2427
2428    for (option = options; option; option = option->next) {
2429        if (strcmp(option->key, "type") == 0) {
2430            if (strcmp(option->value, "pointer") == 0) {
2431                pi = KdNewPointer();
2432                if (!pi)
2433                    return BadAlloc;
2434            }
2435            else if (strcmp(option->value, "keyboard") == 0) {
2436                ki = KdNewKeyboard();
2437                if (!ki)
2438                    return BadAlloc;
2439            }
2440            else {
2441                ErrorF("unrecognised device type!\n");
2442                return BadValue;
2443            }
2444        }
2445    }
2446
2447    if (!ki && !pi) {
2448        ErrorF("unrecognised device identifier!\n");
2449        return BadValue;
2450    }
2451
2452    /* FIXME: change this code below to use KdParseKbdOptions and
2453     * KdParsePointerOptions */
2454    for (option = options; option; option = option->next) {
2455        if (strcmp(option->key, "device") == 0) {
2456            if (pi && option->value)
2457                pi->path = KdSaveString(option->value);
2458            else if (ki && option->value)
2459                ki->path = KdSaveString(option->value);
2460        }
2461        else if (strcmp(option->key, "driver") == 0) {
2462            if (pi) {
2463                pi->driver = KdFindPointerDriver(option->value);
2464                if (!pi->driver) {
2465                    ErrorF("couldn't find driver!\n");
2466                    KdFreePointer(pi);
2467                    return BadValue;
2468                }
2469                pi->options = options;
2470            }
2471            else if (ki) {
2472                ki->driver = KdFindKeyboardDriver(option->value);
2473                if (!ki->driver) {
2474                    ErrorF("couldn't find driver!\n");
2475                    KdFreeKeyboard(ki);
2476                    return BadValue;
2477                }
2478                ki->options = options;
2479            }
2480        }
2481    }
2482
2483    if (pi) {
2484        if (KdAddPointer(pi) != Success ||
2485            ActivateDevice(pi->dixdev) != Success ||
2486            EnableDevice(pi->dixdev) != TRUE) {
2487            ErrorF("couldn't add or enable pointer\n");
2488            return BadImplementation;
2489        }
2490    }
2491    else if (ki) {
2492        if (KdAddKeyboard(ki) != Success ||
2493            ActivateDevice(ki->dixdev) != Success ||
2494            EnableDevice(ki->dixdev) != TRUE) {
2495            ErrorF("couldn't add or enable keyboard\n");
2496            return BadImplementation;
2497        }
2498    }
2499
2500    if (pi) {
2501        *pdev = pi->dixdev;
2502    } else if(ki) {
2503        *pdev = ki->dixdev;
2504    }
2505
2506    return Success;
2507}
2508
2509void
2510DeleteInputDeviceRequest(DeviceIntPtr pDev)
2511{
2512    RemoveDevice(pDev);
2513}
2514