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