getevents.c 63.6 KB
Newer Older
1
2
/*
 * Copyright © 2006 Nokia Corporation
3
 * Copyright © 2006-2007 Daniel Stone
4
 * Copyright © 2008 Red Hat, Inc.
5
 * Copyright © 2011 The Chromium Authors
Daniel Stone's avatar
Daniel Stone committed
6
 *
7
8
9
10
11
12
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
13
 *
14
15
16
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
17
 *
18
19
20
21
22
23
24
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
25
 *
26
27
 * Authors: Daniel Stone <daniel@fooishbar.org>
 *          Peter Hutterer <peter.hutterer@who-t.net>
28
29
30
31
32
33
34
35
36
 */

#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif

#include <X11/X.h>
#include <X11/keysym.h>
#include <X11/Xproto.h>
37
#include <math.h>
38
#include <limits.h>
39
40
41

#include "misc.h"
#include "resource.h"
42
43
44
45
46
#include "inputstr.h"
#include "scrnintstr.h"
#include "cursorstr.h"
#include "dixstruct.h"
#include "globals.h"
47
#include "dixevents.h"
48
#include "mipointer.h"
49
#include "eventstr.h"
50
#include "eventconvert.h"
51
#include "inpututils.h"
52
#include "mi.h"
53
#include "windowstr.h"
54
55

#include <X11/extensions/XKBproto.h>
56
#include "xkbsrv.h"
57

58
59
60
61
62
#ifdef PANORAMIX
#include "panoramiX.h"
#include "panoramiXsrv.h"
#endif

63
#include <X11/extensions/XI.h>
64
#include <X11/extensions/XI2.h>
65
#include <X11/extensions/XIproto.h>
66
#include <pixman.h>
67
68
69
#include "exglobals.h"
#include "exevents.h"
#include "extnsionst.h"
70
#include "listdev.h"            /* for sizing up DeviceClassesChangedEvent */
71

72
73
74
75
76
77
#if XSERVER_DTRACE
#include <sys/types.h>
typedef const char *string;
#include <Xserver-dtrace.h>
#endif

Daniel Stone's avatar
Daniel Stone committed
78
79
80
/* Number of motion history events to store. */
#define MOTION_HISTORY_SIZE 256

81
82
83
84
/**
 * InputEventList is the storage for input events generated by
 * QueuePointerEvents, QueueKeyboardEvents, and QueueProximityEvents.
 * This list is allocated on startup by the DIX.
85
 */
86
InternalEvent *InputEventList = NULL;
87

88
/**
89
 * Pick some arbitrary size for Xi motion history.
90
 */
91
int
92
GetMotionHistorySize(void)
93
94
{
    return MOTION_HISTORY_SIZE;
95
96
}

97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
void
set_button_down(DeviceIntPtr pDev, int button, int type)
{
    if (type == BUTTON_PROCESSED)
        SetBit(pDev->button->down, button);
    else
        SetBit(pDev->button->postdown, button);
}

void
set_button_up(DeviceIntPtr pDev, int button, int type)
{
    if (type == BUTTON_PROCESSED)
        ClearBit(pDev->button->down, button);
    else
        ClearBit(pDev->button->postdown, button);
}

Bool
button_is_down(DeviceIntPtr pDev, int button, int type)
{
118
    Bool ret = FALSE;
119
120

    if (type & BUTTON_PROCESSED)
121
        ret = ret || BitIsOn(pDev->button->down, button);
122
    if (type & BUTTON_POSTED)
123
        ret = ret || BitIsOn(pDev->button->postdown, button);
124
125
126
127

    return ret;
}

Daniel Stone's avatar
Daniel Stone committed
128
129
void
set_key_down(DeviceIntPtr pDev, int key_code, int type)
130
{
Daniel Stone's avatar
Daniel Stone committed
131
    if (type == KEY_PROCESSED)
132
        SetBit(pDev->key->down, key_code);
Daniel Stone's avatar
Daniel Stone committed
133
    else
134
        SetBit(pDev->key->postdown, key_code);
135
136
}

Daniel Stone's avatar
Daniel Stone committed
137
138
void
set_key_up(DeviceIntPtr pDev, int key_code, int type)
139
{
Daniel Stone's avatar
Daniel Stone committed
140
    if (type == KEY_PROCESSED)
141
        ClearBit(pDev->key->down, key_code);
Daniel Stone's avatar
Daniel Stone committed
142
    else
143
        ClearBit(pDev->key->postdown, key_code);
144
145
}

