getevents.c 60.7 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 39 40

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

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

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

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

71 72 73
/* Number of motion history events to store. */
#define MOTION_HISTORY_SIZE 256

74 75 76 77
/**
 * InputEventList is the storage for input events generated by
 * QueuePointerEvents, QueueKeyboardEvents, and QueueProximityEvents.
 * This list is allocated on startup by the DIX.
78
 */
79
InternalEvent *InputEventList = NULL;
80

81
/**
82
 * Pick some arbitrary size for Xi motion history.
83
 */
84
int
85
GetMotionHistorySize(void)
86 87
{
    return MOTION_HISTORY_SIZE;
88 89
}

90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
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)
{
111
    Bool ret = FALSE;
112 113

    if (type & BUTTON_PROCESSED)
114
        ret = ret || BitIsOn(pDev->button->down, button);
115
    if (type & BUTTON_POSTED)
116
        ret = ret || BitIsOn(pDev->button->postdown, button);
117 118 119 120

    return ret;
}

Daniel Stone's avatar
Daniel Stone committed
121 122
void
set_key_down(DeviceIntPtr pDev, int key_code, int type)
123
{
Daniel Stone's avatar
Daniel Stone committed
124
    if (type == KEY_PROCESSED)
125
        SetBit(pDev->key->down, key_code);
Daniel Stone's avatar
Daniel Stone committed
126
    else
127
        SetBit(pDev->key->postdown, key_code);
128 129
}

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

Daniel Stone's avatar
Daniel Stone committed
139 140
Bool
key_is_down(DeviceIntPtr pDev, int key_code, int type)
141
{
142
    Bool ret = FALSE;
Daniel Stone's avatar
Daniel Stone committed
143 144

    if (type & KEY_PROCESSED)
145
        ret = ret || BitIsOn(pDev->key->down, key_code);
146
    if (type & KEY_POSTED)
147
        ret = ret || BitIsOn(pDev->key->postdown, key_code);
Daniel Stone's avatar
Daniel Stone committed
148 149

    return ret;
150 151 152 153 154
}

static Bool
key_autorepeats(DeviceIntPtr pDev, int key_code)
{
155 156
    return ! !(pDev->kbdfeed->ctrl.autoRepeats[key_code >> 3] &
               (1 << (key_code & 7)));
157
}
158

159
static void
160
init_event(DeviceIntPtr dev, DeviceEvent *event, Time ms)
161 162 163 164 165 166 167 168 169
{
    memset(event, 0, sizeof(DeviceEvent));
    event->header = ET_Internal;
    event->length = sizeof(DeviceEvent);
    event->time = ms;
    event->deviceid = dev->id;
    event->sourceid = dev->id;
}

170 171 172 173 174 175 176 177 178 179 180
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;
}

181
static void
182
init_raw(DeviceIntPtr dev, RawDeviceEvent *event, Time ms, int type, int detail)
183 184 185 186
{
    memset(event, 0, sizeof(RawDeviceEvent));
    event->header = ET_Internal;
    event->length = sizeof(RawDeviceEvent);
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
    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;
212
    }
213 214 215 216 217 218 219
    event->time = ms;
    event->deviceid = dev->id;
    event->sourceid = dev->id;
    event->detail.button = detail;
}

static void
220
set_raw_valuators(RawDeviceEvent *event, ValuatorMask *mask, double *data)
221 222
{
    int i;
223

224 225
    for (i = 0; i < valuator_mask_size(mask); i++) {
        if (valuator_mask_isset(mask, i)) {
226
            SetBit(event->valuators.mask, i);
227
            data[i] = valuator_mask_get_double(mask, i);
228 229
        }
    }
230 231
}

232
static void
233
set_valuators(DeviceIntPtr dev, DeviceEvent *event, ValuatorMask *mask)
234 235 236
{
    int i;

237 238
    /* 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. */
239 240
    for (i = 0; i < valuator_mask_size(mask); i++) {
        if (valuator_mask_isset(mask, i)) {
241
            SetBit(event->valuators.mask, i);
242
            if (valuator_get_mode(dev, i) == Absolute)
243
                SetBit(event->valuators.mode, i);
244
            event->valuators.data[i] = valuator_mask_get_double(mask, i);
245
        }
246 247
        else if (valuator_get_mode(dev, i) == Absolute)
            event->valuators.data[i] = dev->valuator->axisVal[i];
248
    }
249 250
}

