105b261ecSmrg/*
235c4bbdfSmrg * Copyright © 1999 Keith Packard
335c4bbdfSmrg * Copyright © 2006 Nokia Corporation
405b261ecSmrg *
505b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its
605b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that
705b261ecSmrg * the above copyright notice appear in all copies and that both that
805b261ecSmrg * copyright notice and this permission notice appear in supporting
905b261ecSmrg * documentation, and that the name of the authors not be used in
1005b261ecSmrg * advertising or publicity pertaining to distribution of the software without
1105b261ecSmrg * specific, written prior permission.  The authors make no
1205b261ecSmrg * representations about the suitability of this software for any purpose.  It
1305b261ecSmrg * is provided "as is" without express or implied warranty.
1405b261ecSmrg *
1505b261ecSmrg * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1605b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1705b261ecSmrg * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1805b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1905b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
2005b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2105b261ecSmrg * PERFORMANCE OF THIS SOFTWARE.
2205b261ecSmrg */
2305b261ecSmrg
241b5d61b8Smrg#ifdef HAVE_DIX_CONFIG_H
251b5d61b8Smrg#include <dix-config.h>
261b5d61b8Smrg#include <xkb-config.h>
2705b261ecSmrg#endif
2805b261ecSmrg#include "kdrive.h"
2905b261ecSmrg#include "inputstr.h"
3005b261ecSmrg
3105b261ecSmrg#define XK_PUBLISHING
3205b261ecSmrg#include <X11/keysym.h>
3305b261ecSmrg#if HAVE_X11_XF86KEYSYM_H
3405b261ecSmrg#include <X11/XF86keysym.h>
3505b261ecSmrg#endif
3605b261ecSmrg#include <stdio.h>
371b5d61b8Smrg#ifdef __sun
3835c4bbdfSmrg#include <sys/file.h>           /* needed for FNONBLOCK & FASYNC */
3905b261ecSmrg#endif
4005b261ecSmrg
416747b715Smrg#include "xkbsrv.h"
4205b261ecSmrg
4305b261ecSmrg#include <X11/extensions/XI.h>
4405b261ecSmrg#include <X11/extensions/XIproto.h>
4535c4bbdfSmrg#include "XIstubs.h"            /* even though we don't use stubs.  cute, no? */
4605b261ecSmrg#include "exevents.h"
4705b261ecSmrg#include "extinit.h"
4805b261ecSmrg#include "exglobals.h"
496747b715Smrg#include "eventstr.h"
506747b715Smrg#include "xserver-properties.h"
519ace9065Smrg#include "inpututils.h"
5235c4bbdfSmrg#include "optionstr.h"
5305b261ecSmrg
541b5d61b8Smrg#if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
551b5d61b8Smrg#include <hotplug.h>
561b5d61b8Smrg#endif
571b5d61b8Smrg
5805b261ecSmrg#define AtomFromName(x) MakeAtom(x, strlen(x), 1)
5905b261ecSmrg
6005b261ecSmrgstruct KdConfigDevice {
6105b261ecSmrg    char *line;
6205b261ecSmrg    struct KdConfigDevice *next;
6305b261ecSmrg};
6405b261ecSmrg
6505b261ecSmrg/* kdKeyboards and kdPointers hold all the real devices. */
6635c4bbdfSmrgstatic KdKeyboardInfo *kdKeyboards = NULL;
6735c4bbdfSmrgstatic KdPointerInfo *kdPointers = NULL;
6835c4bbdfSmrgstatic struct KdConfigDevice *kdConfigKeyboards = NULL;
6935c4bbdfSmrgstatic struct KdConfigDevice *kdConfigPointers = NULL;
7005b261ecSmrg
7105b261ecSmrgstatic KdKeyboardDriver *kdKeyboardDrivers = NULL;
7235c4bbdfSmrgstatic KdPointerDriver *kdPointerDrivers = NULL;
7305b261ecSmrg
7435c4bbdfSmrgstatic Bool kdInputEnabled;
7535c4bbdfSmrgstatic Bool kdOffScreen;
7635c4bbdfSmrgstatic unsigned long kdOffScreenTime;
7705b261ecSmrg
7835c4bbdfSmrgstatic KdPointerMatrix kdPointerMatrix = {
7935c4bbdfSmrg    {{1, 0, 0},
8035c4bbdfSmrg     {0, 1, 0}}
8105b261ecSmrg};
8205b261ecSmrg
8335c4bbdfSmrgextern Bool kdRawPointerCoordinates;
8405b261ecSmrg
851b5d61b8Smrgextern const char *kdGlobalXkbRules;
861b5d61b8Smrgextern const char *kdGlobalXkbModel;
871b5d61b8Smrgextern const char *kdGlobalXkbLayout;
881b5d61b8Smrgextern const char *kdGlobalXkbVariant;
891b5d61b8Smrgextern const char *kdGlobalXkbOptions;
9005b261ecSmrg
9105b261ecSmrg#ifdef FNONBLOCK
9205b261ecSmrg#define NOBLOCK FNONBLOCK
9305b261ecSmrg#else
9405b261ecSmrg#define NOBLOCK FNDELAY
9505b261ecSmrg#endif
9605b261ecSmrg
971b5d61b8Smrgstatic void
9835c4bbdfSmrgKdResetInputMachine(void)
9905b261ecSmrg{
10005b261ecSmrg    KdPointerInfo *pi;
10105b261ecSmrg
10205b261ecSmrg    for (pi = kdPointers; pi; pi = pi->next) {
10305b261ecSmrg        pi->mouseState = start;
10405b261ecSmrg        pi->eventHeld = FALSE;
10505b261ecSmrg    }
10605b261ecSmrg}
10705b261ecSmrg
10805b261ecSmrgvoid
10935c4bbdfSmrgKdDisableInput(void)
11005b261ecSmrg{
11105b261ecSmrg    KdKeyboardInfo *ki;
11205b261ecSmrg    KdPointerInfo *pi;
11305b261ecSmrg
1141b5d61b8Smrg    input_lock();
11505b261ecSmrg
11605b261ecSmrg    for (ki = kdKeyboards; ki; ki = ki->next) {
11705b261ecSmrg        if (ki->driver && ki->driver->Disable)
11805b261ecSmrg            (*ki->driver->Disable) (ki);
11905b261ecSmrg    }
12005b261ecSmrg
12105b261ecSmrg    for (pi = kdPointers; pi; pi = pi->next) {
12205b261ecSmrg        if (pi->driver && pi->driver->Disable)
12305b261ecSmrg            (*pi->driver->Disable) (pi);
12405b261ecSmrg    }
12505b261ecSmrg
12605b261ecSmrg    kdInputEnabled = FALSE;
12705b261ecSmrg}
12805b261ecSmrg
12905b261ecSmrgvoid
13035c4bbdfSmrgKdEnableInput(void)
13105b261ecSmrg{
1326747b715Smrg    InternalEvent ev;
13305b261ecSmrg    KdKeyboardInfo *ki;
13405b261ecSmrg    KdPointerInfo *pi;
1356747b715Smrg
13605b261ecSmrg    kdInputEnabled = TRUE;
13705b261ecSmrg
13835c4bbdfSmrg    ev.any.time = GetTimeInMillis();
13935c4bbdfSmrg
14005b261ecSmrg    for (ki = kdKeyboards; ki; ki = ki->next) {
14105b261ecSmrg        if (ki->driver && ki->driver->Enable)
14205b261ecSmrg            (*ki->driver->Enable) (ki);
14335c4bbdfSmrg        /* reset screen saver */
14435c4bbdfSmrg        NoticeEventTime (&ev, ki->dixdev);
14505b261ecSmrg    }
14605b261ecSmrg
14705b261ecSmrg    for (pi = kdPointers; pi; pi = pi->next) {
14805b261ecSmrg        if (pi->driver && pi->driver->Enable)
14905b261ecSmrg            (*pi->driver->Enable) (pi);
15035c4bbdfSmrg        /* reset screen saver */
15135c4bbdfSmrg        NoticeEventTime (&ev, pi->dixdev);
15205b261ecSmrg    }
15305b261ecSmrg
1541b5d61b8Smrg    input_unlock();
15505b261ecSmrg}
15605b261ecSmrg
15705b261ecSmrgstatic KdKeyboardDriver *
15835c4bbdfSmrgKdFindKeyboardDriver(const char *name)
15905b261ecSmrg{
16005b261ecSmrg    KdKeyboardDriver *ret;
16105b261ecSmrg
16205b261ecSmrg    /* ask a stupid question ... */
16305b261ecSmrg    if (!name)
16405b261ecSmrg        return NULL;
1656747b715Smrg
16605b261ecSmrg    for (ret = kdKeyboardDrivers; ret; ret = ret->next) {
16705b261ecSmrg        if (strcmp(ret->name, name) == 0)
16805b261ecSmrg            return ret;
16905b261ecSmrg    }
17005b261ecSmrg
17105b261ecSmrg    return NULL;
17205b261ecSmrg}
17305b261ecSmrg
17405b261ecSmrgstatic KdPointerDriver *
17535c4bbdfSmrgKdFindPointerDriver(const char *name)
17605b261ecSmrg{
17705b261ecSmrg    KdPointerDriver *ret;
17805b261ecSmrg
17905b261ecSmrg    /* ask a stupid question ... */
18005b261ecSmrg    if (!name)
18105b261ecSmrg        return NULL;
18205b261ecSmrg
18305b261ecSmrg    for (ret = kdPointerDrivers; ret; ret = ret->next) {
18405b261ecSmrg        if (strcmp(ret->name, name) == 0)
18505b261ecSmrg            return ret;
18605b261ecSmrg    }
18705b261ecSmrg
18805b261ecSmrg    return NULL;
18905b261ecSmrg}
19005b261ecSmrg
19105b261ecSmrgstatic int
19205b261ecSmrgKdPointerProc(DeviceIntPtr pDevice, int onoff)
19305b261ecSmrg{
19435c4bbdfSmrg    DevicePtr pDev = (DevicePtr) pDevice;
19535c4bbdfSmrg    KdPointerInfo *pi;
19635c4bbdfSmrg    Atom xiclass;
19735c4bbdfSmrg    Atom *btn_labels;
19835c4bbdfSmrg    Atom *axes_labels;
19905b261ecSmrg
20005b261ecSmrg    if (!pDev)
20135c4bbdfSmrg        return BadImplementation;
20205b261ecSmrg
20305b261ecSmrg    for (pi = kdPointers; pi; pi = pi->next) {
20405b261ecSmrg        if (pi->dixdev && pi->dixdev->id == pDevice->id)
20505b261ecSmrg            break;
20605b261ecSmrg    }
20705b261ecSmrg
20805b261ecSmrg    if (!pi || !pi->dixdev || pi->dixdev->id != pDevice->id) {
20905b261ecSmrg        ErrorF("[KdPointerProc] Failed to find pointer for device %d!\n",
21005b261ecSmrg               pDevice->id);
21105b261ecSmrg        return BadImplementation;
21205b261ecSmrg    }
21305b261ecSmrg
21435c4bbdfSmrg    switch (onoff) {
21505b261ecSmrg    case DEVICE_INIT:
21605b261ecSmrg#ifdef DEBUG
21705b261ecSmrg        ErrorF("initialising pointer %s ...\n", pi->name);
21805b261ecSmrg#endif
21905b261ecSmrg        if (!pi->driver) {
22005b261ecSmrg            if (!pi->driverPrivate) {
2211b5d61b8Smrg                ErrorF("no driver specified for pointer device \"%s\" (%s)\n",
2221b5d61b8Smrg                       pi->name ? pi->name : "(unnamed)", pi->path);
22305b261ecSmrg                return BadImplementation;
22405b261ecSmrg            }
22505b261ecSmrg
22605b261ecSmrg            pi->driver = KdFindPointerDriver(pi->driverPrivate);
22705b261ecSmrg            if (!pi->driver) {
22805b261ecSmrg                ErrorF("Couldn't find pointer driver %s\n",
22905b261ecSmrg                       pi->driverPrivate ? (char *) pi->driverPrivate :
23005b261ecSmrg                       "(unnamed)");
23105b261ecSmrg                return !Success;
23205b261ecSmrg            }
2336747b715Smrg            free(pi->driverPrivate);
23405b261ecSmrg            pi->driverPrivate = NULL;
23505b261ecSmrg        }
23605b261ecSmrg
23705b261ecSmrg        if (!pi->driver->Init) {
23805b261ecSmrg            ErrorF("no init function\n");
23905b261ecSmrg            return BadImplementation;
24005b261ecSmrg        }
24105b261ecSmrg
24205b261ecSmrg        if ((*pi->driver->Init) (pi) != Success) {
24305b261ecSmrg            return !Success;
24405b261ecSmrg        }
24505b261ecSmrg
24635c4bbdfSmrg        btn_labels = calloc(pi->nButtons, sizeof(Atom));
24735c4bbdfSmrg        if (!btn_labels)
24835c4bbdfSmrg            return BadAlloc;
24935c4bbdfSmrg        axes_labels = calloc(pi->nAxes, sizeof(Atom));
25035c4bbdfSmrg        if (!axes_labels) {
25135c4bbdfSmrg            free(btn_labels);
25235c4bbdfSmrg            return BadAlloc;
25335c4bbdfSmrg        }
25435c4bbdfSmrg
25535c4bbdfSmrg        switch (pi->nAxes) {
25635c4bbdfSmrg        default:
25735c4bbdfSmrg        case 7:
25835c4bbdfSmrg            btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
25935c4bbdfSmrg        case 6:
26035c4bbdfSmrg            btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
26135c4bbdfSmrg        case 5:
26235c4bbdfSmrg            btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
26335c4bbdfSmrg        case 4:
26435c4bbdfSmrg            btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
26535c4bbdfSmrg        case 3:
26635c4bbdfSmrg            btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
26735c4bbdfSmrg        case 2:
26835c4bbdfSmrg            btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
26935c4bbdfSmrg        case 1:
27035c4bbdfSmrg            btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
27135c4bbdfSmrg        case 0:
27235c4bbdfSmrg            break;
27335c4bbdfSmrg        }
27435c4bbdfSmrg
27535c4bbdfSmrg        if (pi->nAxes >= 2) {
27635c4bbdfSmrg            axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
27735c4bbdfSmrg            axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
27835c4bbdfSmrg        }
27935c4bbdfSmrg
28035c4bbdfSmrg        InitPointerDeviceStruct(pDev, pi->map, pi->nButtons, btn_labels,
28135c4bbdfSmrg                                (PtrCtrlProcPtr) NoopDDA,
28235c4bbdfSmrg                                GetMotionHistorySize(), pi->nAxes, axes_labels);
2836747b715Smrg
2846747b715Smrg        free(btn_labels);
2856747b715Smrg        free(axes_labels);
28605b261ecSmrg
28705b261ecSmrg        if (pi->inputClass == KD_TOUCHSCREEN) {
28805b261ecSmrg            xiclass = AtomFromName(XI_TOUCHSCREEN);
28905b261ecSmrg        }
29005b261ecSmrg        else {
29105b261ecSmrg            xiclass = AtomFromName(XI_MOUSE);
29205b261ecSmrg        }
29305b261ecSmrg
29405b261ecSmrg        AssignTypeAndName(pi->dixdev, xiclass,
29505b261ecSmrg                          pi->name ? pi->name : "Generic KDrive Pointer");
29605b261ecSmrg
29735c4bbdfSmrg        return Success;
2986747b715Smrg
29905b261ecSmrg    case DEVICE_ON:
30005b261ecSmrg        if (pDev->on == TRUE)
30105b261ecSmrg            return Success;
3026747b715Smrg
30305b261ecSmrg        if (!pi->driver->Enable) {
30405b261ecSmrg            ErrorF("no enable function\n");
30505b261ecSmrg            return BadImplementation;
30605b261ecSmrg        }
30705b261ecSmrg
30805b261ecSmrg        if ((*pi->driver->Enable) (pi) == Success) {
30905b261ecSmrg            pDev->on = TRUE;
31005b261ecSmrg            return Success;
31105b261ecSmrg        }
31205b261ecSmrg        else {
31305b261ecSmrg            return BadImplementation;
31405b261ecSmrg        }
31505b261ecSmrg
31635c4bbdfSmrg        return Success;
31705b261ecSmrg
31805b261ecSmrg    case DEVICE_OFF:
31905b261ecSmrg        if (pDev->on == FALSE) {
32005b261ecSmrg            return Success;
32105b261ecSmrg        }
32205b261ecSmrg
32305b261ecSmrg        if (!pi->driver->Disable) {
32405b261ecSmrg            return BadImplementation;
32505b261ecSmrg        }
32605b261ecSmrg        else {
32705b261ecSmrg            (*pi->driver->Disable) (pi);
32805b261ecSmrg            pDev->on = FALSE;
32905b261ecSmrg            return Success;
33005b261ecSmrg        }
33105b261ecSmrg
33205b261ecSmrg        return Success;
33305b261ecSmrg
33405b261ecSmrg    case DEVICE_CLOSE:
33535c4bbdfSmrg        if (pDev->on) {
33605b261ecSmrg            if (!pi->driver->Disable) {
33705b261ecSmrg                return BadImplementation;
33805b261ecSmrg            }
33905b261ecSmrg            (*pi->driver->Disable) (pi);
34005b261ecSmrg            pDev->on = FALSE;
34105b261ecSmrg        }
34205b261ecSmrg
34305b261ecSmrg        if (!pi->driver->Fini)
34405b261ecSmrg            return BadImplementation;
34505b261ecSmrg
34605b261ecSmrg        (*pi->driver->Fini) (pi);
34705b261ecSmrg
34805b261ecSmrg        KdRemovePointer(pi);
3496747b715Smrg
35005b261ecSmrg        return Success;
35105b261ecSmrg    }
35205b261ecSmrg
35305b261ecSmrg    /* NOTREACHED */
35405b261ecSmrg    return BadImplementation;
35505b261ecSmrg}
35605b261ecSmrg
3571b5d61b8Smrgstatic void
3581b5d61b8SmrgKdRingBell(KdKeyboardInfo * ki, int volume, int pitch, int duration)
3591b5d61b8Smrg{
3601b5d61b8Smrg    if (!ki || !ki->driver || !ki->driver->Bell)
3611b5d61b8Smrg        return;
3621b5d61b8Smrg
3631b5d61b8Smrg    if (kdInputEnabled)
3641b5d61b8Smrg        (*ki->driver->Bell) (ki, volume, pitch, duration);
3651b5d61b8Smrg}
3661b5d61b8Smrg
36705b261ecSmrgstatic void
36835c4bbdfSmrgKdBell(int volume, DeviceIntPtr pDev, void *arg, int something)
36905b261ecSmrg{
37005b261ecSmrg    KeybdCtrl *ctrl = arg;
37105b261ecSmrg    KdKeyboardInfo *ki = NULL;
3726747b715Smrg
37305b261ecSmrg    for (ki = kdKeyboards; ki; ki = ki->next) {
37405b261ecSmrg        if (ki->dixdev && ki->dixdev->id == pDev->id)
37505b261ecSmrg            break;
37605b261ecSmrg    }
37705b261ecSmrg
37805b261ecSmrg    if (!ki || !ki->dixdev || ki->dixdev->id != pDev->id || !ki->driver)
37905b261ecSmrg        return;
3806747b715Smrg
38105b261ecSmrg    KdRingBell(ki, volume, ctrl->bell_pitch, ctrl->bell_duration);
38205b261ecSmrg}
38305b261ecSmrg
38405b261ecSmrgvoid
38505b261ecSmrgDDXRingBell(int volume, int pitch, int duration)
38605b261ecSmrg{
38705b261ecSmrg    KdKeyboardInfo *ki = NULL;
38805b261ecSmrg
3891b5d61b8Smrg    for (ki = kdKeyboards; ki; ki = ki->next) {
3901b5d61b8Smrg        if (ki->dixdev->coreEvents)
3911b5d61b8Smrg            KdRingBell(ki, volume, pitch, duration);
39205b261ecSmrg    }
39305b261ecSmrg}
39405b261ecSmrg
39505b261ecSmrgstatic void
39635c4bbdfSmrgKdSetLeds(KdKeyboardInfo * ki, int leds)
39705b261ecSmrg{
39805b261ecSmrg    if (!ki || !ki->driver)
39905b261ecSmrg        return;
40005b261ecSmrg
40105b261ecSmrg    if (kdInputEnabled) {
40205b261ecSmrg        if (ki->driver->Leds)
40305b261ecSmrg            (*ki->driver->Leds) (ki, leds);
40405b261ecSmrg    }
40505b261ecSmrg}
40605b261ecSmrg
4071b5d61b8Smrgstatic void
40835c4bbdfSmrgKdSetLed(KdKeyboardInfo * ki, int led, Bool on)
40905b261ecSmrg{
41005b261ecSmrg    if (!ki || !ki->dixdev || !ki->dixdev->kbdfeed)
41105b261ecSmrg        return;
41205b261ecSmrg
41335c4bbdfSmrg    NoteLedState(ki->dixdev, led, on);
41435c4bbdfSmrg    KdSetLeds(ki, ki->dixdev->kbdfeed->ctrl.leds);
41505b261ecSmrg}
41605b261ecSmrg
41705b261ecSmrgvoid
41835c4bbdfSmrgKdSetPointerMatrix(KdPointerMatrix * matrix)
41905b261ecSmrg{
42005b261ecSmrg    kdPointerMatrix = *matrix;
42105b261ecSmrg}
42205b261ecSmrg
42305b261ecSmrgvoid
42435c4bbdfSmrgKdComputePointerMatrix(KdPointerMatrix * m, Rotation randr, int width,
42535c4bbdfSmrg                       int height)
42605b261ecSmrg{
42735c4bbdfSmrg    int x_dir = 1, y_dir = 1;
42835c4bbdfSmrg    int i, j;
42935c4bbdfSmrg    int size[2];
43005b261ecSmrg
43135c4bbdfSmrg    size[0] = width;
43235c4bbdfSmrg    size[1] = height;
43305b261ecSmrg    if (randr & RR_Reflect_X)
43435c4bbdfSmrg        x_dir = -1;
43505b261ecSmrg    if (randr & RR_Reflect_Y)
43635c4bbdfSmrg        y_dir = -1;
43705b261ecSmrg    switch (randr & (RR_Rotate_All)) {
43805b261ecSmrg    case RR_Rotate_0:
43935c4bbdfSmrg        m->matrix[0][0] = x_dir;
44035c4bbdfSmrg        m->matrix[0][1] = 0;
44135c4bbdfSmrg        m->matrix[1][0] = 0;
44235c4bbdfSmrg        m->matrix[1][1] = y_dir;
44335c4bbdfSmrg        break;
44405b261ecSmrg    case RR_Rotate_90:
44535c4bbdfSmrg        m->matrix[0][0] = 0;
44635c4bbdfSmrg        m->matrix[0][1] = -x_dir;
44735c4bbdfSmrg        m->matrix[1][0] = y_dir;
44835c4bbdfSmrg        m->matrix[1][1] = 0;
44935c4bbdfSmrg        break;
45005b261ecSmrg    case RR_Rotate_180:
45135c4bbdfSmrg        m->matrix[0][0] = -x_dir;
45235c4bbdfSmrg        m->matrix[0][1] = 0;
45335c4bbdfSmrg        m->matrix[1][0] = 0;
45435c4bbdfSmrg        m->matrix[1][1] = -y_dir;
45535c4bbdfSmrg        break;
45605b261ecSmrg    case RR_Rotate_270:
45735c4bbdfSmrg        m->matrix[0][0] = 0;
45835c4bbdfSmrg        m->matrix[0][1] = x_dir;
45935c4bbdfSmrg        m->matrix[1][0] = -y_dir;
46035c4bbdfSmrg        m->matrix[1][1] = 0;
46135c4bbdfSmrg        break;
46205b261ecSmrg    }
46335c4bbdfSmrg    for (i = 0; i < 2; i++) {
46435c4bbdfSmrg        m->matrix[i][2] = 0;
46535c4bbdfSmrg        for (j = 0; j < 2; j++)
46635c4bbdfSmrg            if (m->matrix[i][j] < 0)
46735c4bbdfSmrg                m->matrix[i][2] = size[j] - 1;
46805b261ecSmrg    }
46905b261ecSmrg}
47005b261ecSmrg
47105b261ecSmrgstatic void
47235c4bbdfSmrgKdKbdCtrl(DeviceIntPtr pDevice, KeybdCtrl * ctrl)
47305b261ecSmrg{
47405b261ecSmrg    KdKeyboardInfo *ki;
47505b261ecSmrg
47605b261ecSmrg    for (ki = kdKeyboards; ki; ki = ki->next) {
47705b261ecSmrg        if (ki->dixdev && ki->dixdev->id == pDevice->id)
47805b261ecSmrg            break;
47905b261ecSmrg    }
48005b261ecSmrg
48105b261ecSmrg    if (!ki || !ki->dixdev || ki->dixdev->id != pDevice->id || !ki->driver)
48205b261ecSmrg        return;
48305b261ecSmrg
48405b261ecSmrg    KdSetLeds(ki, ctrl->leds);
48505b261ecSmrg    ki->bellPitch = ctrl->bell_pitch;
4866747b715Smrg    ki->bellDuration = ctrl->bell_duration;
48705b261ecSmrg}
48805b261ecSmrg
48905b261ecSmrgstatic int
49005b261ecSmrgKdKeyboardProc(DeviceIntPtr pDevice, int onoff)
49105b261ecSmrg{
49235c4bbdfSmrg    Bool ret;
49335c4bbdfSmrg    DevicePtr pDev = (DevicePtr) pDevice;
49405b261ecSmrg    KdKeyboardInfo *ki;
49505b261ecSmrg    Atom xiclass;
4966747b715Smrg    XkbRMLVOSet rmlvo;
49705b261ecSmrg
49805b261ecSmrg    if (!pDev)
49935c4bbdfSmrg        return BadImplementation;
50005b261ecSmrg
50105b261ecSmrg    for (ki = kdKeyboards; ki; ki = ki->next) {
50205b261ecSmrg        if (ki->dixdev && ki->dixdev->id == pDevice->id)
50305b261ecSmrg            break;
50405b261ecSmrg    }
50505b261ecSmrg
50605b261ecSmrg    if (!ki || !ki->dixdev || ki->dixdev->id != pDevice->id) {
50705b261ecSmrg        return BadImplementation;
50805b261ecSmrg    }
50905b261ecSmrg
51035c4bbdfSmrg    switch (onoff) {
51105b261ecSmrg    case DEVICE_INIT:
51205b261ecSmrg#ifdef DEBUG
51305b261ecSmrg        ErrorF("initialising keyboard %s\n", ki->name);
51405b261ecSmrg#endif
51505b261ecSmrg        if (!ki->driver) {
51605b261ecSmrg            if (!ki->driverPrivate) {
5171b5d61b8Smrg                ErrorF("no driver specified for keyboard device \"%s\" (%s)\n",
5181b5d61b8Smrg                       ki->name ? ki->name : "(unnamed)", ki->path);
51905b261ecSmrg                return BadImplementation;
52005b261ecSmrg            }
52105b261ecSmrg
52205b261ecSmrg            ki->driver = KdFindKeyboardDriver(ki->driverPrivate);
52305b261ecSmrg            if (!ki->driver) {
52405b261ecSmrg                ErrorF("Couldn't find keyboard driver %s\n",
52505b261ecSmrg                       ki->driverPrivate ? (char *) ki->driverPrivate :
52605b261ecSmrg                       "(unnamed)");
52705b261ecSmrg                return !Success;
52805b261ecSmrg            }
5296747b715Smrg            free(ki->driverPrivate);
53005b261ecSmrg            ki->driverPrivate = NULL;
53105b261ecSmrg        }
53205b261ecSmrg
53305b261ecSmrg        if (!ki->driver->Init) {
53405b261ecSmrg            ErrorF("Keyboard %s: no init function\n", ki->name);
53505b261ecSmrg            return BadImplementation;
53605b261ecSmrg        }
53705b261ecSmrg
5386747b715Smrg        memset(&rmlvo, 0, sizeof(rmlvo));
5396747b715Smrg        rmlvo.rules = ki->xkbRules;
5406747b715Smrg        rmlvo.model = ki->xkbModel;
5416747b715Smrg        rmlvo.layout = ki->xkbLayout;
5426747b715Smrg        rmlvo.variant = ki->xkbVariant;
5436747b715Smrg        rmlvo.options = ki->xkbOptions;
54435c4bbdfSmrg        ret = InitKeyboardDeviceStruct(pDevice, &rmlvo, KdBell, KdKbdCtrl);
54535c4bbdfSmrg        if (!ret) {
54605b261ecSmrg            ErrorF("Couldn't initialise keyboard %s\n", ki->name);
54735c4bbdfSmrg            return BadImplementation;
54805b261ecSmrg        }
54905b261ecSmrg
5501b5d61b8Smrg        if ((*ki->driver->Init) (ki) != Success) {
5511b5d61b8Smrg            return !Success;
5521b5d61b8Smrg        }
5531b5d61b8Smrg
55405b261ecSmrg        xiclass = AtomFromName(XI_KEYBOARD);
55505b261ecSmrg        AssignTypeAndName(pDevice, xiclass,
55605b261ecSmrg                          ki->name ? ki->name : "Generic KDrive Keyboard");
55705b261ecSmrg
55805b261ecSmrg        KdResetInputMachine();
55905b261ecSmrg
56005b261ecSmrg        return Success;
56105b261ecSmrg
56205b261ecSmrg    case DEVICE_ON:
56305b261ecSmrg        if (pDev->on == TRUE)
56405b261ecSmrg            return Success;
56505b261ecSmrg
56605b261ecSmrg        if (!ki->driver->Enable)
56705b261ecSmrg            return BadImplementation;
56805b261ecSmrg
56905b261ecSmrg        if ((*ki->driver->Enable) (ki) != Success) {
57005b261ecSmrg            return BadMatch;
57105b261ecSmrg        }
57205b261ecSmrg
57305b261ecSmrg        pDev->on = TRUE;
57405b261ecSmrg        return Success;
57505b261ecSmrg
57605b261ecSmrg    case DEVICE_OFF:
57705b261ecSmrg        if (pDev->on == FALSE)
57805b261ecSmrg            return Success;
57905b261ecSmrg
58005b261ecSmrg        if (!ki->driver->Disable)
58105b261ecSmrg            return BadImplementation;
58205b261ecSmrg
58305b261ecSmrg        (*ki->driver->Disable) (ki);
58405b261ecSmrg        pDev->on = FALSE;
58505b261ecSmrg
58605b261ecSmrg        return Success;
5876747b715Smrg
58805b261ecSmrg        break;
58905b261ecSmrg
59005b261ecSmrg    case DEVICE_CLOSE:
59135c4bbdfSmrg        if (pDev->on) {
59205b261ecSmrg            if (!ki->driver->Disable)
59305b261ecSmrg                return BadImplementation;
59405b261ecSmrg
59505b261ecSmrg            (*ki->driver->Disable) (ki);
59605b261ecSmrg            pDev->on = FALSE;
59735c4bbdfSmrg        }
59805b261ecSmrg
59905b261ecSmrg        if (!ki->driver->Fini)
60005b261ecSmrg            return BadImplementation;
60105b261ecSmrg
60205b261ecSmrg        (*ki->driver->Fini) (ki);
60305b261ecSmrg
60405b261ecSmrg        KdRemoveKeyboard(ki);
60505b261ecSmrg
60605b261ecSmrg        return Success;
60705b261ecSmrg    }
60805b261ecSmrg
60905b261ecSmrg    /* NOTREACHED */
61005b261ecSmrg    return BadImplementation;
61105b261ecSmrg}
61205b261ecSmrg
61305b261ecSmrgvoid
61435c4bbdfSmrgKdAddPointerDriver(KdPointerDriver * driver)
61505b261ecSmrg{
61605b261ecSmrg    KdPointerDriver **prev;
61705b261ecSmrg
61805b261ecSmrg    if (!driver)
61905b261ecSmrg        return;
62005b261ecSmrg
62105b261ecSmrg    for (prev = &kdPointerDrivers; *prev; prev = &(*prev)->next) {
62205b261ecSmrg        if (*prev == driver)
62305b261ecSmrg            return;
62405b261ecSmrg    }
62505b261ecSmrg    *prev = driver;
62605b261ecSmrg}
62705b261ecSmrg
62805b261ecSmrgvoid
62935c4bbdfSmrgKdRemovePointerDriver(KdPointerDriver * driver)
63005b261ecSmrg{
63105b261ecSmrg    KdPointerDriver *tmp;
63205b261ecSmrg
63305b261ecSmrg    if (!driver)
63405b261ecSmrg        return;
63505b261ecSmrg
63605b261ecSmrg    /* FIXME remove all pointers using this driver */
63705b261ecSmrg    for (tmp = kdPointerDrivers; tmp; tmp = tmp->next) {
63805b261ecSmrg        if (tmp->next == driver)
63905b261ecSmrg            tmp->next = driver->next;
64005b261ecSmrg    }
64105b261ecSmrg    if (tmp == driver)
64205b261ecSmrg        tmp = NULL;
64305b261ecSmrg}
64405b261ecSmrg
64505b261ecSmrgvoid
64635c4bbdfSmrgKdAddKeyboardDriver(KdKeyboardDriver * driver)
64705b261ecSmrg{
64805b261ecSmrg    KdKeyboardDriver **prev;
64905b261ecSmrg
65005b261ecSmrg    if (!driver)
65105b261ecSmrg        return;
65205b261ecSmrg
65305b261ecSmrg    for (prev = &kdKeyboardDrivers; *prev; prev = &(*prev)->next) {
65405b261ecSmrg        if (*prev == driver)
65505b261ecSmrg            return;
65605b261ecSmrg    }
65705b261ecSmrg    *prev = driver;
65805b261ecSmrg}
65905b261ecSmrg
66005b261ecSmrgvoid
66135c4bbdfSmrgKdRemoveKeyboardDriver(KdKeyboardDriver * driver)
66205b261ecSmrg{
66305b261ecSmrg    KdKeyboardDriver *tmp;
66405b261ecSmrg
66505b261ecSmrg    if (!driver)
66605b261ecSmrg        return;
66705b261ecSmrg
66805b261ecSmrg    /* FIXME remove all keyboards using this driver */
66905b261ecSmrg    for (tmp = kdKeyboardDrivers; tmp; tmp = tmp->next) {
67005b261ecSmrg        if (tmp->next == driver)
67105b261ecSmrg            tmp->next = driver->next;
67205b261ecSmrg    }
67305b261ecSmrg    if (tmp == driver)
67405b261ecSmrg        tmp = NULL;
67505b261ecSmrg}
67605b261ecSmrg
67705b261ecSmrgKdKeyboardInfo *
67835c4bbdfSmrgKdNewKeyboard(void)
67905b261ecSmrg{
6806747b715Smrg    KdKeyboardInfo *ki = calloc(sizeof(KdKeyboardInfo), 1);
68135c4bbdfSmrg
68205b261ecSmrg    if (!ki)
68305b261ecSmrg        return NULL;
68405b261ecSmrg
68505b261ecSmrg    ki->minScanCode = 0;
68605b261ecSmrg    ki->maxScanCode = 0;
68705b261ecSmrg    ki->leds = 0;
68805b261ecSmrg    ki->bellPitch = 1000;
68905b261ecSmrg    ki->bellDuration = 200;
69005b261ecSmrg    ki->next = NULL;
69105b261ecSmrg    ki->options = NULL;
6921b5d61b8Smrg    ki->name = strdup("Generic Keyboard");
6931b5d61b8Smrg    ki->path = NULL;
6941b5d61b8Smrg    ki->xkbRules = strdup(kdGlobalXkbRules ? kdGlobalXkbRules : XKB_DFLT_RULES);
6951b5d61b8Smrg    ki->xkbModel = strdup(kdGlobalXkbModel ? kdGlobalXkbModel : XKB_DFLT_MODEL);
6961b5d61b8Smrg    ki->xkbLayout = strdup(kdGlobalXkbLayout ? kdGlobalXkbLayout : XKB_DFLT_LAYOUT);
6971b5d61b8Smrg    ki->xkbVariant = strdup(kdGlobalXkbVariant ? kdGlobalXkbVariant :XKB_DFLT_VARIANT);
6981b5d61b8Smrg    ki->xkbOptions = strdup(kdGlobalXkbOptions ? kdGlobalXkbOptions : XKB_DFLT_OPTIONS);
69905b261ecSmrg
70005b261ecSmrg    return ki;
70105b261ecSmrg}
70205b261ecSmrg
70305b261ecSmrgint
70435c4bbdfSmrgKdAddConfigKeyboard(char *keyboard)
70505b261ecSmrg{
70605b261ecSmrg    struct KdConfigDevice **prev, *new;
70705b261ecSmrg
70805b261ecSmrg    if (!keyboard)
70905b261ecSmrg        return Success;
71005b261ecSmrg
7116747b715Smrg    new = (struct KdConfigDevice *) calloc(sizeof(struct KdConfigDevice), 1);
71205b261ecSmrg    if (!new)
71305b261ecSmrg        return BadAlloc;
71405b261ecSmrg
7156747b715Smrg    new->line = strdup(keyboard);
71605b261ecSmrg    new->next = NULL;
71705b261ecSmrg
71805b261ecSmrg    for (prev = &kdConfigKeyboards; *prev; prev = &(*prev)->next);
71905b261ecSmrg    *prev = new;
72005b261ecSmrg
72105b261ecSmrg    return Success;
72205b261ecSmrg}
72305b261ecSmrg
72405b261ecSmrgint
72535c4bbdfSmrgKdAddKeyboard(KdKeyboardInfo * ki)
72605b261ecSmrg{
72705b261ecSmrg    KdKeyboardInfo **prev;
72805b261ecSmrg
72905b261ecSmrg    if (!ki)
73005b261ecSmrg        return !Success;
7316747b715Smrg
7324642e01fSmrg    ki->dixdev = AddInputDevice(serverClient, KdKeyboardProc, TRUE);
73305b261ecSmrg    if (!ki->dixdev) {
73405b261ecSmrg        ErrorF("Couldn't register keyboard device %s\n",
73505b261ecSmrg               ki->name ? ki->name : "(unnamed)");
73605b261ecSmrg        return !Success;
73705b261ecSmrg    }
73805b261ecSmrg
73905b261ecSmrg#ifdef DEBUG
74005b261ecSmrg    ErrorF("added keyboard %s with dix id %d\n", ki->name, ki->dixdev->id);
74105b261ecSmrg#endif
74205b261ecSmrg
74305b261ecSmrg    for (prev = &kdKeyboards; *prev; prev = &(*prev)->next);
74405b261ecSmrg    *prev = ki;
74505b261ecSmrg
74605b261ecSmrg    return Success;
74705b261ecSmrg}
74805b261ecSmrg
74905b261ecSmrgvoid
75035c4bbdfSmrgKdRemoveKeyboard(KdKeyboardInfo * ki)
75105b261ecSmrg{
75205b261ecSmrg    KdKeyboardInfo **prev;
75305b261ecSmrg
75405b261ecSmrg    if (!ki)
75505b261ecSmrg        return;
75605b261ecSmrg
75705b261ecSmrg    for (prev = &kdKeyboards; *prev; prev = &(*prev)->next) {
75805b261ecSmrg        if (*prev == ki) {
75905b261ecSmrg            *prev = ki->next;
76005b261ecSmrg            break;
76105b261ecSmrg        }
76205b261ecSmrg    }
76305b261ecSmrg
76405b261ecSmrg    KdFreeKeyboard(ki);
76505b261ecSmrg}
76605b261ecSmrg
76705b261ecSmrgint
76835c4bbdfSmrgKdAddConfigPointer(char *pointer)
76905b261ecSmrg{
77005b261ecSmrg    struct KdConfigDevice **prev, *new;
77105b261ecSmrg
77205b261ecSmrg    if (!pointer)
77305b261ecSmrg        return Success;
77405b261ecSmrg
7756747b715Smrg    new = (struct KdConfigDevice *) calloc(sizeof(struct KdConfigDevice), 1);
77605b261ecSmrg    if (!new)
77705b261ecSmrg        return BadAlloc;
77805b261ecSmrg
7796747b715Smrg    new->line = strdup(pointer);
78005b261ecSmrg    new->next = NULL;
78105b261ecSmrg
78205b261ecSmrg    for (prev = &kdConfigPointers; *prev; prev = &(*prev)->next);
78305b261ecSmrg    *prev = new;
78405b261ecSmrg
78505b261ecSmrg    return Success;
78605b261ecSmrg}
78705b261ecSmrg
78805b261ecSmrgint
78935c4bbdfSmrgKdAddPointer(KdPointerInfo * pi)
79005b261ecSmrg{
79105b261ecSmrg    KdPointerInfo **prev;
79205b261ecSmrg
79305b261ecSmrg    if (!pi)
79405b261ecSmrg        return Success;
79505b261ecSmrg
79605b261ecSmrg    pi->mouseState = start;
79705b261ecSmrg    pi->eventHeld = FALSE;
79805b261ecSmrg
7994642e01fSmrg    pi->dixdev = AddInputDevice(serverClient, KdPointerProc, TRUE);
80005b261ecSmrg    if (!pi->dixdev) {
80105b261ecSmrg        ErrorF("Couldn't add pointer device %s\n",
80205b261ecSmrg               pi->name ? pi->name : "(unnamed)");
80305b261ecSmrg        return BadDevice;
80405b261ecSmrg    }
80505b261ecSmrg
80605b261ecSmrg    for (prev = &kdPointers; *prev; prev = &(*prev)->next);
80705b261ecSmrg    *prev = pi;
80805b261ecSmrg
80905b261ecSmrg    return Success;
81005b261ecSmrg}
81105b261ecSmrg
81205b261ecSmrgvoid
81335c4bbdfSmrgKdRemovePointer(KdPointerInfo * pi)
81405b261ecSmrg{
81505b261ecSmrg    KdPointerInfo **prev;
81605b261ecSmrg
81705b261ecSmrg    if (!pi)
81805b261ecSmrg        return;
81905b261ecSmrg
82005b261ecSmrg    for (prev = &kdPointers; *prev; prev = &(*prev)->next) {
82105b261ecSmrg        if (*prev == pi) {
82205b261ecSmrg            *prev = pi->next;
82305b261ecSmrg            break;
82405b261ecSmrg        }
82505b261ecSmrg    }
82605b261ecSmrg
82705b261ecSmrg    KdFreePointer(pi);
82805b261ecSmrg}
82905b261ecSmrg
8306747b715Smrg/*
83105b261ecSmrg * You can call your kdriver server with something like:
83205b261ecSmrg * $ ./hw/kdrive/yourserver/X :1 -mouse evdev,,device=/dev/input/event4 -keybd
8336747b715Smrg * evdev,,device=/dev/input/event1,xkbmodel=abnt2,xkblayout=br
83405b261ecSmrg */
8356747b715Smrgstatic Bool
83635c4bbdfSmrgKdGetOptions(InputOption **options, char *string)
83705b261ecSmrg{
83835c4bbdfSmrg    InputOption *newopt = NULL;
83935c4bbdfSmrg    char *key = NULL, *value = NULL;
84035c4bbdfSmrg    int tam_key = 0;
84105b261ecSmrg
84235c4bbdfSmrg    if (strchr(string, '=')) {
84305b261ecSmrg        tam_key = (strchr(string, '=') - string);
84435c4bbdfSmrg        key = strndup(string, tam_key);
84535c4bbdfSmrg        if (!key)
84635c4bbdfSmrg            goto out;
84735c4bbdfSmrg
84835c4bbdfSmrg        value = strdup(strchr(string, '=') + 1);
84935c4bbdfSmrg        if (!value)
85035c4bbdfSmrg            goto out;
85105b261ecSmrg    }
85235c4bbdfSmrg    else {
85335c4bbdfSmrg        key = strdup(string);
85435c4bbdfSmrg        value = NULL;
85505b261ecSmrg    }
85605b261ecSmrg
85735c4bbdfSmrg    newopt = input_option_new(*options, key, value);
85835c4bbdfSmrg    if (newopt)
85935c4bbdfSmrg        *options = newopt;
86035c4bbdfSmrg
86135c4bbdfSmrg out:
86235c4bbdfSmrg    free(key);
86335c4bbdfSmrg    free(value);
86435c4bbdfSmrg
86535c4bbdfSmrg    return (newopt != NULL);
86605b261ecSmrg}
86705b261ecSmrg
86805b261ecSmrgstatic void
86935c4bbdfSmrgKdParseKbdOptions(KdKeyboardInfo * ki)
87005b261ecSmrg{
87105b261ecSmrg    InputOption *option = NULL;
87205b261ecSmrg
87335c4bbdfSmrg    nt_list_for_each_entry(option, ki->options, list.next) {
87435c4bbdfSmrg        const char *key = input_option_get_key(option);
87535c4bbdfSmrg        const char *value = input_option_get_value(option);
87635c4bbdfSmrg
8771b5d61b8Smrg        if (
8781b5d61b8Smrg#if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
8791b5d61b8Smrg            strcasecmp(key, "xkb_rules") == 0 ||
8801b5d61b8Smrg#endif
8811b5d61b8Smrg            strcasecmp(key, "XkbRules") == 0)
88235c4bbdfSmrg            ki->xkbRules = strdup(value);
8831b5d61b8Smrg        else if (
8841b5d61b8Smrg#if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
8851b5d61b8Smrg                 strcasecmp(key, "xkb_model") == 0 ||
8861b5d61b8Smrg#endif
8871b5d61b8Smrg                 strcasecmp(key, "XkbModel") == 0)
88835c4bbdfSmrg            ki->xkbModel = strdup(value);
8891b5d61b8Smrg        else if (
8901b5d61b8Smrg#if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
8911b5d61b8Smrg                 strcasecmp(key, "xkb_layout") == 0 ||
8921b5d61b8Smrg#endif
8931b5d61b8Smrg                 strcasecmp(key, "XkbLayout") == 0)
89435c4bbdfSmrg            ki->xkbLayout = strdup(value);
8951b5d61b8Smrg        else if (
8961b5d61b8Smrg#if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
8971b5d61b8Smrg                 strcasecmp(key, "xkb_variant") == 0 ||
8981b5d61b8Smrg#endif
8991b5d61b8Smrg                 strcasecmp(key, "XkbVariant") == 0)
90035c4bbdfSmrg            ki->xkbVariant = strdup(value);
9011b5d61b8Smrg        else if (
9021b5d61b8Smrg#if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
9031b5d61b8Smrg                 strcasecmp(key, "xkb_options") == 0 ||
9041b5d61b8Smrg#endif
9051b5d61b8Smrg                 strcasecmp(key, "XkbOptions") == 0)
90635c4bbdfSmrg            ki->xkbOptions = strdup(value);
9071b5d61b8Smrg        else if (!strcasecmp(key, "device")) {
9081b5d61b8Smrg            if (ki->path != NULL)
9091b5d61b8Smrg                free(ki->path);
9101b5d61b8Smrg            ki->path = strdup(value);
9111b5d61b8Smrg        }
9121b5d61b8Smrg#if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
9131b5d61b8Smrg        else if (!strcasecmp(key, "path")) {
9141b5d61b8Smrg            if (ki->path != NULL)
9151b5d61b8Smrg                free(ki->path);
91635c4bbdfSmrg            ki->path = strdup(value);
9171b5d61b8Smrg        }
9181b5d61b8Smrg        else if (!strcasecmp(key, "name")) {
9191b5d61b8Smrg            free(ki->name);
9201b5d61b8Smrg            ki->name = strdup(value);
9211b5d61b8Smrg        }
9221b5d61b8Smrg#endif
9231b5d61b8Smrg        else if (!strcasecmp(key, "driver"))
9241b5d61b8Smrg            ki->driver = KdFindKeyboardDriver(value);
92505b261ecSmrg        else
92635c4bbdfSmrg            ErrorF("Kbd option key (%s) of value (%s) not assigned!\n",
92735c4bbdfSmrg                   key, value);
92805b261ecSmrg    }
92905b261ecSmrg}
93005b261ecSmrg
9311b5d61b8Smrgstatic KdKeyboardInfo *
93235c4bbdfSmrgKdParseKeyboard(const char *arg)
93305b261ecSmrg{
93435c4bbdfSmrg    char save[1024];
93535c4bbdfSmrg    char delim;
93635c4bbdfSmrg    InputOption *options = NULL;
93735c4bbdfSmrg    KdKeyboardInfo *ki = NULL;
93805b261ecSmrg
93905b261ecSmrg    ki = KdNewKeyboard();
94005b261ecSmrg    if (!ki)
94105b261ecSmrg        return NULL;
94205b261ecSmrg
94305b261ecSmrg    ki->name = strdup("Unknown KDrive Keyboard");
94405b261ecSmrg    ki->path = NULL;
94505b261ecSmrg    ki->driver = NULL;
94605b261ecSmrg    ki->driverPrivate = NULL;
94705b261ecSmrg    ki->next = NULL;
94805b261ecSmrg
94935c4bbdfSmrg    if (!arg) {
95005b261ecSmrg        ErrorF("keybd: no arg\n");
95135c4bbdfSmrg        KdFreeKeyboard(ki);
95205b261ecSmrg        return NULL;
95305b261ecSmrg    }
95405b261ecSmrg
95535c4bbdfSmrg    if (strlen(arg) >= sizeof(save)) {
95605b261ecSmrg        ErrorF("keybd: arg too long\n");
95735c4bbdfSmrg        KdFreeKeyboard(ki);
95805b261ecSmrg        return NULL;
95905b261ecSmrg    }
96005b261ecSmrg
96135c4bbdfSmrg    arg = KdParseFindNext(arg, ",", save, &delim);
96235c4bbdfSmrg    if (!save[0]) {
96305b261ecSmrg        ErrorF("keybd: failed on save[0]\n");
96435c4bbdfSmrg        KdFreeKeyboard(ki);
96505b261ecSmrg        return NULL;
96605b261ecSmrg    }
96705b261ecSmrg
96835c4bbdfSmrg    if (strcmp(save, "auto") == 0)
96905b261ecSmrg        ki->driverPrivate = NULL;
97005b261ecSmrg    else
9716747b715Smrg        ki->driverPrivate = strdup(save);
97205b261ecSmrg
97335c4bbdfSmrg    if (delim != ',') {
97405b261ecSmrg        return ki;
97505b261ecSmrg    }
97605b261ecSmrg
97735c4bbdfSmrg    arg = KdParseFindNext(arg, ",", save, &delim);
97805b261ecSmrg
97935c4bbdfSmrg    while (delim == ',') {
98035c4bbdfSmrg        arg = KdParseFindNext(arg, ",", save, &delim);
98105b261ecSmrg
98235c4bbdfSmrg        if (!KdGetOptions(&options, save)) {
98335c4bbdfSmrg            KdFreeKeyboard(ki);
98435c4bbdfSmrg            return NULL;
9856747b715Smrg        }
98605b261ecSmrg    }
98705b261ecSmrg
98835c4bbdfSmrg    if (options) {
98905b261ecSmrg        ki->options = options;
99005b261ecSmrg        KdParseKbdOptions(ki);
99105b261ecSmrg    }
99205b261ecSmrg
99305b261ecSmrg    return ki;
99405b261ecSmrg}
99505b261ecSmrg
99605b261ecSmrgstatic void
99735c4bbdfSmrgKdParsePointerOptions(KdPointerInfo * pi)
99805b261ecSmrg{
99905b261ecSmrg    InputOption *option = NULL;
100005b261ecSmrg
100135c4bbdfSmrg    nt_list_for_each_entry(option, pi->options, list.next) {
100235c4bbdfSmrg        const char *key = input_option_get_key(option);
100335c4bbdfSmrg        const char *value = input_option_get_value(option);
100435c4bbdfSmrg
10051b5d61b8Smrg        if (!strcasecmp(key, "emulatemiddle"))
100605b261ecSmrg            pi->emulateMiddleButton = TRUE;
10071b5d61b8Smrg        else if (!strcasecmp(key, "noemulatemiddle"))
100805b261ecSmrg            pi->emulateMiddleButton = FALSE;
10091b5d61b8Smrg        else if (!strcasecmp(key, "transformcoord"))
101005b261ecSmrg            pi->transformCoordinates = TRUE;
10111b5d61b8Smrg        else if (!strcasecmp(key, "rawcoord"))
101205b261ecSmrg            pi->transformCoordinates = FALSE;
10131b5d61b8Smrg        else if (!strcasecmp(key, "device")) {
10141b5d61b8Smrg            if (pi->path != NULL)
10151b5d61b8Smrg                free(pi->path);
101635c4bbdfSmrg            pi->path = strdup(value);
10171b5d61b8Smrg        }
10181b5d61b8Smrg#if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
10191b5d61b8Smrg        else if (!strcasecmp(key, "path")) {
10201b5d61b8Smrg            if (pi->path != NULL)
10211b5d61b8Smrg                free(pi->path);
10221b5d61b8Smrg            pi->path = strdup(value);
10231b5d61b8Smrg        }
10241b5d61b8Smrg        else if (!strcasecmp(key, "name")) {
10251b5d61b8Smrg            free(pi->name);
10261b5d61b8Smrg            pi->name = strdup(value);
10271b5d61b8Smrg        }
10281b5d61b8Smrg#endif
102935c4bbdfSmrg        else if (!strcasecmp(key, "protocol"))
103035c4bbdfSmrg            pi->protocol = strdup(value);
10311b5d61b8Smrg        else if (!strcasecmp(key, "driver"))
10321b5d61b8Smrg            pi->driver = KdFindPointerDriver(value);
103305b261ecSmrg        else
10346747b715Smrg            ErrorF("Pointer option key (%s) of value (%s) not assigned!\n",
103535c4bbdfSmrg                   key, value);
103605b261ecSmrg    }
103705b261ecSmrg}
103805b261ecSmrg
10391b5d61b8Smrgstatic KdPointerInfo *
104035c4bbdfSmrgKdParsePointer(const char *arg)
104105b261ecSmrg{
104235c4bbdfSmrg    char save[1024];
104335c4bbdfSmrg    char delim;
104435c4bbdfSmrg    KdPointerInfo *pi = NULL;
104535c4bbdfSmrg    InputOption *options = NULL;
104635c4bbdfSmrg    int i = 0;
104705b261ecSmrg
104805b261ecSmrg    pi = KdNewPointer();
104905b261ecSmrg    if (!pi)
105005b261ecSmrg        return NULL;
105105b261ecSmrg    pi->emulateMiddleButton = kdEmulateMiddleButton;
105205b261ecSmrg    pi->transformCoordinates = !kdRawPointerCoordinates;
10536747b715Smrg    pi->protocol = NULL;
105435c4bbdfSmrg    pi->nButtons = 5;           /* XXX should not be hardcoded */
105505b261ecSmrg    pi->inputClass = KD_MOUSE;
105605b261ecSmrg
105735c4bbdfSmrg    if (!arg) {
105805b261ecSmrg        ErrorF("mouse: no arg\n");
105935c4bbdfSmrg        KdFreePointer(pi);
106005b261ecSmrg        return NULL;
106105b261ecSmrg    }
106205b261ecSmrg
106335c4bbdfSmrg    if (strlen(arg) >= sizeof(save)) {
106405b261ecSmrg        ErrorF("mouse: arg too long\n");
106535c4bbdfSmrg        KdFreePointer(pi);
106605b261ecSmrg        return NULL;
106705b261ecSmrg    }
106835c4bbdfSmrg    arg = KdParseFindNext(arg, ",", save, &delim);
106935c4bbdfSmrg    if (!save[0]) {
107005b261ecSmrg        ErrorF("failed on save[0]\n");
107135c4bbdfSmrg        KdFreePointer(pi);
107205b261ecSmrg        return NULL;
107305b261ecSmrg    }
107405b261ecSmrg
107505b261ecSmrg    if (strcmp(save, "auto") == 0)
107605b261ecSmrg        pi->driverPrivate = NULL;
107705b261ecSmrg    else
10786747b715Smrg        pi->driverPrivate = strdup(save);
107905b261ecSmrg
108035c4bbdfSmrg    if (delim != ',') {
108105b261ecSmrg        return pi;
108205b261ecSmrg    }
108305b261ecSmrg
108435c4bbdfSmrg    arg = KdParseFindNext(arg, ",", save, &delim);
108505b261ecSmrg
108635c4bbdfSmrg    while (delim == ',') {
108735c4bbdfSmrg        arg = KdParseFindNext(arg, ",", save, &delim);
108835c4bbdfSmrg        if (save[0] == '{') {
108905b261ecSmrg            char *s = save + 1;
109035c4bbdfSmrg
109135c4bbdfSmrg            i = 0;
109235c4bbdfSmrg            while (*s && *s != '}') {
109305b261ecSmrg                if ('1' <= *s && *s <= '0' + pi->nButtons)
109405b261ecSmrg                    pi->map[i] = *s - '0';
109505b261ecSmrg                else
109635c4bbdfSmrg                    UseMsg();
109705b261ecSmrg                s++;
109835c4bbdfSmrg            }
109905b261ecSmrg        }
110035c4bbdfSmrg        else {
110135c4bbdfSmrg            if (!KdGetOptions(&options, save)) {
110205b261ecSmrg                KdFreePointer(pi);
110305b261ecSmrg                return NULL;
110405b261ecSmrg            }
110505b261ecSmrg        }
110605b261ecSmrg    }
110705b261ecSmrg
110835c4bbdfSmrg    if (options) {
110905b261ecSmrg        pi->options = options;
111005b261ecSmrg        KdParsePointerOptions(pi);
111105b261ecSmrg    }
111205b261ecSmrg
111305b261ecSmrg    return pi;
111405b261ecSmrg}
111505b261ecSmrg
111605b261ecSmrgvoid
111735c4bbdfSmrgKdInitInput(void)
111805b261ecSmrg{
111905b261ecSmrg    KdPointerInfo *pi;
112005b261ecSmrg    KdKeyboardInfo *ki;
112105b261ecSmrg    struct KdConfigDevice *dev;
112205b261ecSmrg
11231b5d61b8Smrg    if (kdConfigPointers || kdConfigKeyboards)
11241b5d61b8Smrg        InputThreadPreInit();
11251b5d61b8Smrg
112605b261ecSmrg    kdInputEnabled = TRUE;
112705b261ecSmrg
112805b261ecSmrg    for (dev = kdConfigPointers; dev; dev = dev->next) {
112905b261ecSmrg        pi = KdParsePointer(dev->line);
113005b261ecSmrg        if (!pi)
113105b261ecSmrg            ErrorF("Failed to parse pointer\n");
113205b261ecSmrg        if (KdAddPointer(pi) != Success)
113305b261ecSmrg            ErrorF("Failed to add pointer!\n");
113405b261ecSmrg    }
113505b261ecSmrg    for (dev = kdConfigKeyboards; dev; dev = dev->next) {
113605b261ecSmrg        ki = KdParseKeyboard(dev->line);
113705b261ecSmrg        if (!ki)
113805b261ecSmrg            ErrorF("Failed to parse keyboard\n");
113905b261ecSmrg        if (KdAddKeyboard(ki) != Success)
114005b261ecSmrg            ErrorF("Failed to add keyboard!\n");
114105b261ecSmrg    }
114205b261ecSmrg
114305b261ecSmrg    mieqInit();
11441b5d61b8Smrg
11451b5d61b8Smrg#if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
11461b5d61b8Smrg    if (SeatId) /* Enable input hot-plugging */
11471b5d61b8Smrg        config_init();
11481b5d61b8Smrg#endif
114905b261ecSmrg}
115005b261ecSmrg
115135c4bbdfSmrgvoid
115235c4bbdfSmrgKdCloseInput(void)
115335c4bbdfSmrg{
11541b5d61b8Smrg#if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
11551b5d61b8Smrg    if (SeatId) /* Input hot-plugging is enabled */
11561b5d61b8Smrg        config_fini();
11571b5d61b8Smrg#endif
11581b5d61b8Smrg
115935c4bbdfSmrg    mieqFini();
116035c4bbdfSmrg}
116135c4bbdfSmrg
116205b261ecSmrg/*
116305b261ecSmrg * Middle button emulation state machine
116405b261ecSmrg *
116505b261ecSmrg *  Possible transitions:
116605b261ecSmrg *	Button 1 press	    v1
116705b261ecSmrg *	Button 1 release    ^1
116805b261ecSmrg *	Button 2 press	    v2
116905b261ecSmrg *	Button 2 release    ^2
117005b261ecSmrg *	Button 3 press	    v3
117105b261ecSmrg *	Button 3 release    ^3
117205b261ecSmrg *	Button other press  vo
117305b261ecSmrg *	Button other release ^o
117405b261ecSmrg *	Mouse motion	    <>
117505b261ecSmrg *	Keyboard event	    k
117605b261ecSmrg *	timeout		    ...
117705b261ecSmrg *	outside box	    <->
117805b261ecSmrg *
117905b261ecSmrg *  States:
118005b261ecSmrg *	start
118105b261ecSmrg *	button_1_pend
118205b261ecSmrg *	button_1_down
118305b261ecSmrg *	button_2_down
118405b261ecSmrg *	button_3_pend
118505b261ecSmrg *	button_3_down
118605b261ecSmrg *	synthetic_2_down_13
118705b261ecSmrg *	synthetic_2_down_3
118805b261ecSmrg *	synthetic_2_down_1
118905b261ecSmrg *
119005b261ecSmrg *  Transition diagram
119105b261ecSmrg *
119205b261ecSmrg *  start
119305b261ecSmrg *	v1  -> (hold) (settimeout) button_1_pend
119405b261ecSmrg *	^1  -> (deliver) start
119505b261ecSmrg *	v2  -> (deliver) button_2_down
119605b261ecSmrg *	^2  -> (deliever) start
119705b261ecSmrg *	v3  -> (hold) (settimeout) button_3_pend
119805b261ecSmrg *	^3  -> (deliver) start
119905b261ecSmrg *	vo  -> (deliver) start
120005b261ecSmrg *	^o  -> (deliver) start
120105b261ecSmrg *	<>  -> (deliver) start
120205b261ecSmrg *	k   -> (deliver) start
120305b261ecSmrg *
120405b261ecSmrg *  button_1_pend	(button 1 is down, timeout pending)
120505b261ecSmrg *	^1  -> (release) (deliver) start
120605b261ecSmrg *	v2  -> (release) (deliver) button_1_down
120705b261ecSmrg *	^2  -> (release) (deliver) button_1_down
120805b261ecSmrg *	v3  -> (cleartimeout) (generate v2) synthetic_2_down_13
120905b261ecSmrg *	^3  -> (release) (deliver) button_1_down
121005b261ecSmrg *	vo  -> (release) (deliver) button_1_down
121105b261ecSmrg *	^o  -> (release) (deliver) button_1_down
121205b261ecSmrg *	<-> -> (release) (deliver) button_1_down
121305b261ecSmrg *	<>  -> (deliver) button_1_pend
121405b261ecSmrg *	k   -> (release) (deliver) button_1_down
121505b261ecSmrg *	... -> (release) button_1_down
121605b261ecSmrg *
121705b261ecSmrg *  button_1_down	(button 1 is down)
121805b261ecSmrg *	^1  -> (deliver) start
121905b261ecSmrg *	v2  -> (deliver) button_1_down
122005b261ecSmrg *	^2  -> (deliver) button_1_down
122105b261ecSmrg *	v3  -> (deliver) button_1_down
122205b261ecSmrg *	^3  -> (deliver) button_1_down
122305b261ecSmrg *	vo  -> (deliver) button_1_down
122405b261ecSmrg *	^o  -> (deliver) button_1_down
122505b261ecSmrg *	<>  -> (deliver) button_1_down
122605b261ecSmrg *	k   -> (deliver) button_1_down
122705b261ecSmrg *
122805b261ecSmrg *  button_2_down	(button 2 is down)
122905b261ecSmrg *	v1  -> (deliver) button_2_down
123005b261ecSmrg *	^1  -> (deliver) button_2_down
123105b261ecSmrg *	^2  -> (deliver) start
123205b261ecSmrg *	v3  -> (deliver) button_2_down
123305b261ecSmrg *	^3  -> (deliver) button_2_down
123405b261ecSmrg *	vo  -> (deliver) button_2_down
123505b261ecSmrg *	^o  -> (deliver) button_2_down
123605b261ecSmrg *	<>  -> (deliver) button_2_down
123705b261ecSmrg *	k   -> (deliver) button_2_down
123805b261ecSmrg *
123905b261ecSmrg *  button_3_pend	(button 3 is down, timeout pending)
124005b261ecSmrg *	v1  -> (generate v2) synthetic_2_down
124105b261ecSmrg *	^1  -> (release) (deliver) button_3_down
124205b261ecSmrg *	v2  -> (release) (deliver) button_3_down
124305b261ecSmrg *	^2  -> (release) (deliver) button_3_down
124405b261ecSmrg *	^3  -> (release) (deliver) start
124505b261ecSmrg *	vo  -> (release) (deliver) button_3_down
124605b261ecSmrg *	^o  -> (release) (deliver) button_3_down
124705b261ecSmrg *	<-> -> (release) (deliver) button_3_down
124805b261ecSmrg *	<>  -> (deliver) button_3_pend
124905b261ecSmrg *	k   -> (release) (deliver) button_3_down
125005b261ecSmrg *	... -> (release) button_3_down
125105b261ecSmrg *
125205b261ecSmrg *  button_3_down	(button 3 is down)
125305b261ecSmrg *	v1  -> (deliver) button_3_down
125405b261ecSmrg *	^1  -> (deliver) button_3_down
125505b261ecSmrg *	v2  -> (deliver) button_3_down
125605b261ecSmrg *	^2  -> (deliver) button_3_down
125705b261ecSmrg *	^3  -> (deliver) start
125805b261ecSmrg *	vo  -> (deliver) button_3_down
125905b261ecSmrg *	^o  -> (deliver) button_3_down
126005b261ecSmrg *	<>  -> (deliver) button_3_down
126105b261ecSmrg *	k   -> (deliver) button_3_down
126205b261ecSmrg *
126305b261ecSmrg *  synthetic_2_down_13	(button 1 and 3 are down)
126405b261ecSmrg *	^1  -> (generate ^2) synthetic_2_down_3
126505b261ecSmrg *	v2  -> synthetic_2_down_13
126605b261ecSmrg *	^2  -> synthetic_2_down_13
126705b261ecSmrg *	^3  -> (generate ^2) synthetic_2_down_1
126805b261ecSmrg *	vo  -> (deliver) synthetic_2_down_13
126905b261ecSmrg *	^o  -> (deliver) synthetic_2_down_13
127005b261ecSmrg *	<>  -> (deliver) synthetic_2_down_13
127105b261ecSmrg *	k   -> (deliver) synthetic_2_down_13
127205b261ecSmrg *
127305b261ecSmrg *  synthetic_2_down_3 (button 3 is down)
127405b261ecSmrg *	v1  -> (deliver) synthetic_2_down_3
127505b261ecSmrg *	^1  -> (deliver) synthetic_2_down_3
127605b261ecSmrg *	v2  -> synthetic_2_down_3
127705b261ecSmrg *	^2  -> synthetic_2_down_3
127805b261ecSmrg *	^3  -> start
127905b261ecSmrg *	vo  -> (deliver) synthetic_2_down_3
128005b261ecSmrg *	^o  -> (deliver) synthetic_2_down_3
128105b261ecSmrg *	<>  -> (deliver) synthetic_2_down_3
128205b261ecSmrg *	k   -> (deliver) synthetic_2_down_3
128305b261ecSmrg *
128405b261ecSmrg *  synthetic_2_down_1 (button 1 is down)
128505b261ecSmrg *	^1  -> start
128605b261ecSmrg *	v2  -> synthetic_2_down_1
128705b261ecSmrg *	^2  -> synthetic_2_down_1
128805b261ecSmrg *	v3  -> (deliver) synthetic_2_down_1
128905b261ecSmrg *	^3  -> (deliver) synthetic_2_down_1
129005b261ecSmrg *	vo  -> (deliver) synthetic_2_down_1
129105b261ecSmrg *	^o  -> (deliver) synthetic_2_down_1
129205b261ecSmrg *	<>  -> (deliver) synthetic_2_down_1
129305b261ecSmrg *	k   -> (deliver) synthetic_2_down_1
129405b261ecSmrg */
12956747b715Smrg
129605b261ecSmrgtypedef enum _inputClass {
129705b261ecSmrg    down_1, up_1,
129805b261ecSmrg    down_2, up_2,
129905b261ecSmrg    down_3, up_3,
130005b261ecSmrg    down_o, up_o,
130105b261ecSmrg    motion, outside_box,
130205b261ecSmrg    keyboard, timeout,
130305b261ecSmrg    num_input_class
130405b261ecSmrg} KdInputClass;
130505b261ecSmrg
130605b261ecSmrgtypedef enum _inputAction {
130705b261ecSmrg    noop,
130805b261ecSmrg    hold,
130905b261ecSmrg    setto,
131005b261ecSmrg    deliver,
131105b261ecSmrg    release,
131205b261ecSmrg    clearto,
131305b261ecSmrg    gen_down_2,
131405b261ecSmrg    gen_up_2
131505b261ecSmrg} KdInputAction;
131605b261ecSmrg
131705b261ecSmrg#define MAX_ACTIONS 2
131805b261ecSmrg
131905b261ecSmrgtypedef struct _inputTransition {
132035c4bbdfSmrg    KdInputAction actions[MAX_ACTIONS];
132105b261ecSmrg    KdPointerState nextState;
132205b261ecSmrg} KdInputTransition;
132305b261ecSmrg
132405b261ecSmrgstatic const
132535c4bbdfSmrgKdInputTransition kdInputMachine[num_input_states][num_input_class] = {
132605b261ecSmrg    /* start */
132705b261ecSmrg    {
132835c4bbdfSmrg     {{hold, setto}, button_1_pend},    /* v1 */
132935c4bbdfSmrg     {{deliver, noop}, start},  /* ^1 */
133035c4bbdfSmrg     {{deliver, noop}, button_2_down},  /* v2 */
133135c4bbdfSmrg     {{deliver, noop}, start},  /* ^2 */
133235c4bbdfSmrg     {{hold, setto}, button_3_pend},    /* v3 */
133335c4bbdfSmrg     {{deliver, noop}, start},  /* ^3 */
133435c4bbdfSmrg     {{deliver, noop}, start},  /* vo */
133535c4bbdfSmrg     {{deliver, noop}, start},  /* ^o */
133635c4bbdfSmrg     {{deliver, noop}, start},  /* <> */
133735c4bbdfSmrg     {{deliver, noop}, start},  /* <-> */
133835c4bbdfSmrg     {{noop, noop}, start},     /* k */
133935c4bbdfSmrg     {{noop, noop}, start},     /* ... */
134035c4bbdfSmrg     },
134105b261ecSmrg    /* button_1_pend */
134205b261ecSmrg    {
134335c4bbdfSmrg     {{noop, noop}, button_1_pend},     /* v1 */
134435c4bbdfSmrg     {{release, deliver}, start},       /* ^1 */
134535c4bbdfSmrg     {{release, deliver}, button_1_down},       /* v2 */
134635c4bbdfSmrg     {{release, deliver}, button_1_down},       /* ^2 */
134735c4bbdfSmrg     {{clearto, gen_down_2}, synth_2_down_13},  /* v3 */
134835c4bbdfSmrg     {{release, deliver}, button_1_down},       /* ^3 */
134935c4bbdfSmrg     {{release, deliver}, button_1_down},       /* vo */
135035c4bbdfSmrg     {{release, deliver}, button_1_down},       /* ^o */
135135c4bbdfSmrg     {{deliver, noop}, button_1_pend},  /* <> */
135235c4bbdfSmrg     {{release, deliver}, button_1_down},       /* <-> */
135335c4bbdfSmrg     {{noop, noop}, button_1_down},     /* k */
135435c4bbdfSmrg     {{release, noop}, button_1_down},  /* ... */
135535c4bbdfSmrg     },
135605b261ecSmrg    /* button_1_down */
135705b261ecSmrg    {
135835c4bbdfSmrg     {{noop, noop}, button_1_down},     /* v1 */
135935c4bbdfSmrg     {{deliver, noop}, start},  /* ^1 */
136035c4bbdfSmrg     {{deliver, noop}, button_1_down},  /* v2 */
136135c4bbdfSmrg     {{deliver, noop}, button_1_down},  /* ^2 */
136235c4bbdfSmrg     {{deliver, noop}, button_1_down},  /* v3 */
136335c4bbdfSmrg     {{deliver, noop}, button_1_down},  /* ^3 */
136435c4bbdfSmrg     {{deliver, noop}, button_1_down},  /* vo */
136535c4bbdfSmrg     {{deliver, noop}, button_1_down},  /* ^o */
136635c4bbdfSmrg     {{deliver, noop}, button_1_down},  /* <> */
136735c4bbdfSmrg     {{deliver, noop}, button_1_down},  /* <-> */
136835c4bbdfSmrg     {{noop, noop}, button_1_down},     /* k */
136935c4bbdfSmrg     {{noop, noop}, button_1_down},     /* ... */
137035c4bbdfSmrg     },
137105b261ecSmrg    /* button_2_down */
137205b261ecSmrg    {
137335c4bbdfSmrg     {{deliver, noop}, button_2_down},  /* v1 */
137435c4bbdfSmrg     {{deliver, noop}, button_2_down},  /* ^1 */
137535c4bbdfSmrg     {{noop, noop}, button_2_down},     /* v2 */
137635c4bbdfSmrg     {{deliver, noop}, start},  /* ^2 */
137735c4bbdfSmrg     {{deliver, noop}, button_2_down},  /* v3 */
137835c4bbdfSmrg     {{deliver, noop}, button_2_down},  /* ^3 */
137935c4bbdfSmrg     {{deliver, noop}, button_2_down},  /* vo */
138035c4bbdfSmrg     {{deliver, noop}, button_2_down},  /* ^o */
138135c4bbdfSmrg     {{deliver, noop}, button_2_down},  /* <> */
138235c4bbdfSmrg     {{deliver, noop}, button_2_down},  /* <-> */
138335c4bbdfSmrg     {{noop, noop}, button_2_down},     /* k */
138435c4bbdfSmrg     {{noop, noop}, button_2_down},     /* ... */
138535c4bbdfSmrg     },
138605b261ecSmrg    /* button_3_pend */
138705b261ecSmrg    {
138835c4bbdfSmrg     {{clearto, gen_down_2}, synth_2_down_13},  /* v1 */
138935c4bbdfSmrg     {{release, deliver}, button_3_down},       /* ^1 */
139035c4bbdfSmrg     {{release, deliver}, button_3_down},       /* v2 */
139135c4bbdfSmrg     {{release, deliver}, button_3_down},       /* ^2 */
139235c4bbdfSmrg     {{release, deliver}, button_3_down},       /* v3 */
139335c4bbdfSmrg     {{release, deliver}, start},       /* ^3 */
139435c4bbdfSmrg     {{release, deliver}, button_3_down},       /* vo */
139535c4bbdfSmrg     {{release, deliver}, button_3_down},       /* ^o */
139635c4bbdfSmrg     {{deliver, noop}, button_3_pend},  /* <> */
139735c4bbdfSmrg     {{release, deliver}, button_3_down},       /* <-> */
139835c4bbdfSmrg     {{release, noop}, button_3_down},  /* k */
139935c4bbdfSmrg     {{release, noop}, button_3_down},  /* ... */
140035c4bbdfSmrg     },
140105b261ecSmrg    /* button_3_down */
140205b261ecSmrg    {
140335c4bbdfSmrg     {{deliver, noop}, button_3_down},  /* v1 */
140435c4bbdfSmrg     {{deliver, noop}, button_3_down},  /* ^1 */
140535c4bbdfSmrg     {{deliver, noop}, button_3_down},  /* v2 */
140635c4bbdfSmrg     {{deliver, noop}, button_3_down},  /* ^2 */
140735c4bbdfSmrg     {{noop, noop}, button_3_down},     /* v3 */
140835c4bbdfSmrg     {{deliver, noop}, start},  /* ^3 */
140935c4bbdfSmrg     {{deliver, noop}, button_3_down},  /* vo */
141035c4bbdfSmrg     {{deliver, noop}, button_3_down},  /* ^o */
141135c4bbdfSmrg     {{deliver, noop}, button_3_down},  /* <> */
141235c4bbdfSmrg     {{deliver, noop}, button_3_down},  /* <-> */
141335c4bbdfSmrg     {{noop, noop}, button_3_down},     /* k */
141435c4bbdfSmrg     {{noop, noop}, button_3_down},     /* ... */
141535c4bbdfSmrg     },
141605b261ecSmrg    /* synthetic_2_down_13 */
141705b261ecSmrg    {
141835c4bbdfSmrg     {{noop, noop}, synth_2_down_13},   /* v1 */
141935c4bbdfSmrg     {{gen_up_2, noop}, synth_2_down_3},        /* ^1 */
142035c4bbdfSmrg     {{noop, noop}, synth_2_down_13},   /* v2 */
142135c4bbdfSmrg     {{noop, noop}, synth_2_down_13},   /* ^2 */
142235c4bbdfSmrg     {{noop, noop}, synth_2_down_13},   /* v3 */
142335c4bbdfSmrg     {{gen_up_2, noop}, synth_2_down_1},        /* ^3 */
142435c4bbdfSmrg     {{deliver, noop}, synth_2_down_13},        /* vo */
142535c4bbdfSmrg     {{deliver, noop}, synth_2_down_13},        /* ^o */
142635c4bbdfSmrg     {{deliver, noop}, synth_2_down_13},        /* <> */
142735c4bbdfSmrg     {{deliver, noop}, synth_2_down_13},        /* <-> */
142835c4bbdfSmrg     {{noop, noop}, synth_2_down_13},   /* k */
142935c4bbdfSmrg     {{noop, noop}, synth_2_down_13},   /* ... */
143035c4bbdfSmrg     },
143105b261ecSmrg    /* synthetic_2_down_3 */
143205b261ecSmrg    {
143335c4bbdfSmrg     {{deliver, noop}, synth_2_down_3}, /* v1 */
143435c4bbdfSmrg     {{deliver, noop}, synth_2_down_3}, /* ^1 */
143535c4bbdfSmrg     {{deliver, noop}, synth_2_down_3}, /* v2 */
143635c4bbdfSmrg     {{deliver, noop}, synth_2_down_3}, /* ^2 */
143735c4bbdfSmrg     {{noop, noop}, synth_2_down_3},    /* v3 */
143835c4bbdfSmrg     {{noop, noop}, start},     /* ^3 */
143935c4bbdfSmrg     {{deliver, noop}, synth_2_down_3}, /* vo */
144035c4bbdfSmrg     {{deliver, noop}, synth_2_down_3}, /* ^o */
144135c4bbdfSmrg     {{deliver, noop}, synth_2_down_3}, /* <> */
144235c4bbdfSmrg     {{deliver, noop}, synth_2_down_3}, /* <-> */
144335c4bbdfSmrg     {{noop, noop}, synth_2_down_3},    /* k */
144435c4bbdfSmrg     {{noop, noop}, synth_2_down_3},    /* ... */
144535c4bbdfSmrg     },
144605b261ecSmrg    /* synthetic_2_down_1 */
144705b261ecSmrg    {
144835c4bbdfSmrg     {{noop, noop}, synth_2_down_1},    /* v1 */
144935c4bbdfSmrg     {{noop, noop}, start},     /* ^1 */
145035c4bbdfSmrg     {{deliver, noop}, synth_2_down_1}, /* v2 */
145135c4bbdfSmrg     {{deliver, noop}, synth_2_down_1}, /* ^2 */
145235c4bbdfSmrg     {{deliver, noop}, synth_2_down_1}, /* v3 */
145335c4bbdfSmrg     {{deliver, noop}, synth_2_down_1}, /* ^3 */
145435c4bbdfSmrg     {{deliver, noop}, synth_2_down_1}, /* vo */
145535c4bbdfSmrg     {{deliver, noop}, synth_2_down_1}, /* ^o */
145635c4bbdfSmrg     {{deliver, noop}, synth_2_down_1}, /* <> */
145735c4bbdfSmrg     {{deliver, noop}, synth_2_down_1}, /* <-> */
145835c4bbdfSmrg     {{noop, noop}, synth_2_down_1},    /* k */
145935c4bbdfSmrg     {{noop, noop}, synth_2_down_1},    /* ... */
146035c4bbdfSmrg     },
146105b261ecSmrg};
146205b261ecSmrg
146305b261ecSmrg#define EMULATION_WINDOW    10
146405b261ecSmrg#define EMULATION_TIMEOUT   100
146505b261ecSmrg
146605b261ecSmrgstatic int
146735c4bbdfSmrgKdInsideEmulationWindow(KdPointerInfo * pi, int x, int y, int z)
146805b261ecSmrg{
146905b261ecSmrg    pi->emulationDx = pi->heldEvent.x - x;
147005b261ecSmrg    pi->emulationDy = pi->heldEvent.y - y;
147105b261ecSmrg
147235c4bbdfSmrg    return (abs(pi->emulationDx) < EMULATION_WINDOW &&
147335c4bbdfSmrg            abs(pi->emulationDy) < EMULATION_WINDOW);
147405b261ecSmrg}
14756747b715Smrg
147605b261ecSmrgstatic KdInputClass
147735c4bbdfSmrgKdClassifyInput(KdPointerInfo * pi, int type, int x, int y, int z, int b)
147805b261ecSmrg{
147905b261ecSmrg    switch (type) {
148005b261ecSmrg    case ButtonPress:
148135c4bbdfSmrg        switch (b) {
148235c4bbdfSmrg        case 1:
148335c4bbdfSmrg            return down_1;
148435c4bbdfSmrg        case 2:
148535c4bbdfSmrg            return down_2;
148635c4bbdfSmrg        case 3:
148735c4bbdfSmrg            return down_3;
148835c4bbdfSmrg        default:
148935c4bbdfSmrg            return down_o;
149035c4bbdfSmrg        }
149135c4bbdfSmrg        break;
149205b261ecSmrg    case ButtonRelease:
149335c4bbdfSmrg        switch (b) {
149435c4bbdfSmrg        case 1:
149535c4bbdfSmrg            return up_1;
149635c4bbdfSmrg        case 2:
149735c4bbdfSmrg            return up_2;
149835c4bbdfSmrg        case 3:
149935c4bbdfSmrg            return up_3;
150035c4bbdfSmrg        default:
150135c4bbdfSmrg            return up_o;
150235c4bbdfSmrg        }
150335c4bbdfSmrg        break;
150405b261ecSmrg    case MotionNotify:
150535c4bbdfSmrg        if (pi->eventHeld && !KdInsideEmulationWindow(pi, x, y, z))
150635c4bbdfSmrg            return outside_box;
150735c4bbdfSmrg        else
150835c4bbdfSmrg            return motion;
150905b261ecSmrg    default:
151035c4bbdfSmrg        return keyboard;
151105b261ecSmrg    }
151205b261ecSmrg    return keyboard;
151305b261ecSmrg}
151405b261ecSmrg
15151b5d61b8Smrgstatic void
15161b5d61b8Smrg_KdEnqueuePointerEvent(KdPointerInfo * pi, int type, int x, int y, int z,
15171b5d61b8Smrg                       int b, int absrel, Bool force);
151805b261ecSmrg/* We return true if we're stealing the event. */
151905b261ecSmrgstatic Bool
152035c4bbdfSmrgKdRunMouseMachine(KdPointerInfo * pi, KdInputClass c, int type, int x, int y,
152135c4bbdfSmrg                  int z, int b, int absrel)
152205b261ecSmrg{
152305b261ecSmrg    const KdInputTransition *t;
152435c4bbdfSmrg    int a;
152505b261ecSmrg
152605b261ecSmrg    c = KdClassifyInput(pi, type, x, y, z, b);
152705b261ecSmrg    t = &kdInputMachine[pi->mouseState][c];
152835c4bbdfSmrg    for (a = 0; a < MAX_ACTIONS; a++) {
152935c4bbdfSmrg        switch (t->actions[a]) {
153035c4bbdfSmrg        case noop:
153135c4bbdfSmrg            break;
153235c4bbdfSmrg        case hold:
153335c4bbdfSmrg            pi->eventHeld = TRUE;
153435c4bbdfSmrg            pi->emulationDx = 0;
153535c4bbdfSmrg            pi->emulationDy = 0;
153635c4bbdfSmrg            pi->heldEvent.type = type;
153705b261ecSmrg            pi->heldEvent.x = x;
153805b261ecSmrg            pi->heldEvent.y = y;
153905b261ecSmrg            pi->heldEvent.z = z;
154005b261ecSmrg            pi->heldEvent.flags = b;
154105b261ecSmrg            pi->heldEvent.absrel = absrel;
154205b261ecSmrg            return TRUE;
154335c4bbdfSmrg            break;
154435c4bbdfSmrg        case setto:
154535c4bbdfSmrg            pi->emulationTimeout = GetTimeInMillis() + EMULATION_TIMEOUT;
154635c4bbdfSmrg            pi->timeoutPending = TRUE;
154735c4bbdfSmrg            break;
154835c4bbdfSmrg        case deliver:
154935c4bbdfSmrg            _KdEnqueuePointerEvent(pi, pi->heldEvent.type, pi->heldEvent.x,
155035c4bbdfSmrg                                   pi->heldEvent.y, pi->heldEvent.z,
155135c4bbdfSmrg                                   pi->heldEvent.flags, pi->heldEvent.absrel,
155235c4bbdfSmrg                                   TRUE);
155335c4bbdfSmrg            break;
155435c4bbdfSmrg        case release:
155535c4bbdfSmrg            pi->eventHeld = FALSE;
155635c4bbdfSmrg            pi->timeoutPending = FALSE;
155735c4bbdfSmrg            _KdEnqueuePointerEvent(pi, pi->heldEvent.type, pi->heldEvent.x,
155835c4bbdfSmrg                                   pi->heldEvent.y, pi->heldEvent.z,
155935c4bbdfSmrg                                   pi->heldEvent.flags, pi->heldEvent.absrel,
156035c4bbdfSmrg                                   TRUE);
156105b261ecSmrg            return TRUE;
156235c4bbdfSmrg            break;
156335c4bbdfSmrg        case clearto:
156435c4bbdfSmrg            pi->timeoutPending = FALSE;
156535c4bbdfSmrg            break;
156635c4bbdfSmrg        case gen_down_2:
156735c4bbdfSmrg            _KdEnqueuePointerEvent(pi, ButtonPress, x, y, z, 2, absrel, TRUE);
156835c4bbdfSmrg            pi->eventHeld = FALSE;
156905b261ecSmrg            return TRUE;
157035c4bbdfSmrg            break;
157135c4bbdfSmrg        case gen_up_2:
157235c4bbdfSmrg            _KdEnqueuePointerEvent(pi, ButtonRelease, x, y, z, 2, absrel, TRUE);
157305b261ecSmrg            return TRUE;
157435c4bbdfSmrg            break;
157535c4bbdfSmrg        }
157605b261ecSmrg    }
157705b261ecSmrg    pi->mouseState = t->nextState;
157805b261ecSmrg    return FALSE;
157905b261ecSmrg}
158005b261ecSmrg
158105b261ecSmrgstatic int
158235c4bbdfSmrgKdHandlePointerEvent(KdPointerInfo * pi, int type, int x, int y, int z, int b,
158335c4bbdfSmrg                     int absrel)
158405b261ecSmrg{
158505b261ecSmrg    if (pi->emulateMiddleButton)
158635c4bbdfSmrg        return KdRunMouseMachine(pi, KdClassifyInput(pi, type, x, y, z, b),
158735c4bbdfSmrg                                 type, x, y, z, b, absrel);
158805b261ecSmrg    return FALSE;
158905b261ecSmrg}
159005b261ecSmrg
159105b261ecSmrgstatic void
15921b5d61b8Smrg_KdEnqueuePointerEvent(KdPointerInfo * pi, int type, int x, int y, int z,
15931b5d61b8Smrg                       int b, int absrel, Bool force)
159405b261ecSmrg{
15951b5d61b8Smrg    int valuators[3] = { x, y, z };
15961b5d61b8Smrg    ValuatorMask mask;
159705b261ecSmrg
15981b5d61b8Smrg    /* TRUE from KdHandlePointerEvent, means 'we swallowed the event'. */
15991b5d61b8Smrg    if (!force && KdHandlePointerEvent(pi, type, x, y, z, b, absrel))
16001b5d61b8Smrg        return;
160105b261ecSmrg
16021b5d61b8Smrg    valuator_mask_set_range(&mask, 0, 3, valuators);
160305b261ecSmrg
16041b5d61b8Smrg    QueuePointerEvents(pi->dixdev, type, b, absrel, &mask);
16051b5d61b8Smrg}
160605b261ecSmrg
16071b5d61b8Smrgstatic void
16081b5d61b8SmrgKdReceiveTimeout(KdPointerInfo * pi)
16091b5d61b8Smrg{
16101b5d61b8Smrg    KdRunMouseMachine(pi, timeout, 0, 0, 0, 0, 0, 0);
161105b261ecSmrg}
161205b261ecSmrg
16131b5d61b8Smrgextern int nClients;
16141b5d61b8Smrg
161505b261ecSmrgstatic void
161635c4bbdfSmrgKdCheckLock(void)
161705b261ecSmrg{
161835c4bbdfSmrg    KeyClassPtr keyc = NULL;
161935c4bbdfSmrg    Bool isSet = FALSE, shouldBeSet = FALSE;
162035c4bbdfSmrg    KdKeyboardInfo *tmp = NULL;
162105b261ecSmrg
162205b261ecSmrg    for (tmp = kdKeyboards; tmp; tmp = tmp->next) {
162305b261ecSmrg        if (tmp->LockLed && tmp->dixdev && tmp->dixdev->key) {
162405b261ecSmrg            keyc = tmp->dixdev->key;
162535c4bbdfSmrg            isSet = (tmp->leds & (1 << (tmp->LockLed - 1))) != 0;
16266747b715Smrg            /* FIXME: Just use XKB indicators! */
162735c4bbdfSmrg            shouldBeSet =
162835c4bbdfSmrg                ! !(XkbStateFieldFromRec(&keyc->xkbInfo->state) & LockMask);
162905b261ecSmrg            if (isSet != shouldBeSet)
163035c4bbdfSmrg                KdSetLed(tmp, tmp->LockLed, shouldBeSet);
163105b261ecSmrg        }
163205b261ecSmrg    }
163305b261ecSmrg}
163405b261ecSmrg
163505b261ecSmrgvoid
163635c4bbdfSmrgKdEnqueueKeyboardEvent(KdKeyboardInfo * ki,
163735c4bbdfSmrg                       unsigned char scan_code, unsigned char is_up)
163805b261ecSmrg{
163905b261ecSmrg    unsigned char key_code;
164035c4bbdfSmrg    int type;
164105b261ecSmrg
164205b261ecSmrg    if (!ki || !ki->dixdev || !ki->dixdev->kbdfeed || !ki->dixdev->key)
164335c4bbdfSmrg        return;
16446747b715Smrg
164535c4bbdfSmrg    if (scan_code >= ki->minScanCode && scan_code <= ki->maxScanCode) {
164635c4bbdfSmrg        key_code = scan_code + KD_MIN_KEYCODE - ki->minScanCode;
16476747b715Smrg
164835c4bbdfSmrg        /*
164935c4bbdfSmrg         * Set up this event -- the type may be modified below
165035c4bbdfSmrg         */
165135c4bbdfSmrg        if (is_up)
165235c4bbdfSmrg            type = KeyRelease;
165335c4bbdfSmrg        else
165435c4bbdfSmrg            type = KeyPress;
16556747b715Smrg
165635c4bbdfSmrg        QueueKeyboardEvents(ki->dixdev, type, key_code);
165705b261ecSmrg    }
165805b261ecSmrg    else {
165905b261ecSmrg        ErrorF("driver %s wanted to post scancode %d outside of [%d, %d]!\n",
166005b261ecSmrg               ki->name, scan_code, ki->minScanCode, ki->maxScanCode);
166105b261ecSmrg    }
166205b261ecSmrg}
166305b261ecSmrg
166405b261ecSmrg/*
166505b261ecSmrg * kdEnqueuePointerEvent
166605b261ecSmrg *
166705b261ecSmrg * This function converts hardware mouse event information into X event
166805b261ecSmrg * information.  A mouse movement event is passed off to MI to generate
166905b261ecSmrg * a MotionNotify event, if appropriate.  Button events are created and
167005b261ecSmrg * passed off to MI for enqueueing.
167105b261ecSmrg */
167205b261ecSmrg
167305b261ecSmrg/* FIXME do something a little more clever to deal with multiple axes here */
167405b261ecSmrgvoid
167535c4bbdfSmrgKdEnqueuePointerEvent(KdPointerInfo * pi, unsigned long flags, int rx, int ry,
167605b261ecSmrg                      int rz)
167705b261ecSmrg{
167805b261ecSmrg    unsigned char buttons;
167935c4bbdfSmrg    int x, y, z;
168035c4bbdfSmrg    int (*matrix)[3] = kdPointerMatrix.matrix;
168105b261ecSmrg    unsigned long button;
168235c4bbdfSmrg    int n;
168335c4bbdfSmrg    int dixflags = 0;
168405b261ecSmrg
168505b261ecSmrg    if (!pi)
168635c4bbdfSmrg        return;
168705b261ecSmrg
168805b261ecSmrg    /* we don't need to transform z, so we don't. */
168905b261ecSmrg    if (flags & KD_MOUSE_DELTA) {
169035c4bbdfSmrg        if (pi->transformCoordinates) {
169135c4bbdfSmrg            x = matrix[0][0] * rx + matrix[0][1] * ry;
169235c4bbdfSmrg            y = matrix[1][0] * rx + matrix[1][1] * ry;
169335c4bbdfSmrg        }
169435c4bbdfSmrg        else {
169535c4bbdfSmrg            x = rx;
169635c4bbdfSmrg            y = ry;
169735c4bbdfSmrg        }
169805b261ecSmrg    }
169905b261ecSmrg    else {
170035c4bbdfSmrg        if (pi->transformCoordinates) {
170135c4bbdfSmrg            x = matrix[0][0] * rx + matrix[0][1] * ry + matrix[0][2];
170235c4bbdfSmrg            y = matrix[1][0] * rx + matrix[1][1] * ry + matrix[1][2];
170335c4bbdfSmrg        }
170435c4bbdfSmrg        else {
170535c4bbdfSmrg            x = rx;
170635c4bbdfSmrg            y = ry;
170735c4bbdfSmrg        }
170805b261ecSmrg    }
170905b261ecSmrg    z = rz;
171005b261ecSmrg
171135c4bbdfSmrg    if (flags & KD_MOUSE_DELTA) {
171235c4bbdfSmrg        if (x || y || z) {
17134642e01fSmrg            dixflags = POINTER_RELATIVE | POINTER_ACCELERATE;
171435c4bbdfSmrg            _KdEnqueuePointerEvent(pi, MotionNotify, x, y, z, 0, dixflags,
171535c4bbdfSmrg                                   FALSE);
17164642e01fSmrg        }
171735c4bbdfSmrg    }
171835c4bbdfSmrg    else {
171905b261ecSmrg        dixflags = POINTER_ABSOLUTE;
172035c4bbdfSmrg        if (flags & KD_POINTER_DESKTOP)
172135c4bbdfSmrg            dixflags |= POINTER_DESKTOP;
17224642e01fSmrg        if (x != pi->dixdev->last.valuators[0] ||
17234642e01fSmrg            y != pi->dixdev->last.valuators[1])
172435c4bbdfSmrg            _KdEnqueuePointerEvent(pi, MotionNotify, x, y, z, 0, dixflags,
172535c4bbdfSmrg                                   FALSE);
17264642e01fSmrg    }
172705b261ecSmrg
172805b261ecSmrg    buttons = flags;
172905b261ecSmrg
173035c4bbdfSmrg    for (button = KD_BUTTON_1, n = 1; n <= pi->nButtons; button <<= 1, n++) {
173105b261ecSmrg        if (((pi->buttonState & button) ^ (buttons & button)) &&
173235c4bbdfSmrg            !(buttons & button)) {
173305b261ecSmrg            _KdEnqueuePointerEvent(pi, ButtonRelease, x, y, z, n,
173405b261ecSmrg                                   dixflags, FALSE);
173535c4bbdfSmrg        }
173605b261ecSmrg    }
173735c4bbdfSmrg    for (button = KD_BUTTON_1, n = 1; n <= pi->nButtons; button <<= 1, n++) {
173835c4bbdfSmrg        if (((pi->buttonState & button) ^ (buttons & button)) &&
173935c4bbdfSmrg            (buttons & button)) {
174005b261ecSmrg            _KdEnqueuePointerEvent(pi, ButtonPress, x, y, z, n,
174105b261ecSmrg                                   dixflags, FALSE);
174205b261ecSmrg        }
174305b261ecSmrg    }
174405b261ecSmrg
174505b261ecSmrg    pi->buttonState = buttons;
174605b261ecSmrg}
174705b261ecSmrg
174805b261ecSmrgvoid
17491b5d61b8SmrgKdBlockHandler(ScreenPtr pScreen, void *timeo)
175005b261ecSmrg{
175135c4bbdfSmrg    KdPointerInfo *pi;
175235c4bbdfSmrg    int myTimeout = 0;
17536747b715Smrg
175435c4bbdfSmrg    for (pi = kdPointers; pi; pi = pi->next) {
175535c4bbdfSmrg        if (pi->timeoutPending) {
175635c4bbdfSmrg            int ms;
175735c4bbdfSmrg
175835c4bbdfSmrg            ms = pi->emulationTimeout - GetTimeInMillis();
175935c4bbdfSmrg            if (ms < 1)
176035c4bbdfSmrg                ms = 1;
176135c4bbdfSmrg            if (ms < myTimeout || myTimeout == 0)
176235c4bbdfSmrg                myTimeout = ms;
176335c4bbdfSmrg        }
176405b261ecSmrg    }
176535c4bbdfSmrg    if (myTimeout > 0)
176635c4bbdfSmrg        AdjustWaitForDelay(timeo, myTimeout);
176705b261ecSmrg}
176805b261ecSmrg
176905b261ecSmrgvoid
17701b5d61b8SmrgKdWakeupHandler(ScreenPtr pScreen, int result)
177105b261ecSmrg{
177235c4bbdfSmrg    KdPointerInfo *pi;
17736747b715Smrg
177435c4bbdfSmrg    for (pi = kdPointers; pi; pi = pi->next) {
177535c4bbdfSmrg        if (pi->timeoutPending) {
177635c4bbdfSmrg            if ((long) (GetTimeInMillis() - pi->emulationTimeout) >= 0) {
177735c4bbdfSmrg                pi->timeoutPending = FALSE;
17781b5d61b8Smrg                input_lock();
177935c4bbdfSmrg                KdReceiveTimeout(pi);
17801b5d61b8Smrg                input_unlock();
178135c4bbdfSmrg            }
178235c4bbdfSmrg        }
178305b261ecSmrg    }
178405b261ecSmrg}
178505b261ecSmrg
178605b261ecSmrg#define KdScreenOrigin(pScreen) (&(KdGetScreenPriv(pScreen)->screen->origin))
178705b261ecSmrg
178805b261ecSmrgstatic Bool
178905b261ecSmrgKdCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y)
179005b261ecSmrg{
179135c4bbdfSmrg    ScreenPtr pScreen = *ppScreen;
179235c4bbdfSmrg    ScreenPtr pNewScreen;
179335c4bbdfSmrg    int n;
179435c4bbdfSmrg    int dx, dy;
179535c4bbdfSmrg    int best_x, best_y;
179635c4bbdfSmrg    int n_best_x, n_best_y;
179735c4bbdfSmrg    CARD32 ms;
17986747b715Smrg
179905b261ecSmrg    if (kdDisableZaphod || screenInfo.numScreens <= 1)
180035c4bbdfSmrg        return FALSE;
180105b261ecSmrg
180205b261ecSmrg    if (0 <= *x && *x < pScreen->width && 0 <= *y && *y < pScreen->height)
180335c4bbdfSmrg        return FALSE;
18046747b715Smrg
180535c4bbdfSmrg    ms = GetTimeInMillis();
180605b261ecSmrg    if (kdOffScreen && (int) (ms - kdOffScreenTime) < 1000)
180735c4bbdfSmrg        return FALSE;
180805b261ecSmrg    kdOffScreen = TRUE;
180905b261ecSmrg    kdOffScreenTime = ms;
181005b261ecSmrg    n_best_x = -1;
181105b261ecSmrg    best_x = 32767;
181205b261ecSmrg    n_best_y = -1;
181305b261ecSmrg    best_y = 32767;
181435c4bbdfSmrg    for (n = 0; n < screenInfo.numScreens; n++) {
181535c4bbdfSmrg        pNewScreen = screenInfo.screens[n];
181635c4bbdfSmrg        if (pNewScreen == pScreen)
181735c4bbdfSmrg            continue;
181835c4bbdfSmrg        dx = KdScreenOrigin(pNewScreen)->x - KdScreenOrigin(pScreen)->x;
181935c4bbdfSmrg        dy = KdScreenOrigin(pNewScreen)->y - KdScreenOrigin(pScreen)->y;
182035c4bbdfSmrg        if (*x < 0) {
182135c4bbdfSmrg            if (dx < 0 && -dx < best_x) {
182235c4bbdfSmrg                best_x = -dx;
182335c4bbdfSmrg                n_best_x = n;
182435c4bbdfSmrg            }
182535c4bbdfSmrg        }
182635c4bbdfSmrg        else if (*x >= pScreen->width) {
182735c4bbdfSmrg            if (dx > 0 && dx < best_x) {
182835c4bbdfSmrg                best_x = dx;
182935c4bbdfSmrg                n_best_x = n;
183035c4bbdfSmrg            }
183135c4bbdfSmrg        }
183235c4bbdfSmrg        if (*y < 0) {
183335c4bbdfSmrg            if (dy < 0 && -dy < best_y) {
183435c4bbdfSmrg                best_y = -dy;
183535c4bbdfSmrg                n_best_y = n;
183635c4bbdfSmrg            }
183735c4bbdfSmrg        }
183835c4bbdfSmrg        else if (*y >= pScreen->height) {
183935c4bbdfSmrg            if (dy > 0 && dy < best_y) {
184035c4bbdfSmrg                best_y = dy;
184135c4bbdfSmrg                n_best_y = n;
184235c4bbdfSmrg            }
184335c4bbdfSmrg        }
184405b261ecSmrg    }
184505b261ecSmrg    if (best_y < best_x)
184635c4bbdfSmrg        n_best_x = n_best_y;
184705b261ecSmrg    if (n_best_x == -1)
184835c4bbdfSmrg        return FALSE;
184905b261ecSmrg    pNewScreen = screenInfo.screens[n_best_x];
18506747b715Smrg
185105b261ecSmrg    if (*x < 0)
185235c4bbdfSmrg        *x += pNewScreen->width;
185305b261ecSmrg    if (*y < 0)
185435c4bbdfSmrg        *y += pNewScreen->height;
18556747b715Smrg
185605b261ecSmrg    if (*x >= pScreen->width)
185735c4bbdfSmrg        *x -= pScreen->width;
185805b261ecSmrg    if (*y >= pScreen->height)
185935c4bbdfSmrg        *y -= pScreen->height;
18606747b715Smrg
186105b261ecSmrg    *ppScreen = pNewScreen;
186205b261ecSmrg    return TRUE;
186305b261ecSmrg}
186405b261ecSmrg
186505b261ecSmrgstatic void
186605b261ecSmrgKdCrossScreen(ScreenPtr pScreen, Bool entering)
186705b261ecSmrg{
186805b261ecSmrg}
186905b261ecSmrg
187005b261ecSmrgstatic void
187135c4bbdfSmrgKdWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
187205b261ecSmrg{
18731b5d61b8Smrg    input_lock();
18744642e01fSmrg    miPointerWarpCursor(pDev, pScreen, x, y);
18751b5d61b8Smrg    input_unlock();
187605b261ecSmrg}
187705b261ecSmrg
187835c4bbdfSmrgmiPointerScreenFuncRec kdPointerScreenFuncs = {
187905b261ecSmrg    KdCursorOffScreen,
188005b261ecSmrg    KdCrossScreen,
188105b261ecSmrg    KdWarpCursor
188205b261ecSmrg};
188305b261ecSmrg
188405b261ecSmrgvoid
188535c4bbdfSmrgProcessInputEvents(void)
188605b261ecSmrg{
188705b261ecSmrg    mieqProcessInputEvents();
188835c4bbdfSmrg    KdCheckLock();
188905b261ecSmrg}
189005b261ecSmrg
189105b261ecSmrg/* At the moment, absolute/relative is up to the client. */
189205b261ecSmrgint
189305b261ecSmrgSetDeviceMode(register ClientPtr client, DeviceIntPtr pDev, int mode)
189405b261ecSmrg{
189505b261ecSmrg    return BadMatch;
189605b261ecSmrg}
189705b261ecSmrg
189805b261ecSmrgint
189905b261ecSmrgSetDeviceValuators(register ClientPtr client, DeviceIntPtr pDev,
190005b261ecSmrg                   int *valuators, int first_valuator, int num_valuators)
190105b261ecSmrg{
190205b261ecSmrg    return BadMatch;
190305b261ecSmrg}
190405b261ecSmrg
190505b261ecSmrgint
190605b261ecSmrgChangeDeviceControl(register ClientPtr client, DeviceIntPtr pDev,
190735c4bbdfSmrg                    xDeviceCtl * control)
190805b261ecSmrg{
190905b261ecSmrg    switch (control->control) {
191005b261ecSmrg    case DEVICE_RESOLUTION:
191105b261ecSmrg        /* FIXME do something more intelligent here */
191205b261ecSmrg        return BadMatch;
191305b261ecSmrg
191405b261ecSmrg    case DEVICE_ABS_CALIB:
191505b261ecSmrg    case DEVICE_ABS_AREA:
191605b261ecSmrg    case DEVICE_CORE:
19174642e01fSmrg        return BadMatch;
191805b261ecSmrg    case DEVICE_ENABLE:
191905b261ecSmrg        return Success;
192005b261ecSmrg
192105b261ecSmrg    default:
192205b261ecSmrg        return BadMatch;
192305b261ecSmrg    }
192405b261ecSmrg
192505b261ecSmrg    /* NOTREACHED */
192605b261ecSmrg    return BadImplementation;
192705b261ecSmrg}
192805b261ecSmrg
192905b261ecSmrgint
193035c4bbdfSmrgNewInputDeviceRequest(InputOption *options, InputAttributes * attrs,
19316747b715Smrg                      DeviceIntPtr *pdev)
193205b261ecSmrg{
19331b5d61b8Smrg    InputOption *option = NULL, *optionsdup = NULL;
193405b261ecSmrg    KdPointerInfo *pi = NULL;
193505b261ecSmrg    KdKeyboardInfo *ki = NULL;
193605b261ecSmrg
193735c4bbdfSmrg    nt_list_for_each_entry(option, options, list.next) {
193835c4bbdfSmrg        const char *key = input_option_get_key(option);
193935c4bbdfSmrg        const char *value = input_option_get_value(option);
19401b5d61b8Smrg        optionsdup = input_option_new(optionsdup, key, value);
194135c4bbdfSmrg
194235c4bbdfSmrg        if (strcmp(key, "type") == 0) {
194335c4bbdfSmrg            if (strcmp(value, "pointer") == 0) {
194405b261ecSmrg                pi = KdNewPointer();
19451b5d61b8Smrg                if (!pi) {
19461b5d61b8Smrg                    input_option_free_list(&optionsdup);
194705b261ecSmrg                    return BadAlloc;
19481b5d61b8Smrg                }
194905b261ecSmrg            }
195035c4bbdfSmrg            else if (strcmp(value, "keyboard") == 0) {
195105b261ecSmrg                ki = KdNewKeyboard();
19521b5d61b8Smrg                if (!ki) {
19531b5d61b8Smrg                    input_option_free_list(&optionsdup);
195405b261ecSmrg                    return BadAlloc;
19551b5d61b8Smrg                }
195605b261ecSmrg            }
195705b261ecSmrg            else {
195805b261ecSmrg                ErrorF("unrecognised device type!\n");
195905b261ecSmrg                return BadValue;
196005b261ecSmrg            }
196105b261ecSmrg        }
19626747b715Smrg#ifdef CONFIG_HAL
196335c4bbdfSmrg        else if (strcmp(key, "_source") == 0 &&
196435c4bbdfSmrg                 strcmp(value, "server/hal") == 0) {
19651b5d61b8Smrg            if (SeatId) {
19661b5d61b8Smrg                /* Input hot-plugging is enabled */
19671b5d61b8Smrg                if (attrs->flags & ATTR_POINTER) {
19681b5d61b8Smrg                    pi = KdNewPointer();
19691b5d61b8Smrg                    if (!pi) {
19701b5d61b8Smrg                        input_option_free_list(&optionsdup);
19711b5d61b8Smrg                        return BadAlloc;
19721b5d61b8Smrg                    }
19731b5d61b8Smrg                }
19741b5d61b8Smrg                else if (attrs->flags & ATTR_KEYBOARD) {
19751b5d61b8Smrg                    ki = KdNewKeyboard();
19761b5d61b8Smrg                    if (!ki) {
19771b5d61b8Smrg                        input_option_free_list(&optionsdup);
19781b5d61b8Smrg                        return BadAlloc;
19791b5d61b8Smrg                    }
19801b5d61b8Smrg                }
19811b5d61b8Smrg            }
19821b5d61b8Smrg            else {
19831b5d61b8Smrg                ErrorF("Ignoring device from HAL.\n");
19841b5d61b8Smrg                input_option_free_list(&optionsdup);
19851b5d61b8Smrg                return BadValue;
19861b5d61b8Smrg            }
19876747b715Smrg        }
19886747b715Smrg#endif
19896747b715Smrg#ifdef CONFIG_UDEV
199035c4bbdfSmrg        else if (strcmp(key, "_source") == 0 &&
199135c4bbdfSmrg                 strcmp(value, "server/udev") == 0) {
19921b5d61b8Smrg            if (SeatId) {
19931b5d61b8Smrg                /* Input hot-plugging is enabled */
19941b5d61b8Smrg                if (attrs->flags & ATTR_POINTER) {
19951b5d61b8Smrg                    pi = KdNewPointer();
19961b5d61b8Smrg                    if (!pi) {
19971b5d61b8Smrg                        input_option_free_list(&optionsdup);
19981b5d61b8Smrg                        return BadAlloc;
19991b5d61b8Smrg                    }
200005b261ecSmrg                }
20011b5d61b8Smrg                else if (attrs->flags & ATTR_KEYBOARD) {
20021b5d61b8Smrg                    ki = KdNewKeyboard();
20031b5d61b8Smrg                    if (!ki) {
20041b5d61b8Smrg                        input_option_free_list(&optionsdup);
20051b5d61b8Smrg                        return BadAlloc;
20061b5d61b8Smrg                    }
200705b261ecSmrg                }
20081b5d61b8Smrg            }
20091b5d61b8Smrg            else {
20101b5d61b8Smrg                ErrorF("Ignoring device from udev.\n");
20111b5d61b8Smrg                input_option_free_list(&optionsdup);
20121b5d61b8Smrg                return BadValue;
201305b261ecSmrg            }
201405b261ecSmrg        }
20151b5d61b8Smrg#endif
201605b261ecSmrg    }
201705b261ecSmrg
201805b261ecSmrg    if (pi) {
20191b5d61b8Smrg        pi->options = optionsdup;
20201b5d61b8Smrg        KdParsePointerOptions(pi);
20211b5d61b8Smrg
20221b5d61b8Smrg        if (!pi->driver) {
20231b5d61b8Smrg            ErrorF("couldn't find driver for pointer device \"%s\" (%s)\n",
20241b5d61b8Smrg                   pi->name ? pi->name : "(unnamed)", pi->path);
20251b5d61b8Smrg            KdFreePointer(pi);
20261b5d61b8Smrg            return BadValue;
20271b5d61b8Smrg        }
20281b5d61b8Smrg
202905b261ecSmrg        if (KdAddPointer(pi) != Success ||
20306747b715Smrg            ActivateDevice(pi->dixdev, TRUE) != Success ||
20316747b715Smrg            EnableDevice(pi->dixdev, TRUE) != TRUE) {
20321b5d61b8Smrg            ErrorF("couldn't add or enable pointer \"%s\" (%s)\n",
20331b5d61b8Smrg                   pi->name ? pi->name : "(unnamed)", pi->path);
20341b5d61b8Smrg            KdFreePointer(pi);
203505b261ecSmrg            return BadImplementation;
203605b261ecSmrg        }
20371b5d61b8Smrg
20381b5d61b8Smrg        *pdev = pi->dixdev;
203905b261ecSmrg    }
204005b261ecSmrg    else if (ki) {
20411b5d61b8Smrg        ki->options = optionsdup;
20421b5d61b8Smrg        KdParseKbdOptions(ki);
20431b5d61b8Smrg
20441b5d61b8Smrg        if (!ki->driver) {
20451b5d61b8Smrg            ErrorF("couldn't find driver for keyboard device \"%s\" (%s)\n",
20461b5d61b8Smrg                   ki->name ? ki->name : "(unnamed)", ki->path);
20471b5d61b8Smrg            KdFreeKeyboard(ki);
20481b5d61b8Smrg            return BadValue;
20491b5d61b8Smrg        }
20501b5d61b8Smrg
205105b261ecSmrg        if (KdAddKeyboard(ki) != Success ||
20526747b715Smrg            ActivateDevice(ki->dixdev, TRUE) != Success ||
20536747b715Smrg            EnableDevice(ki->dixdev, TRUE) != TRUE) {
20541b5d61b8Smrg            ErrorF("couldn't add or enable keyboard \"%s\" (%s)\n",
20551b5d61b8Smrg                   ki->name ? ki->name : "(unnamed)", ki->path);
20561b5d61b8Smrg            KdFreeKeyboard(ki);
205705b261ecSmrg            return BadImplementation;
205805b261ecSmrg        }
205905b261ecSmrg
206005b261ecSmrg        *pdev = ki->dixdev;
206105b261ecSmrg    }
20621b5d61b8Smrg    else {
20631b5d61b8Smrg        ErrorF("unrecognised device identifier: %s\n",
20641b5d61b8Smrg               input_option_get_value(input_option_find(optionsdup,
20651b5d61b8Smrg                                                        "device")));
20661b5d61b8Smrg        input_option_free_list(&optionsdup);
20671b5d61b8Smrg        return BadValue;
20681b5d61b8Smrg    }
206905b261ecSmrg
207005b261ecSmrg    return Success;
207105b261ecSmrg}
207205b261ecSmrg
207305b261ecSmrgvoid
207405b261ecSmrgDeleteInputDeviceRequest(DeviceIntPtr pDev)
207505b261ecSmrg{
20766747b715Smrg    RemoveDevice(pDev, TRUE);
207705b261ecSmrg}
20781b5d61b8Smrg
20791b5d61b8Smrgvoid
20801b5d61b8SmrgRemoveInputDeviceTraces(const char *config_info)
20811b5d61b8Smrg{
20821b5d61b8Smrg}
2083