Daniel Stone's avatar
Daniel Stone committed
146
147
Bool
key_is_down(DeviceIntPtr pDev, int key_code, int type)
148
{
149
    Bool ret = FALSE;
Daniel Stone's avatar
Daniel Stone committed
150
151

    if (type & KEY_PROCESSED)
152
        ret = ret || BitIsOn(pDev->key->down, key_code);
153
    if (type & KEY_POSTED)
154
        ret = ret || BitIsOn(pDev->key->postdown, key_code);
Daniel Stone's avatar
Daniel Stone committed
155
156

    return ret;
157
158
159
160
161
}

static Bool
key_autorepeats(DeviceIntPtr pDev, int key_code)
{
162
163
    return ! !(pDev->kbdfeed->ctrl.autoRepeats[key_code >> 3] &
               (1 << (key_code & 7)));
164
}
165

166
167
168
169
170
171
172
173
174
175
176
static void
init_touch_ownership(DeviceIntPtr dev, TouchOwnershipEvent *event, Time ms)
{
    memset(event, 0, sizeof(TouchOwnershipEvent));
    event->header = ET_Internal;
    event->type = ET_TouchOwnership;
    event->length = sizeof(TouchOwnershipEvent);
    event->time = ms;
    event->deviceid = dev->id;
}

177
static void
178
init_raw(DeviceIntPtr dev, RawDeviceEvent *event, Time ms, int type, int detail)
179
180
181
182
{
    memset(event, 0, sizeof(RawDeviceEvent));
    event->header = ET_Internal;
    event->length = sizeof(RawDeviceEvent);
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
    switch (type) {
    case MotionNotify:
        event->type = ET_RawMotion;
        break;
    case ButtonPress:
        event->type = ET_RawButtonPress;
        break;
    case ButtonRelease:
        event->type = ET_RawButtonRelease;
        break;
    case KeyPress:
        event->type = ET_RawKeyPress;
        break;
    case KeyRelease:
        event->type = ET_RawKeyRelease;
        break;
    case XI_TouchBegin:
        event->type = ET_RawTouchBegin;
        break;
    case XI_TouchUpdate:
        event->type = ET_RawTouchUpdate;
        break;
    case XI_TouchEnd:
        event->type = ET_RawTouchEnd;
        break;
Peter Hutterer's avatar
Peter Hutterer committed
208
    }
209
210
211
212
213
214
215
    event->time = ms;
    event->deviceid = dev->id;
    event->sourceid = dev->id;
    event->detail.button = detail;
}

static void
216
set_raw_valuators(RawDeviceEvent *event, ValuatorMask *mask, double *data)
217
218
{
    int i;
219

220
221
    for (i = 0; i < valuator_mask_size(mask); i++) {
        if (valuator_mask_isset(mask, i)) {
222
            SetBit(event->valuators.mask, i);
223
            data[i] = valuator_mask_get_double(mask, i);
224
225
        }
    }
226
227
}

228
static void
229
set_valuators(DeviceIntPtr dev, DeviceEvent *event, ValuatorMask *mask)
230
231
232
{
    int i;

233
234
    /* Set the data to the previous value for unset absolute axes. The values
     * may be used when sent as part of an XI 1.x valuator event. */
235
236
    for (i = 0; i < valuator_mask_size(mask); i++) {
        if (valuator_mask_isset(mask, i)) {
237
            SetBit(event->valuators.mask, i);
238
            if (valuator_get_mode(dev, i) == Absolute)
239
                SetBit(event->valuators.mode, i);
240
            event->valuators.data[i] = valuator_mask_get_double(mask, i);
241
        }
242
243
        else if (valuator_get_mode(dev, i) == Absolute)
            event->valuators.data[i] = dev->valuator->axisVal[i];
244
    }
245
246
}

247
void
248
249
CreateClassesChangedEvent(InternalEvent *event,
                          DeviceIntPtr master, DeviceIntPtr slave, int flags)
