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