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