250
{
251
    int i;
252
    DeviceChangedEvent *dce;
253
    CARD32 ms = GetTimeInMillis();
254

255
    dce = &event->changed_event;
256
    memset(dce, 0, sizeof(DeviceChangedEvent));
257
    dce->deviceid = slave->id;
258
    dce->masterid = master ? master->id : 0;
259
260
261
262
    dce->header = ET_Internal;
    dce->length = sizeof(DeviceChangedEvent);
    dce->type = ET_DeviceChanged;
    dce->time = ms;
263
    dce->flags = flags;
264
    dce->sourceid = slave->id;
265

266
    if (slave->button) {
267
268
        dce->buttons.num_buttons = slave->button->numButtons;
        for (i = 0; i < dce->buttons.num_buttons; i++)
269
            dce->buttons.names[i] = slave->button->labels[i];
270
    }
271
    if (slave->valuator) {
272
        dce->num_valuators = slave->valuator->numAxes;
273
        for (i = 0; i < dce->num_valuators; i++) {
274
275
276
            dce->valuators[i].min = slave->valuator->axes[i].min_value;
            dce->valuators[i].max = slave->valuator->axes[i].max_value;
            dce->valuators[i].resolution = slave->valuator->axes[i].resolution;
277
            dce->valuators[i].mode = slave->valuator->axes[i].mode;
278
            dce->valuators[i].name = slave->valuator->axes[i].label;
279
            dce->valuators[i].scroll = slave->valuator->axes[i].scroll;
280
281
        }
    }
282
    if (slave->key) {
283
284
285
        dce->keys.min_keycode = slave->key->xkbInfo->desc->min_key_code;
        dce->keys.max_keycode = slave->key->xkbInfo->desc->max_key_code;
    }
286
287
}

288
289
290
/**
 * Rescale the coord between the two axis ranges.
 */
291
292
static double
rescaleValuatorAxis(double coord, AxisInfoPtr from, AxisInfoPtr to,
293
                    double defmin, double defmax)
294
{
295
296
    double fmin = defmin, fmax = defmax;
    double tmin = defmin, tmax = defmax;
297

298
    if (from && from->min_value < from->max_value) {
299
300
        fmin = from->min_value;
        fmax = from->max_value;
301
    }
302
    if (to && to->min_value < to->max_value) {
303
304
        tmin = to->min_value;
        tmax = to->max_value;
305
    }
306

307
    if (fmin == tmin && fmax == tmax)
308
        return coord;
Peter Hutterer's avatar
Peter Hutterer committed
309

310
    if (fmax == fmin)           /* avoid division by 0 */
311
        return 0.0;
Peter Hutterer's avatar
Peter Hutterer committed
312

313
    return (coord - fmin) * (tmax - tmin) / (fmax - fmin) + tmin;
314
315
316
317
318
319
}

/**
 * Update all coordinates when changing to a different SD
 * to ensure that relative reporting will work as expected
 * without loss of precision.
320
321
322
 *
 * pDev->last.valuators will be in absolute device coordinates after this
 * function.
323
324
325
326
 */
static void
updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
{
327
328
    int i;
    DeviceIntPtr lastSlave;
329

330
    /* master->last.valuators[0]/[1] is in desktop-wide coords and the actual
331
     * position of the pointer */
332
333
    pDev->last.valuators[0] = master->last.valuators[0];
    pDev->last.valuators[1] = master->last.valuators[1];
334

335
336
337
    if (!pDev->valuator)
        return;

338
    /* scale back to device coordinates */
339
    if (pDev->valuator->numAxes > 0) {
340
341
342
        pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0],
                                                      NULL,
                                                      pDev->valuator->axes + 0,
343
344
                                                      screenInfo.x,
                                                      screenInfo.width);
345
    }
346
    if (pDev->valuator->numAxes > 1) {
347
348
349
        pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1],
                                                      NULL,
                                                      pDev->valuator->axes + 1,
350
351
                                                      screenInfo.y,
                                                      screenInfo.height);
352
    }
353
354
355
356
357

    /* calculate the other axis as well based on info from the old
     * slave-device. If the old slave had less axes than this one,
     * last.valuators is reset to 0.
     */
358
    if ((lastSlave = master->last.slave) && lastSlave->valuator) {
359
        for (i = 2; i < pDev->valuator->numAxes; i++) {
360
            if (i >= lastSlave->valuator->numAxes) {
361
                pDev->last.valuators[i] = 0;
362
                valuator_mask_set_double(pDev->last.scroll, i, 0);
363
            }
364
            else {
365
                double val = pDev->last.valuators[i];
366

367
                val = rescaleValuatorAxis(val, lastSlave->valuator->axes + i,
368
                                          pDev->valuator->axes + i, 0, 0);
369
                pDev->last.valuators[i] = val;
370
                valuator_mask_set_double(pDev->last.scroll, i, val);
371
            }
372
373
374
        }
    }