251
void
252 253
CreateClassesChangedEvent(InternalEvent *event,
                          DeviceIntPtr master, DeviceIntPtr slave, int flags)
254
{
255
    int i;
256
    DeviceChangedEvent *dce;
257
    CARD32 ms = GetTimeInMillis();
258

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

270
    if (slave->button) {
271 272
        dce->buttons.num_buttons = slave->button->numButtons;
        for (i = 0; i < dce->buttons.num_buttons; i++)
273
            dce->buttons.names[i] = slave->button->labels[i];
274
    }
275
    if (slave->valuator) {
276
        dce->num_valuators = slave->valuator->numAxes;
277
        for (i = 0; i < dce->num_valuators; i++) {
278 279 280
            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;
281
            dce->valuators[i].mode = slave->valuator->axes[i].mode;
282
            dce->valuators[i].name = slave->valuator->axes[i].label;
283
            dce->valuators[i].scroll = slave->valuator->axes[i].scroll;
284 285
        }
    }
286
    if (slave->key) {
287 288 289
        dce->keys.min_keycode = slave->key->xkbInfo->desc->min_key_code;
        dce->keys.max_keycode = slave->key->xkbInfo->desc->max_key_code;
    }
290 291
}

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

302
    if (from && from->min_value < from->max_value) {
303 304
        fmin = from->min_value;
        fmax = from->max_value;
305
    }
306
    if (to && to->min_value < to->max_value) {
307 308
        tmin = to->min_value;
        tmax = to->max_value;
309
    }
310

311
    if (fmin == tmin && fmax == tmax)
312
        return coord;
Peter Hutterer's avatar
Peter Hutterer committed
313

314
    if (fmax == fmin)           /* avoid division by 0 */
315
        return 0.0;
Peter Hutterer's avatar
Peter Hutterer committed
316

317
    return (coord - fmin) * (tmax - tmin) / (fmax - fmin) + tmin;
318 319 320 321 322 323
}

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

334
    /* master->last.valuators[0]/[1] is in desktop-wide coords and the actual
335
     * position of the pointer */
336 337
    pDev->last.valuators[0] = master->last.valuators[0];
    pDev->last.valuators[1] = master->last.valuators[1];
338

339 340 341
    if (!pDev->valuator)
        return;

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

    /* 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.
     */
362
    if ((lastSlave = master->last.slave) && lastSlave->valuator) {
363
        for (i = 2; i < pDev->valuator->numAxes; i++) {
364
            if (i >= lastSlave->valuator->numAxes) {
365
                pDev->last.valuators[i] = 0;
366
                valuator_mask_set_double(pDev->last.scroll, i, 0);
367
            }
368
            else {
369
                double val = pDev->last.valuators[i];
370

371
                val = rescaleValuatorAxis(val, lastSlave->valuator->axes + i,
372
                                          pDev->valuator->axes + i, 0, 0);
373
                pDev->last.valuators[i] = val;
374
                valuator_mask_set_double(pDev->last.scroll, i, val);
375
            }
376 377 378
        }
    }

379 380
}

381
/**
382
 * Allocate the motion history buffer.
383
 */
