~brandontschaefer/+junk/break-x

« back to all changes in this revision

Viewing changes to hw/kdrive/src/kinput.c

  • Committer: Brandon Schaefer
  • Date: 2014-09-30 19:38:40 UTC
  • Revision ID: brandon.schaefer@canonical.com-20140930193840-a65z6qk8ze02cgsb
* Init commit to back this up

Show diffs side-by-side

added added

removed removed

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