375
376
}

377
/**
378
 * Allocate the motion history buffer.
379
 */
380
void
381
382
AllocateMotionHistory(DeviceIntPtr pDev)
{
383
    int size;
384

385
    free(pDev->valuator->motion);
386
387
388
389

    if (pDev->valuator->numMotionEvents < 1)
        return;

390
391
392
393
    /* An MD must have a motion history size large enough to keep all
     * potential valuators, plus the respective range of the valuators.
     * 3 * INT32 for (min_val, max_val, curr_val))
     */
394
    if (IsMaster(pDev))
395
        size = sizeof(INT32) * 3 * MAX_VALUATORS;
396
397
398
    else {
        ValuatorClassPtr v = pDev->valuator;
        int numAxes;
399

400
401
        /* XI1 doesn't understand mixed mode devices */
        for (numAxes = 0; numAxes < v->numAxes; numAxes++)
402
            if (valuator_get_mode(pDev, numAxes) != valuator_get_mode(pDev, 0))
403
404
405
                break;
        size = sizeof(INT32) * numAxes;
    }
406
407
408

    size += sizeof(Time);

409
    pDev->valuator->motion = calloc(pDev->valuator->numMotionEvents, size);
410
411
    pDev->valuator->first_motion = 0;
    pDev->valuator->last_motion = 0;
412
413
    if (!pDev->valuator->motion)
        ErrorF("[dix] %s: Failed to alloc motion history (%d bytes).\n",
414
               pDev->name, size * pDev->valuator->numMotionEvents);
415
416
417
}

/**
418
419
420
 * Dump the motion history between start and stop into the supplied buffer.
 * Only records the event for a given screen in theory, but in practice, we
 * sort of ignore this.
421
422
 *
 * If core is set, we only generate x/y, in INT16, scaled to screen coords.
423
 */
424
int
425
GetMotionHistory(DeviceIntPtr pDev, xTimecoord ** buff, unsigned long start,
426
                 unsigned long stop, ScreenPtr pScreen, BOOL core)