384
void
385 386
AllocateMotionHistory(DeviceIntPtr pDev)
{
387
    int size;
388

389
    free(pDev->valuator->motion);
390 391 392 393

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

394 395 396 397
    /* 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))
     */
398
    if (IsMaster(pDev))
399
        size = sizeof(INT32) * 3 * MAX_VALUATORS;
400 401 402
    else {
        ValuatorClassPtr v = pDev->valuator;
        int numAxes;
403

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

    size += sizeof(Time);

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

/**
422 423 424
 * 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.
425 426
 *
 * If core is set, we only generate x/y, in INT16, scaled to screen coords.
427
 */
428
int
429
GetMotionHistory(DeviceIntPtr pDev, xTimecoord ** buff, unsigned long start,
430
                 unsigned long stop, ScreenPtr pScreen, BOOL core)
431
{
432
    char *ibuff = NULL, *obuff;
433
    int i = 0, ret = 0;
434
    int j, coord;
435
    Time current;
436

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

444
    if (!pDev->valuator || !pDev->valuator->numMotionEvents)
445
        return 0;
Daniel Stone's avatar
Daniel Stone committed
446

447 448 449
    if (core && !pScreen)
        return 0;

450
    if (IsMaster(pDev))
451 452 453 454
        size = (sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(Time);
    else
        size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);

455
    *buff = malloc(size * pDev->valuator->numMotionEvents);
456 457
    if (!(*buff))
        return 0;
458
    obuff = (char *) *buff;
459

460 461 462 463 464 465 466 467
    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));
468

469 470 471 472
        if (current > stop) {
            return ret;
        }
        else if (current >= start) {
473 474
            if (core) {
                memcpy(obuff, ibuff, sizeof(Time));     /* copy timestamp */
475

476 477
                icbuf = (INT32 *) (ibuff + sizeof(Time));
                corebuf = (INT16 *) (obuff + sizeof(Time));
478 479 480 481 482 483 484 485 486

                /* 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;
487 488
                coord =
                    rescaleValuatorAxis(coord, &from, to, 0, pScreen->width);
489 490 491 492 493 494 495 496 497 498

                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;
499 500
                coord =
                    rescaleValuatorAxis(coord, &from, to, 0, pScreen->height);
501 502
                memcpy(corebuf, &coord, sizeof(INT16));

503 504 505
            }
            else if (IsMaster(pDev)) {
                memcpy(obuff, ibuff, sizeof(Time));     /* copy timestamp */
506

507 508 509
                ocbuf = (INT32 *) (obuff + sizeof(Time));
                icbuf = (INT32 *) (ibuff + sizeof(Time));
                for (j = 0; j < MAX_VALUATORS; j++) {
510 511 512 513 514 515 516 517
                    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));

518 519 520
                    to = (j <
                          pDev->valuator->numAxes) ? &pDev->valuator->
                        axes[j] : NULL;
521 522 523 524 525 526 527 528

                    /* 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 */
529
                    coord = rescaleValuatorAxis(coord, &from, to, 0, 0);
530 531 532
                    memcpy(ocbuf, &coord, sizeof(INT32));
                    ocbuf++;
                }
533 534
            }
            else
535 536 537 538
                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 */
539 540 541
            if (core)
                obuff += sizeof(INT32) + sizeof(Time);
            else
542 543
                obuff +=
                    (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
544 545 546
            ret++;
        }
    }
547

548 549
    return ret;
}
550

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

570 571
    if (!pDev->valuator->numMotionEvents)
        return;
572

573
    v = pDev->valuator;