427
{
428
    char *ibuff = NULL, *obuff;
429
    int i = 0, ret = 0;
430
    int j, coord;
431
    Time current;
432

433
    /* The size of a single motion event. */
434
    int size;
435
436
    AxisInfo from, *to;         /* for scaling */
    INT32 *ocbuf, *icbuf;       /* pointer to coordinates for copying */
437
    INT16 *corebuf;
438
    AxisInfo core_axis = { 0 };
439

440
    if (!pDev->valuator || !pDev->valuator->numMotionEvents)
441
        return 0;
Daniel Stone's avatar
Daniel Stone committed
442

443
444
445
    if (core && !pScreen)
        return 0;

446
    if (IsMaster(pDev))
447
448
449
450
        size = (sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(Time);
    else
        size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);

451
    *buff = malloc(size * pDev->valuator->numMotionEvents);
452
453
    if (!(*buff))
        return 0;
454
    obuff = (char *) *buff;
455

456
457
458
459
460
461
462
463
    for (i = pDev->valuator->first_motion;
         i != pDev->valuator->last_motion;
         i = (i + 1) % pDev->valuator->numMotionEvents) {
        /* We index the input buffer by which element we're accessing, which
         * is not monotonic, and the output buffer by how many events we've
         * written so far. */
        ibuff = (char *) pDev->valuator->motion + (i * size);
        memcpy(&current, ibuff, sizeof(Time));
464

465
466
467
468
        if (current > stop) {
            return ret;
        }
        else if (current >= start) {
469
470
            if (core) {
                memcpy(obuff, ibuff, sizeof(Time));     /* copy timestamp */
471

472
473
                icbuf = (INT32 *) (ibuff + sizeof(Time));
                corebuf = (INT16 *) (obuff + sizeof(Time));
474
475
476
477
478
479
480
481
482

                /* fetch x coordinate + range */
                memcpy(&from.min_value, icbuf++, sizeof(INT32));
                memcpy(&from.max_value, icbuf++, sizeof(INT32));
                memcpy(&coord, icbuf++, sizeof(INT32));

                /* scale to screen coords */
                to = &core_axis;
                to->max_value = pScreen->width;
483
484
                coord =
                    rescaleValuatorAxis(coord, &from, to, 0, pScreen->width);
485
486
487
488
489
490
491
492
493
494

                memcpy(corebuf, &coord, sizeof(INT16));
                corebuf++;

                /* fetch y coordinate + range */
                memcpy(&from.min_value, icbuf++, sizeof(INT32));
                memcpy(&from.max_value, icbuf++, sizeof(INT32));
                memcpy(&coord, icbuf++, sizeof(INT32));

                to->max_value = pScreen->height;
495
496
                coord =
                    rescaleValuatorAxis(coord, &from, to, 0, pScreen->height);
497
498
                memcpy(corebuf, &coord, sizeof(INT16));

499
500
501
            }
            else if (IsMaster(pDev)) {
                memcpy(obuff, ibuff, sizeof(Time));     /* copy timestamp */
502

503
504
505
                ocbuf = (INT32 *) (obuff + sizeof(Time));
                icbuf = (INT32 *) (ibuff + sizeof(Time));
                for (j = 0; j < MAX_VALUATORS; j++) {
506
507
508
509
510
511
512
513
                    if (j >= pDev->valuator->numAxes)
                        break;

                    /* fetch min/max/coordinate */
                    memcpy(&from.min_value, icbuf++, sizeof(INT32));
                    memcpy(&from.max_value, icbuf++, sizeof(INT32));
                    memcpy(&coord, icbuf++, sizeof(INT32));

514
515
516
                    to = (j <
                          pDev->valuator->numAxes) ? &pDev->valuator->
                        axes[j] : NULL;
517
518
519
520
521
522
523
524

                    /* x/y scaled to screen if no range is present */
                    if (j == 0 && (from.max_value < from.min_value))
                        from.max_value = pScreen->width;
                    else if (j == 1 && (from.max_value < from.min_value))
                        from.max_value = pScreen->height;

                    /* scale from stored range into current range */
525
                    coord = rescaleValuatorAxis(coord, &from, to, 0, 0);
526
527
528
                    memcpy(ocbuf, &coord, sizeof(INT32));
                    ocbuf++;
                }
529
530
            }
            else
531
532
533
534
                memcpy(obuff, ibuff, size);

            /* don't advance by size here. size may be different to the
             * actually written size if the MD has less valuators than MAX */
535
536
537
            if (core)
                obuff += sizeof(INT32) + sizeof(Time);
            else
538
539
                obuff +=
                    (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
540
541
542
            ret++;
        }
    }
543

544
545
    return ret;
}
546

547
548
549
/**
 * Update the motion history for a specific device, with the list of
 * valuators.
550
551
552
553
554
 *
 * Layout of the history buffer:
 *   for SDs: [time] [val0] [val1] ... [valn]
 *   for MDs: [time] [min_val0] [max_val0] [val0] [min_val1] ... [valn]
 *
555
 * For events that have some valuators unset:
556
 *      min_val == max_val == val == 0.
557
558
 */
static void
559
updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, ValuatorMask *mask,
560
                    double *valuators)
561
562
{
    char *buff = (char *) pDev->valuator->motion;
563
564
    ValuatorClassPtr v;
    int i;
565

566
567
    if (!pDev->valuator->numMotionEvents)
        return;
568

569
    v = pDev->valuator;
570
    if (IsMaster(pDev)) {
571
        buff += ((sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(CARD32)) *
572
            v->last_motion;
573
574
575
576
577
578

        memcpy(buff, &ms, sizeof(Time));
        buff += sizeof(Time);

        memset(buff, 0, sizeof(INT32) * 3 * MAX_VALUATORS);

579
        for (i = 0; i < v->numAxes; i++) {
580
            int val;
581

582
            /* XI1 doesn't support mixed mode devices */
583
            if (valuator_get_mode(pDev, i) != valuator_get_mode(pDev, 0))
584
                break;
585
            if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i)) {
586
587
588
                buff += 3 * sizeof(INT32);
                continue;
            }
589
590
591
592
            memcpy(buff, &v->axes[i].min_value, sizeof(INT32));
            buff += sizeof(INT32);
            memcpy(buff, &v->axes[i].max_value, sizeof(INT32));
            buff += sizeof(INT32);
593
594
            val = valuators[i];
            memcpy(buff, &val, sizeof(INT32));
595
596
            buff += sizeof(INT32);
        }
597
598
    }
    else {
599
600

        buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) *
601
            pDev->valuator->last_motion;
602

603
604
        memcpy(buff, &ms, sizeof(Time));
        buff += sizeof(Time);
605

606
        memset(buff, 0, sizeof(INT32) * pDev->valuator->numAxes);
607

608
        for (i = 0; i < MAX_VALUATORS; i++) {
609
            int val;
610
611

            if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i)) {
612
613
614
                buff += sizeof(INT32);
                continue;
            }
615
616
            val = valuators[i];
            memcpy(buff, &val, sizeof(INT32));
617
618
            buff += sizeof(INT32);
        }
619
    }
Daniel Stone's avatar
Daniel Stone committed
620

621
622
    pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) %
        pDev->valuator->numMotionEvents;
623
624
625
    /* If we're wrapping around, just keep the circular buffer going. */
    if (pDev->valuator->first_motion == pDev->valuator->last_motion)
        pDev->valuator->first_motion = (pDev->valuator->first_motion + 1) %
626
            pDev->valuator->numMotionEvents;
627

628
629
    return;
}
630

631
/**
632
633
 * Returns the maximum number of events GetKeyboardEvents
 * and GetPointerEvents will ever return.
634
 *
635
 * This MUST be absolutely constant, from init until exit.
636
 */
637
int
638
639
GetMaximumEventsNum(void)
{
640
641
642
    /* One raw event
     * One device event
     * One possible device changed event
643
644
     * Lots of possible separate button scroll events (horiz + vert)
     * Lots of possible separate raw button scroll events (horiz + vert)
645
     */
646
    return 100;
647
648
}

649
/**
650
651
 * Clip an axis to its bounds, which are declared in the call to
 * InitValuatorAxisClassStruct.
652
653
 */
static void
654
clipAxis(DeviceIntPtr pDev, int axisNum, double *val)
655
{
656
    AxisInfoPtr axis;
657

658
659
660
    if (axisNum >= pDev->valuator->numAxes)
        return;

661
662
    axis = pDev->valuator->axes + axisNum;

663
664
    /* If a value range is defined, clip. If not, do nothing */
    if (axis->max_value <= axis->min_value)
665
        return;
666

667
    if (*val < axis->min_value)
668
        *val = axis->min_value;
669
    if (*val > axis->max_value)
670
        *val = axis->max_value;
671
672
673
}

/**
674
 * Clip every axis in the list of valuators to its bounds.
675
676
 */
static void
677
clipValuators(DeviceIntPtr pDev, ValuatorMask *mask)
678
679
680
{
    int i;

681
    for (i = 0; i < valuator_mask_size(mask); i++)
682
        if (valuator_mask_isset(mask, i)) {
683
            double val = valuator_mask_get_double(mask, i);
684

685
            clipAxis(pDev, i, &val);
686
            valuator_mask_set_double(mask, i, val);
687
        }
688
689
}

690
691
692
693
694
/**
 * Create the DCCE event (does not update the master's device state yet, this
 * is done in the event processing).
 * Pull in the coordinates from the MD if necessary.
 *
695
 * @param events Pointer to a pre-allocated event array.
696
 * @param dev The slave device that generated an event.
697
 * @param type Either DEVCHANGE_POINTER_EVENT and/or DEVCHANGE_KEYBOARD_EVENT
698
699
700
701
 * @param num_events The current number of events, returns the number of
 *        events if a DCCE was generated.
 * @return The updated @events pointer.
 */
702
703
704
InternalEvent *
UpdateFromMaster(InternalEvent *events, DeviceIntPtr dev, int type,
                 int *num_events)
705
{
Peter Hutterer's avatar
Peter Hutterer committed
706
707
    DeviceIntPtr master;

708
709
710
711
    master =
        GetMaster(dev,
                  (type & DEVCHANGE_POINTER_EVENT) ? MASTER_POINTER :
                  MASTER_KEYBOARD);
Peter Hutterer's avatar
Peter Hutterer committed
712

713
714
715
716
    if (master && master->last.slave != dev) {
        CreateClassesChangedEvent(events, master, dev,
                                  type | DEVCHANGE_SLAVE_SWITCH);
        if (IsPointerDevice(master)) {
717
718
719
            updateSlaveDeviceCoords(master, dev);
            master->last.numValuators = dev->last.numValuators;
        }
720
        master->last.slave = dev;
721
722
723
724
725
726
727
728
729
        (*num_events)++;
        events++;
    }
    return events;
}