574
    if (IsMaster(pDev)) {
575
        buff += ((sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(CARD32)) *
576
            v->last_motion;
577 578 579 580 581 582

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

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

583
        for (i = 0; i < v->numAxes; i++) {
584
            int val;
585

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

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

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

610
        memset(buff, 0, sizeof(INT32) * pDev->valuator->numAxes);
611

612
        for (i = 0; i < MAX_VALUATORS; i++) {
613
            int val;
614 615

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

625 626
    pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) %
        pDev->valuator->numMotionEvents;
627 628 629
    /* 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) %
630
            pDev->valuator->numMotionEvents;
631

632 633
    return;
}
634

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

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

662 663 664
    if (axisNum >= pDev->valuator->numAxes)
        return;

665 666
    axis = pDev->valuator->axes + axisNum;

667 668
    /* If a value range is defined, clip. If not, do nothing */
    if (axis->max_value <= axis->min_value)
669
        return;
670

671
    if (*val < axis->min_value)
672
        *val = axis->min_value;
673
    if (*val > axis->max_value)
674
        *val = axis->max_value;
675 676 677
}

/**
678
 * Clip every axis in the list of valuators to its bounds.
679 680
 */
static void
681
clipValuators(DeviceIntPtr pDev, ValuatorMask *mask)
682 683 684
{
    int i;

685
    for (i = 0; i < valuator_mask_size(mask); i++)
686
        if (valuator_mask_isset(mask, i)) {
687
            double val = valuator_mask_get_double(mask, i);
688

689
            clipAxis(pDev, i, &val);
690
            valuator_mask_set_double(mask, i, val);
691
        }
692 693
}

694 695 696 697 698
/**
 * 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.
 *
699
 * @param events Pointer to a pre-allocated event array.
700
 * @param dev The slave device that generated an event.
701
 * @param type Either DEVCHANGE_POINTER_EVENT and/or DEVCHANGE_KEYBOARD_EVENT
702 703 704 705
 * @param num_events The current number of events, returns the number of
 *        events if a DCCE was generated.
 * @return The updated @events pointer.
 */
706 707 708
InternalEvent *
UpdateFromMaster(InternalEvent *events, DeviceIntPtr dev, int type,
                 int *num_events)
709
{
Peter Hutterer's avatar
Peter Hutterer committed
710 711
    DeviceIntPtr master;

712 713 714 715
    master =
        GetMaster(dev,
                  (type & DEVCHANGE_POINTER_EVENT) ? MASTER_POINTER :
                  MASTER_KEYBOARD);
Peter Hutterer's avatar
Peter Hutterer committed
716

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

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

742
    for (i = 0; i < valuator_mask_size(mask); i++) {
743 744 745 746 747 748 749
        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);
750 751 752 753 754 755
    }
}

/**
 * Move the device's pointer by the values given in @valuators.
 *
756
 * @param dev The device whose pointer is to be moved.
757
 * @param[in,out] mask Valuator data for this event, modified in-place.
758 759
 */
static void
760
moveRelative(DeviceIntPtr dev, ValuatorMask *mask)
761 762
{
    int i;
763
    Bool clip_xy = IsMaster(dev) || !IsFloating(dev);
764 765

    /* calc other axes, clip, drop back into valuators */
766
    for (i = 0; i < valuator_mask_size(mask); i++) {
767
        double val = dev->last.valuators[i];
768 769 770 771 772 773 774 775 776 777

        if (!valuator_mask_isset(mask, i))
            continue;
        val += valuator_mask_get_double(mask, i);
        /* 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 &&
            ((i != 0 && i != 1) || clip_xy))
            clipAxis(dev, i, &val);
        valuator_mask_set_double(mask, i, val);
778 779 780 781 782 783 784
    }
}

/**
 * Accelerate the data in valuators based on the device's acceleration scheme.
 *
 * @param dev The device which's pointer is to be moved.
785
 * @param valuators Valuator mask
786 787 788
 * @param ms Current time.
 */
static void
789
accelPointer(DeviceIntPtr dev, ValuatorMask *valuators, CARD32 ms)
790 791
{
    if (dev->valuator->accelScheme.AccelSchemeProc)
792
        dev->valuator->accelScheme.AccelSchemeProc(dev, valuators, ms);
793 794
}

795 796 797 798 799
/**
 * Scale from absolute screen coordinates to absolute coordinates in the
 * device's coordinate range.
 *
 * @param dev The device to scale for.
800 801
 * @param[in, out] mask The mask in desktop coordinates, modified in place
 * to contain device coordinate range.
802 803 804 805 806 807 808
 */
static void
scale_from_screen(DeviceIntPtr dev, ValuatorMask *mask)
{
    double scaled;
    ScreenPtr scr = miPointerGetScreen(dev);

809
    if (valuator_mask_isset(mask, 0)) {
810 811
        scaled = valuator_mask_get_double(mask, 0) + scr->x;
        scaled = rescaleValuatorAxis(scaled,
812
                                     NULL, dev->valuator->axes + 0,
813
                                     0, scr->width);
814 815
        valuator_mask_set_double(mask, 0, scaled);
    }
816
    if (valuator_mask_isset(mask, 1)) {
817 818
        scaled = valuator_mask_get_double(mask, 1) + scr->y;
        scaled = rescaleValuatorAxis(scaled,
819
                                     NULL, dev->valuator->axes + 1,
820
                                     0, scr->height);
821 822 823 824
        valuator_mask_set_double(mask, 1, scaled);
    }
}

825
/**
826
 * Scale from (absolute) device to screen coordinates here,
827
 *
828 829
 * The coordinates provided are always absolute. see fill_pointer_events for
 * information on coordinate systems.
830
 *
831
 * @param dev The device to be moved.
832
 * @param mask Mask of axis values for this event
833 834 835 836
 * @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
837
 */
838
static ScreenPtr
839
scale_to_desktop(DeviceIntPtr dev, ValuatorMask *mask,
840
                 double *devx, double *devy, double *screenx, double *screeny)
841
{
842
    ScreenPtr scr = miPointerGetScreen(dev);
843
    double x, y;
844

845
    BUG_WARN(dev->valuator && dev->valuator->numAxes < 2);
846
    if (!dev->valuator || dev->valuator->numAxes < 2) {
847 848 849 850
        /* 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];
851
        return scr;
852
    }
853

854 855 856
    if (valuator_mask_isset(mask, 0))
        x = valuator_mask_get_double(mask, 0);
    else
857
        x = dev->last.valuators[0];
858 859 860
    if (valuator_mask_isset(mask, 1))
        y = valuator_mask_get_double(mask, 1);
    else
861
        y = dev->last.valuators[1];
862

863
    /* scale x&y to desktop coordinates */
864
    *screenx = rescaleValuatorAxis(x, dev->valuator->axes + 0, NULL,
865
                                   screenInfo.x, screenInfo.width);
866
    *screeny = rescaleValuatorAxis(y, dev->valuator->axes + 1, NULL,
867
                                   screenInfo.y, screenInfo.height);
868

869 870 871
    *devx = x;
    *devy = y;

872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898
    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
 */
static ScreenPtr
positionSprite(DeviceIntPtr dev, int mode, ValuatorMask *mask,
899
               double *devx, double *devy, double *screenx, double *screeny)
900 901 902 903 904 905 906 907 908 909
{
    ScreenPtr scr = miPointerGetScreen(dev);
    double tmpx, tmpy;

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

    tmpx = *screenx;
    tmpy = *screeny;

910
    /* miPointerSetPosition takes care of crossing screens for us, as well as
911 912
     * clipping to the current screen. Coordinates returned are in desktop
     * coord system */
913 914 915 916 917 918 919
    scr = miPointerSetPosition(dev, mode, screenx, screeny);

    /* 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)
920 921
        *devx = rescaleValuatorAxis(*screenx, NULL, dev->valuator->axes + 0,
                                    screenInfo.x, screenInfo.width);
922

923 924 925
    if (tmpy != *screeny)
        *devy = rescaleValuatorAxis(*screeny, NULL, dev->valuator->axes + 1,
                                    screenInfo.y, screenInfo.height);
926

927 928
    /* Recalculate the per-screen device coordinates */
    if (valuator_mask_isset(mask, 0)) {
929
        double x;
930 931 932

        x = rescaleValuatorAxis(*screenx - scr->x, NULL,
                                dev->valuator->axes + 0, 0, scr->width);
933
        valuator_mask_set_double(mask, 0, x);
934 935
    }
    if (valuator_mask_isset(mask, 1)) {
936
        double y;
937 938 939

        y = rescaleValuatorAxis(*screeny - scr->y, NULL,
                                dev->valuator->axes + 1, 0, scr->height);
940
        valuator_mask_set_double(mask, 1, y);
941
    }
942 943

    return scr;
944 945 946 947 948 949
}

/**
 * Update the motion history for the device and (if appropriate) for its
 * master device.
 * @param dev Slave device to update.
950
 * @param mask Bit mask of valid valuators to append to history.
951 952 953 954
 * @param num Total number of valuators to append to history.
 * @param ms Current time
 */
static void
955
updateHistory(DeviceIntPtr dev, ValuatorMask *mask, CARD32 ms)
956
{
957 958 959
    if (!dev->valuator)
        return;

960
    updateMotionHistory(dev, ms, mask, dev->last.valuators);
961
    if (!IsMaster(dev) && !IsFloating(dev)) {
Peter Hutterer's avatar
Peter Hutterer committed
962
        DeviceIntPtr master = GetMaster(dev, MASTER_POINTER);
963

964
        updateMotionHistory(master, ms, mask, dev->last.valuators);