/**
 * Move the device's pointer to the position given in the valuators.
 *
730
731
 * @param dev The device whose pointer is to be moved.
 * @param mask Valuator data for this event.
732
733
 */
static void
734
clipAbsolute(DeviceIntPtr dev, ValuatorMask *mask)
735
736
737
{
    int i;

738
    for (i = 0; i < valuator_mask_size(mask); i++) {
739
740
741
742
743
744
745
        double val;

        if (!valuator_mask_isset(mask, i))
            continue;
        val = valuator_mask_get_double(mask, i);
        clipAxis(dev, i, &val);
        valuator_mask_set_double(mask, i, val);
746
747
748
    }
}

749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
static void
add_to_scroll_valuator(DeviceIntPtr dev, ValuatorMask *mask, int valuator, double value)
{
    double v;

    if (!valuator_mask_fetch_double(mask, valuator, &v))
        return;

    /* protect against scrolling overflow. INT_MAX for double, because
     * we'll eventually write this as 32.32 fixed point */
    if ((value > 0 && v > INT_MAX - value) || (value < 0 && v < INT_MIN - value)) {
        v = 0;

        /* reset last.scroll to avoid a button storm */
        valuator_mask_set_double(dev->last.scroll, valuator, 0);
    }
    else
        v += value;

    valuator_mask_set_double(mask, valuator, v);
}


772
773
774
/**
 * Move the device's pointer by the values given in @valuators.
 *
775
 * @param dev The device whose pointer is to be moved.
776
 * @param[in,out] mask Valuator data for this event, modified in-place.
777
778
 */
static void
779
moveRelative(DeviceIntPtr dev, ValuatorMask *mask)
780
781
{
    int i;
782
    Bool clip_xy = IsMaster(dev) || !IsFloating(dev);
783
784

    /* calc other axes, clip, drop back into valuators */
785
    for (i = 0; i < valuator_mask_size(mask); i++) {
786
        double val = dev->last.valuators[i];
787
788
789

        if (!valuator_mask_isset(mask, i))
            continue;
790
791
792

        add_to_scroll_valuator(dev, mask, i, val);

793
794
795
        /* x & y need to go over the limits to cross screens if the SD
         * isn't currently attached; otherwise, clip to screen bounds. */
        if (valuator_get_mode(dev, i) == Absolute &&
796
797
            ((i != 0 && i != 1) || clip_xy)) {
            val = valuator_mask_get_double(mask, i);
798
            clipAxis(dev, i, &val);
799
800
            valuator_mask_set_double(mask, i, val);
        }
801
802
803
804
805
806
807
    }
}

/**
 * Accelerate the data in valuators based on the device's acceleration scheme.
 *
 * @param dev The device which's pointer is to be moved.
808
 * @param valuators Valuator mask
809
810
811
 * @param ms Current time.
 */
static void
812
accelPointer(DeviceIntPtr dev, ValuatorMask *valuators, CARD32 ms)
813
814
{
    if (dev->valuator->accelScheme.AccelSchemeProc)
815
        dev->valuator->accelScheme.AccelSchemeProc(dev, valuators, ms);
816
817
}

818
819
820
821
822
/**
 * Scale from absolute screen coordinates to absolute coordinates in the
 * device's coordinate range.
 *
 * @param dev The device to scale for.
823
824
 * @param[in, out] mask The mask in desktop coordinates, modified in place
 * to contain device coordinate range.
825
826
827
828
829
830
831
 */
static void
scale_from_screen(DeviceIntPtr dev, ValuatorMask *mask)
{
    double scaled;
    ScreenPtr scr = miPointerGetScreen(dev);

832
    if (valuator_mask_isset(mask, 0)) {
833
834
        scaled = valuator_mask_get_double(mask, 0) + scr->x;
        scaled = rescaleValuatorAxis(scaled,
835
                                     NULL, dev->valuator->axes + 0,
836
                                     0, scr->width);
837
838
        valuator_mask_set_double(mask, 0, scaled);
    }
839
    if (valuator_mask_isset(mask, 1)) {
840
841
        scaled = valuator_mask_get_double(mask, 1) + scr->y;
        scaled = rescaleValuatorAxis(scaled,
842
                                     NULL, dev->valuator->axes + 1,
843
                                     0, scr->height);
844
845
846
847
        valuator_mask_set_double(mask, 1, scaled);
    }
}

848
/**
849
 * Scale from (absolute) device to screen coordinates here,
850
 *
851
852
 * The coordinates provided are always absolute. see fill_pointer_events for
 * information on coordinate systems.
853
 *
854
 * @param dev The device to be moved.
855
 * @param mask Mask of axis values for this event
856
857
858
859
 * @param[out] devx x desktop-wide coordinate in device coordinate system
 * @param[out] devy y desktop-wide coordinate in device coordinate system
 * @param[out] screenx x coordinate in desktop coordinate system
 * @param[out] screeny y coordinate in desktop coordinate system
860
 */
861
static ScreenPtr
862
scale_to_desktop(DeviceIntPtr dev, ValuatorMask *mask,
863
                 double *devx, double *devy, double *screenx, double *screeny)
864
{
865
    ScreenPtr scr = miPointerGetScreen(dev);
866
    double x, y;
867

868
    BUG_WARN(dev->valuator && dev->valuator->numAxes < 2);
869
    if (!dev->valuator || dev->valuator->numAxes < 2) {
870
871
872
873
        /* if we have no axes, last.valuators must be in screen coords
         * anyway */
        *devx = *screenx = dev->last.valuators[0];
        *devy = *screeny = dev->last.valuators[1];
874
        return scr;
875
    }
876

877
878
879
    if (valuator_mask_isset(mask, 0))
        x = valuator_mask_get_double(mask, 0);
    else
880
        x = dev->last.valuators[0];
881
882
883
    if (valuator_mask_isset(mask, 1))
        y = valuator_mask_get_double(mask, 1);
    else
884
        y = dev->last.valuators[1];
885

886
    /* scale x&y to desktop coordinates */
887
    *screenx = rescaleValuatorAxis(x, dev->valuator->axes + 0, NULL,
888
                                   screenInfo.x, screenInfo.width - 1);
889
    *screeny = rescaleValuatorAxis(y, dev->valuator->axes + 1, NULL,
890
                                   screenInfo.y, screenInfo.height - 1);
891

892
893
894
    *devx = x;
    *devy = y;

895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
    return scr;
}

/**
 * If we have HW cursors, this actually moves the visible sprite. If not, we
 * just do all the screen crossing, etc.
 *
 * We use the screen coordinates here, call miPointerSetPosition() and then
 * scale back into device coordinates (if needed). miPSP will change x/y if
 * the screen was crossed.
 *
 * The coordinates provided are always absolute. The parameter mode
 * specifies whether it was relative or absolute movement that landed us at
 * those coordinates. see fill_pointer_events for information on coordinate
 * systems.
 *
 * @param dev The device to be moved.
 * @param mode Movement mode (Absolute or Relative)
 * @param[out] mask Mask of axis values for this event, returns the
 * per-screen device coordinates after confinement
 * @param[in,out] devx x desktop-wide coordinate in device coordinate system
 * @param[in,out] devy y desktop-wide coordinate in device coordinate system
 * @param[in,out] screenx x coordinate in desktop coordinate system
 * @param[in,out] screeny y coordinate in desktop coordinate system
919
920
 * @param[out] nevents Number of barrier events added to events
 * @param[in,out] events List of events barrier events are added to
921
922
923
 */
static ScreenPtr
positionSprite(DeviceIntPtr dev, int mode, ValuatorMask *mask,
924
925
               double *devx, double *devy, double *screenx, double *screeny,
               int *nevents, InternalEvent* events)
926
927
928
929
930
931
932
933
934
935
{
    ScreenPtr scr = miPointerGetScreen(dev);
    double tmpx, tmpy;

    if (!dev->valuator || dev->valuator->numAxes < 2)
        return scr;

    tmpx = *screenx;
    tmpy = *screeny;

936
    /* miPointerSetPosition takes care of crossing screens for us, as well as
937
938
     * clipping to the current screen. Coordinates returned are in desktop
     * coord system */
939
    scr = miPointerSetPosition(dev, mode, screenx, screeny, nevents, events);
940
941
942
943
944
945

    /* If we were constrained, rescale x/y from the screen coordinates so
     * the device valuators reflect the correct position. For screen
     * crossing this doesn't matter much, the coords would be 0 or max.
     */
    if (tmpx != *screenx)