getevents.c revision 65b04b38
105b261ecSmrg/*
205b261ecSmrg * Copyright © 2006 Nokia Corporation
305b261ecSmrg * Copyright © 2006-2007 Daniel Stone
44202a189Smrg * Copyright © 2008 Red Hat, Inc.
505b261ecSmrg *
605b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a
705b261ecSmrg * copy of this software and associated documentation files (the "Software"),
805b261ecSmrg * to deal in the Software without restriction, including without limitation
905b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1005b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the
1105b261ecSmrg * Software is furnished to do so, subject to the following conditions:
1205b261ecSmrg *
1305b261ecSmrg * The above copyright notice and this permission notice (including the next
1405b261ecSmrg * paragraph) shall be included in all copies or substantial portions of the
1505b261ecSmrg * Software.
1605b261ecSmrg *
1705b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1805b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1905b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2005b261ecSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2105b261ecSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2205b261ecSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2305b261ecSmrg * DEALINGS IN THE SOFTWARE.
2405b261ecSmrg *
254202a189Smrg * Authors: Daniel Stone <daniel@fooishbar.org>
264202a189Smrg *          Peter Hutterer <peter.hutterer@who-t.net>
2705b261ecSmrg */
2805b261ecSmrg
2905b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
3005b261ecSmrg#include <dix-config.h>
3105b261ecSmrg#endif
3205b261ecSmrg
3305b261ecSmrg#include <X11/X.h>
3405b261ecSmrg#include <X11/keysym.h>
3505b261ecSmrg#include <X11/Xproto.h>
364202a189Smrg#include <math.h>
3705b261ecSmrg
3805b261ecSmrg#include "misc.h"
3905b261ecSmrg#include "resource.h"
4005b261ecSmrg#include "inputstr.h"
4105b261ecSmrg#include "scrnintstr.h"
4205b261ecSmrg#include "cursorstr.h"
4305b261ecSmrg#include "dixstruct.h"
4405b261ecSmrg#include "globals.h"
4505b261ecSmrg#include "dixevents.h"
4605b261ecSmrg#include "mipointer.h"
474202a189Smrg#include "eventstr.h"
484202a189Smrg#include "eventconvert.h"
4965b04b38Smrg#include "inpututils.h"
5005b261ecSmrg
5105b261ecSmrg#include <X11/extensions/XKBproto.h>
524202a189Smrg#include "xkbsrv.h"
5305b261ecSmrg
5405b261ecSmrg#ifdef PANORAMIX
5505b261ecSmrg#include "panoramiX.h"
5605b261ecSmrg#include "panoramiXsrv.h"
5705b261ecSmrg#endif
5805b261ecSmrg
5905b261ecSmrg#include <X11/extensions/XI.h>
6005b261ecSmrg#include <X11/extensions/XIproto.h>
614202a189Smrg#include <pixman.h>
6205b261ecSmrg#include "exglobals.h"
6305b261ecSmrg#include "exevents.h"
6405b261ecSmrg#include "exglobals.h"
6505b261ecSmrg#include "extnsionst.h"
664202a189Smrg#include "listdev.h" /* for sizing up DeviceClassesChangedEvent */
6705b261ecSmrg
6805b261ecSmrg/* Number of motion history events to store. */
6905b261ecSmrg#define MOTION_HISTORY_SIZE 256
7005b261ecSmrg
714642e01fSmrg/* InputEventList is the container list for all input events generated by the
724642e01fSmrg * DDX. The DDX is expected to call GetEventList() and then pass the list into
734642e01fSmrg * Get{Pointer|Keyboard}Events.
744642e01fSmrg */
754642e01fSmrgEventListPtr InputEventList = NULL;
764642e01fSmrgint InputEventListLen = 0;
774642e01fSmrg
784202a189Smrgint
794642e01fSmrgGetEventList(EventListPtr* list)
804642e01fSmrg{
814642e01fSmrg    *list = InputEventList;
824642e01fSmrg    return InputEventListLen;
834642e01fSmrg}
8405b261ecSmrg
8505b261ecSmrg/**
8605b261ecSmrg * Pick some arbitrary size for Xi motion history.
8705b261ecSmrg */
884202a189Smrgint
8905b261ecSmrgGetMotionHistorySize(void)
9005b261ecSmrg{
9105b261ecSmrg    return MOTION_HISTORY_SIZE;
9205b261ecSmrg}
9305b261ecSmrg
944202a189Smrgvoid
954202a189Smrgset_button_down(DeviceIntPtr pDev, int button, int type)
9605b261ecSmrg{
974202a189Smrg    if (type == BUTTON_PROCESSED)
984202a189Smrg        SetBit(pDev->button->down, button);
994202a189Smrg    else
1004202a189Smrg        SetBit(pDev->button->postdown, button);
10105b261ecSmrg}
10205b261ecSmrg
1034202a189Smrgvoid
1044202a189Smrgset_button_up(DeviceIntPtr pDev, int button, int type)
10505b261ecSmrg{
1064202a189Smrg    if (type == BUTTON_PROCESSED)
1074202a189Smrg        ClearBit(pDev->button->down, button);
1084202a189Smrg    else
1094202a189Smrg        ClearBit(pDev->button->postdown, button);
11005b261ecSmrg}
11105b261ecSmrg
1124202a189SmrgBool
1134202a189Smrgbutton_is_down(DeviceIntPtr pDev, int button, int type)
1144202a189Smrg{
1151b684552Smrg    Bool ret = FALSE;
1164202a189Smrg
1174202a189Smrg    if (type & BUTTON_PROCESSED)
1181b684552Smrg        ret = ret || BitIsOn(pDev->button->down, button);
1194202a189Smrg    if (type & BUTTON_POSTED)
1201b684552Smrg        ret = ret || BitIsOn(pDev->button->postdown, button);
1214202a189Smrg
1224202a189Smrg    return ret;
1234202a189Smrg}
1244202a189Smrg
1254202a189Smrgvoid
1264202a189Smrgset_key_down(DeviceIntPtr pDev, int key_code, int type)
12705b261ecSmrg{
1284202a189Smrg    if (type == KEY_PROCESSED)
1294202a189Smrg        SetBit(pDev->key->down, key_code);
1304202a189Smrg    else
1314202a189Smrg        SetBit(pDev->key->postdown, key_code);
1324202a189Smrg}
1334202a189Smrg
1344202a189Smrgvoid
1354202a189Smrgset_key_up(DeviceIntPtr pDev, int key_code, int type)
1364202a189Smrg{
1374202a189Smrg    if (type == KEY_PROCESSED)
1384202a189Smrg        ClearBit(pDev->key->down, key_code);
1394202a189Smrg    else
1404202a189Smrg        ClearBit(pDev->key->postdown, key_code);
1414202a189Smrg}
1424202a189Smrg
1434202a189SmrgBool
1444202a189Smrgkey_is_down(DeviceIntPtr pDev, int key_code, int type)
1454202a189Smrg{
1461b684552Smrg    Bool ret = FALSE;
1474202a189Smrg
1484202a189Smrg    if (type & KEY_PROCESSED)
1491b684552Smrg        ret = ret || BitIsOn(pDev->key->down, key_code);
1504202a189Smrg    if (type & KEY_POSTED)
1511b684552Smrg        ret = ret || BitIsOn(pDev->key->postdown, key_code);
1524202a189Smrg
1534202a189Smrg    return ret;
15405b261ecSmrg}
15505b261ecSmrg
15605b261ecSmrgstatic Bool
15705b261ecSmrgkey_autorepeats(DeviceIntPtr pDev, int key_code)
15805b261ecSmrg{
15905b261ecSmrg    return !!(pDev->kbdfeed->ctrl.autoRepeats[key_code >> 3] &
16005b261ecSmrg              (1 << (key_code & 7)));
16105b261ecSmrg}
16205b261ecSmrg
1634202a189Smrgstatic void
1644202a189Smrginit_event(DeviceIntPtr dev, DeviceEvent* event, Time ms)
1654202a189Smrg{
1664202a189Smrg    memset(event, 0, sizeof(DeviceEvent));
1674202a189Smrg    event->header = ET_Internal;
1684202a189Smrg    event->length = sizeof(DeviceEvent);
1694202a189Smrg    event->time = ms;
1704202a189Smrg    event->deviceid = dev->id;
1714202a189Smrg    event->sourceid = dev->id;
1724202a189Smrg}
1734202a189Smrg
1744202a189Smrgstatic void
1754202a189Smrginit_raw(DeviceIntPtr dev, RawDeviceEvent *event, Time ms, int type, int detail)
1764202a189Smrg{
1774202a189Smrg    memset(event, 0, sizeof(RawDeviceEvent));
1784202a189Smrg    event->header = ET_Internal;
1794202a189Smrg    event->length = sizeof(RawDeviceEvent);
1804202a189Smrg    event->type = ET_RawKeyPress - ET_KeyPress + type;
1814202a189Smrg    event->time = ms;
1824202a189Smrg    event->deviceid = dev->id;
1834202a189Smrg    event->sourceid = dev->id;
1844202a189Smrg    event->detail.button = detail;
1854202a189Smrg}
1864202a189Smrg
1874202a189Smrgstatic void
18865b04b38Smrgset_raw_valuators(RawDeviceEvent *event, ValuatorMask *mask, int32_t* data)
1894202a189Smrg{
1904202a189Smrg    int i;
1914202a189Smrg
19265b04b38Smrg    for (i = 0; i < valuator_mask_size(mask); i++)
19365b04b38Smrg    {
19465b04b38Smrg        if (valuator_mask_isset(mask, i))
19565b04b38Smrg        {
19665b04b38Smrg            SetBit(event->valuators.mask, i);
19765b04b38Smrg            data[i] = valuator_mask_get(mask, i);
19865b04b38Smrg        }
19965b04b38Smrg    }
2004202a189Smrg}
2014202a189Smrg
2024202a189Smrg
2034202a189Smrgstatic void
20465b04b38Smrgset_valuators(DeviceIntPtr dev, DeviceEvent* event, ValuatorMask *mask)
2054202a189Smrg{
2064202a189Smrg    int i;
2074202a189Smrg
20865b04b38Smrg    /* Set the data to the previous value for unset absolute axes. The values
20965b04b38Smrg     * may be used when sent as part of an XI 1.x valuator event. */
21065b04b38Smrg    for (i = 0; i < valuator_mask_size(mask); i++)
2114202a189Smrg    {
21265b04b38Smrg        if (valuator_mask_isset(mask, i))
21365b04b38Smrg        {
21465b04b38Smrg            SetBit(event->valuators.mask, i);
21565b04b38Smrg            if (valuator_get_mode(dev, i) == Absolute)
21665b04b38Smrg                SetBit(event->valuators.mode, i);
21765b04b38Smrg            event->valuators.data[i] = valuator_mask_get(mask, i);
21865b04b38Smrg            event->valuators.data_frac[i] =
21965b04b38Smrg                dev->last.remainder[i] * (1 << 16) * (1 << 16);
22065b04b38Smrg        }
22165b04b38Smrg        else if (valuator_get_mode(dev, i) == Absolute)
22265b04b38Smrg            event->valuators.data[i] = dev->valuator->axisVal[i];
2234202a189Smrg    }
2244202a189Smrg}
2254202a189Smrg
2264202a189Smrgvoid
2274202a189SmrgCreateClassesChangedEvent(EventList* event,
2284202a189Smrg                          DeviceIntPtr master,
2294202a189Smrg                          DeviceIntPtr slave,
2304202a189Smrg                          int type)
2314202a189Smrg{
2324202a189Smrg    int i;
2334202a189Smrg    DeviceChangedEvent *dce;
2344202a189Smrg    CARD32 ms = GetTimeInMillis();
2354202a189Smrg
2364202a189Smrg    dce = (DeviceChangedEvent*)event->event;
2374202a189Smrg    memset(dce, 0, sizeof(DeviceChangedEvent));
2384202a189Smrg    dce->deviceid = slave->id;
2394202a189Smrg    dce->masterid = master->id;
2404202a189Smrg    dce->header = ET_Internal;
2414202a189Smrg    dce->length = sizeof(DeviceChangedEvent);
2424202a189Smrg    dce->type = ET_DeviceChanged;
2434202a189Smrg    dce->time = ms;
2444202a189Smrg    dce->flags = type;
2454202a189Smrg    dce->flags |= DEVCHANGE_SLAVE_SWITCH;
2464202a189Smrg    dce->sourceid = slave->id;
2474202a189Smrg
2484202a189Smrg    if (slave->button)
2494202a189Smrg    {
2504202a189Smrg        dce->buttons.num_buttons = slave->button->numButtons;
2514202a189Smrg        for (i = 0; i < dce->buttons.num_buttons; i++)
2524202a189Smrg            dce->buttons.names[i] = slave->button->labels[i];
2534202a189Smrg    }
2544202a189Smrg    if (slave->valuator)
2554202a189Smrg    {
2564202a189Smrg        dce->num_valuators = slave->valuator->numAxes;
2574202a189Smrg        for (i = 0; i < dce->num_valuators; i++)
2584202a189Smrg        {
2594202a189Smrg            dce->valuators[i].min = slave->valuator->axes[i].min_value;
2604202a189Smrg            dce->valuators[i].max = slave->valuator->axes[i].max_value;
2614202a189Smrg            dce->valuators[i].resolution = slave->valuator->axes[i].resolution;
26265b04b38Smrg            dce->valuators[i].mode = slave->valuator->axes[i].mode;
2634202a189Smrg            dce->valuators[i].name = slave->valuator->axes[i].label;
2644202a189Smrg        }
2654202a189Smrg    }
2664202a189Smrg    if (slave->key)
2674202a189Smrg    {
2684202a189Smrg        dce->keys.min_keycode = slave->key->xkbInfo->desc->min_key_code;
2694202a189Smrg        dce->keys.max_keycode = slave->key->xkbInfo->desc->max_key_code;
2704202a189Smrg    }
2714202a189Smrg}
2724202a189Smrg
2734642e01fSmrg/**
2744642e01fSmrg * Rescale the coord between the two axis ranges.
2754642e01fSmrg */
2764642e01fSmrgstatic int
2774202a189SmrgrescaleValuatorAxis(int coord, float remainder, float *remainder_return, AxisInfoPtr from, AxisInfoPtr to,
2784642e01fSmrg                    int defmax)
2794642e01fSmrg{
2804202a189Smrg    int fmin = 0, tmin = 0, fmax = defmax, tmax = defmax, coord_return;
2814202a189Smrg    float value;
2824642e01fSmrg
2834642e01fSmrg    if(from && from->min_value < from->max_value) {
2844642e01fSmrg        fmin = from->min_value;
2854642e01fSmrg        fmax = from->max_value;
2864642e01fSmrg    }
2874642e01fSmrg    if(to && to->min_value < to->max_value) {
2884642e01fSmrg        tmin = to->min_value;
2894642e01fSmrg        tmax = to->max_value;
2904642e01fSmrg    }
2914642e01fSmrg
2924202a189Smrg    if(fmin == tmin && fmax == tmax) {
2934202a189Smrg        if (remainder_return)
2944202a189Smrg            *remainder_return = remainder;
2954642e01fSmrg        return coord;
2964202a189Smrg    }
2974642e01fSmrg
2984202a189Smrg    if(fmax == fmin) { /* avoid division by 0 */
2994202a189Smrg        if (remainder_return)
3004202a189Smrg            *remainder_return = 0.0;
3014642e01fSmrg        return 0;
3024202a189Smrg    }
3034642e01fSmrg
3044202a189Smrg    value = (coord + remainder - fmin) * (tmax - tmin) / (fmax - fmin) + tmin;
3054202a189Smrg    coord_return = lroundf(value);
3064202a189Smrg    if (remainder_return)
3074202a189Smrg        *remainder_return = value - coord_return;
3084202a189Smrg    return coord_return;
3094642e01fSmrg}
3104642e01fSmrg
3114642e01fSmrg/**
3124642e01fSmrg * Update all coordinates when changing to a different SD
3134642e01fSmrg * to ensure that relative reporting will work as expected
3144642e01fSmrg * without loss of precision.
3154642e01fSmrg *
3164642e01fSmrg * pDev->last.valuators will be in absolute device coordinates after this
3174642e01fSmrg * function.
3184642e01fSmrg */
3194642e01fSmrgstatic void
3204642e01fSmrgupdateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
3214642e01fSmrg{
3224642e01fSmrg    ScreenPtr scr = miPointerGetScreen(pDev);
3234642e01fSmrg    int i;
3244642e01fSmrg    DeviceIntPtr lastSlave;
3254642e01fSmrg
3264642e01fSmrg    /* master->last.valuators[0]/[1] is in screen coords and the actual
3274642e01fSmrg     * position of the pointer */
3284642e01fSmrg    pDev->last.valuators[0] = master->last.valuators[0];
3294642e01fSmrg    pDev->last.valuators[1] = master->last.valuators[1];
3304642e01fSmrg
3314642e01fSmrg    if (!pDev->valuator)
3324642e01fSmrg        return;
3334642e01fSmrg
3344642e01fSmrg    /* scale back to device coordinates */
3354642e01fSmrg    if(pDev->valuator->numAxes > 0)
3364202a189Smrg        pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0], pDev->last.remainder[0],
3374202a189Smrg                        &pDev->last.remainder[0], NULL, pDev->valuator->axes + 0, scr->width);
3384642e01fSmrg    if(pDev->valuator->numAxes > 1)
3394202a189Smrg        pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1], pDev->last.remainder[1],
3404202a189Smrg                        &pDev->last.remainder[1], NULL, pDev->valuator->axes + 1, scr->height);
3414642e01fSmrg
3424642e01fSmrg    /* calculate the other axis as well based on info from the old
3434642e01fSmrg     * slave-device. If the old slave had less axes than this one,
3444642e01fSmrg     * last.valuators is reset to 0.
3454642e01fSmrg     */
3464202a189Smrg    if ((lastSlave = master->last.slave) && lastSlave->valuator) {
3474642e01fSmrg        for (i = 2; i < pDev->valuator->numAxes; i++) {
3484642e01fSmrg            if (i >= lastSlave->valuator->numAxes)
3494642e01fSmrg                pDev->last.valuators[i] = 0;
3504642e01fSmrg            else
3514642e01fSmrg                pDev->last.valuators[i] =
3524642e01fSmrg                    rescaleValuatorAxis(pDev->last.valuators[i],
3534202a189Smrg                            pDev->last.remainder[i],
3544202a189Smrg                            &pDev->last.remainder[i],
3554642e01fSmrg                            lastSlave->valuator->axes + i,
3564642e01fSmrg                            pDev->valuator->axes + i, 0);
3574642e01fSmrg        }
3584642e01fSmrg    }
3594642e01fSmrg
3604642e01fSmrg}
3614642e01fSmrg
36205b261ecSmrg/**
36305b261ecSmrg * Allocate the motion history buffer.
36405b261ecSmrg */
3654202a189Smrgvoid
36605b261ecSmrgAllocateMotionHistory(DeviceIntPtr pDev)
36705b261ecSmrg{
3684642e01fSmrg    int size;
3694202a189Smrg    free(pDev->valuator->motion);
37005b261ecSmrg
37105b261ecSmrg    if (pDev->valuator->numMotionEvents < 1)
37205b261ecSmrg        return;
37305b261ecSmrg
3744642e01fSmrg    /* An MD must have a motion history size large enough to keep all
3754642e01fSmrg     * potential valuators, plus the respective range of the valuators.
3764642e01fSmrg     * 3 * INT32 for (min_val, max_val, curr_val))
3774642e01fSmrg     */
3784202a189Smrg    if (IsMaster(pDev))
3794642e01fSmrg        size = sizeof(INT32) * 3 * MAX_VALUATORS;
38065b04b38Smrg    else {
38165b04b38Smrg        ValuatorClassPtr v = pDev->valuator;
38265b04b38Smrg        int numAxes;
38365b04b38Smrg        /* XI1 doesn't understand mixed mode devices */
38465b04b38Smrg        for (numAxes = 0; numAxes < v->numAxes; numAxes++)
38565b04b38Smrg            if (valuator_get_mode(pDev, numAxes) != valuator_get_mode(pDev, 0))
38665b04b38Smrg                break;
38765b04b38Smrg        size = sizeof(INT32) * numAxes;
38865b04b38Smrg    }
3894642e01fSmrg
3904642e01fSmrg    size += sizeof(Time);
3914642e01fSmrg
3924202a189Smrg    pDev->valuator->motion = calloc(pDev->valuator->numMotionEvents, size);
39305b261ecSmrg    pDev->valuator->first_motion = 0;
39405b261ecSmrg    pDev->valuator->last_motion = 0;
3954642e01fSmrg    if (!pDev->valuator->motion)
3964642e01fSmrg        ErrorF("[dix] %s: Failed to alloc motion history (%d bytes).\n",
3974642e01fSmrg                pDev->name, size * pDev->valuator->numMotionEvents);
39805b261ecSmrg}
39905b261ecSmrg
40005b261ecSmrg/**
40105b261ecSmrg * Dump the motion history between start and stop into the supplied buffer.
40205b261ecSmrg * Only records the event for a given screen in theory, but in practice, we
40305b261ecSmrg * sort of ignore this.
4044642e01fSmrg *
4054642e01fSmrg * If core is set, we only generate x/y, in INT16, scaled to screen coords.
40605b261ecSmrg */
4074202a189Smrgint
4084642e01fSmrgGetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
4094642e01fSmrg                 unsigned long stop, ScreenPtr pScreen, BOOL core)
41005b261ecSmrg{
4114642e01fSmrg    char *ibuff = NULL, *obuff;
41205b261ecSmrg    int i = 0, ret = 0;
4134642e01fSmrg    int j, coord;
41405b261ecSmrg    Time current;
41505b261ecSmrg    /* The size of a single motion event. */
4164642e01fSmrg    int size;
4174642e01fSmrg    int dflt;
4184642e01fSmrg    AxisInfo from, *to; /* for scaling */
4194642e01fSmrg    INT32 *ocbuf, *icbuf; /* pointer to coordinates for copying */
4204642e01fSmrg    INT16 *corebuf;
4214642e01fSmrg    AxisInfo core_axis = {0};
42205b261ecSmrg
42305b261ecSmrg    if (!pDev->valuator || !pDev->valuator->numMotionEvents)
42405b261ecSmrg        return 0;
42505b261ecSmrg
4264642e01fSmrg    if (core && !pScreen)
4274642e01fSmrg        return 0;
4284642e01fSmrg
4294202a189Smrg    if (IsMaster(pDev))
4304642e01fSmrg        size = (sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(Time);
4314642e01fSmrg    else
4324642e01fSmrg        size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
4334642e01fSmrg
4344202a189Smrg    *buff = malloc(size * pDev->valuator->numMotionEvents);
4354642e01fSmrg    if (!(*buff))
4364642e01fSmrg        return 0;
4374642e01fSmrg    obuff = (char *)*buff;
4384642e01fSmrg
43905b261ecSmrg    for (i = pDev->valuator->first_motion;
44005b261ecSmrg         i != pDev->valuator->last_motion;
44105b261ecSmrg         i = (i + 1) % pDev->valuator->numMotionEvents) {
44205b261ecSmrg        /* We index the input buffer by which element we're accessing, which
44305b261ecSmrg         * is not monotonic, and the output buffer by how many events we've
44405b261ecSmrg         * written so far. */
44505b261ecSmrg        ibuff = (char *) pDev->valuator->motion + (i * size);
44605b261ecSmrg        memcpy(&current, ibuff, sizeof(Time));
44705b261ecSmrg
44805b261ecSmrg        if (current > stop) {
44905b261ecSmrg            return ret;
45005b261ecSmrg        }
45105b261ecSmrg        else if (current >= start) {
4524642e01fSmrg            if (core)
4534642e01fSmrg            {
4544642e01fSmrg                memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */
4554642e01fSmrg
4564642e01fSmrg                icbuf = (INT32*)(ibuff + sizeof(Time));
4574642e01fSmrg                corebuf = (INT16*)(obuff + sizeof(Time));
4584642e01fSmrg
4594642e01fSmrg                /* fetch x coordinate + range */
4604642e01fSmrg                memcpy(&from.min_value, icbuf++, sizeof(INT32));
4614642e01fSmrg                memcpy(&from.max_value, icbuf++, sizeof(INT32));
4624642e01fSmrg                memcpy(&coord, icbuf++, sizeof(INT32));
4634642e01fSmrg
4644642e01fSmrg                /* scale to screen coords */
4654642e01fSmrg                to = &core_axis;
4664642e01fSmrg                to->max_value = pScreen->width;
4674202a189Smrg                coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->width);
4684642e01fSmrg
4694642e01fSmrg                memcpy(corebuf, &coord, sizeof(INT16));
4704642e01fSmrg                corebuf++;
4714642e01fSmrg
4724642e01fSmrg                /* fetch y coordinate + range */
4734642e01fSmrg                memcpy(&from.min_value, icbuf++, sizeof(INT32));
4744642e01fSmrg                memcpy(&from.max_value, icbuf++, sizeof(INT32));
4754642e01fSmrg                memcpy(&coord, icbuf++, sizeof(INT32));
4764642e01fSmrg
4774642e01fSmrg                to->max_value = pScreen->height;
4784202a189Smrg                coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->height);
4794642e01fSmrg                memcpy(corebuf, &coord, sizeof(INT16));
4804642e01fSmrg
4814202a189Smrg            } else if (IsMaster(pDev))
4824642e01fSmrg            {
4834642e01fSmrg                memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */
4844642e01fSmrg
4854642e01fSmrg                ocbuf = (INT32*)(obuff + sizeof(Time));
4864642e01fSmrg                icbuf = (INT32*)(ibuff + sizeof(Time));
4874642e01fSmrg                for (j = 0; j < MAX_VALUATORS; j++)
4884642e01fSmrg                {
4894642e01fSmrg                    if (j >= pDev->valuator->numAxes)
4904642e01fSmrg                        break;
4914642e01fSmrg
4924642e01fSmrg                    /* fetch min/max/coordinate */
4934642e01fSmrg                    memcpy(&from.min_value, icbuf++, sizeof(INT32));
4944642e01fSmrg                    memcpy(&from.max_value, icbuf++, sizeof(INT32));
4954642e01fSmrg                    memcpy(&coord, icbuf++, sizeof(INT32));
4964642e01fSmrg
4974642e01fSmrg                    to = (j < pDev->valuator->numAxes) ? &pDev->valuator->axes[j] : NULL;
4984642e01fSmrg
4994642e01fSmrg                    /* x/y scaled to screen if no range is present */
5004642e01fSmrg                    if (j == 0 && (from.max_value < from.min_value))
5014642e01fSmrg                        from.max_value = pScreen->width;
5024642e01fSmrg                    else if (j == 1 && (from.max_value < from.min_value))
5034642e01fSmrg                        from.max_value = pScreen->height;
5044642e01fSmrg
5054642e01fSmrg                    if (j == 0 && (to->max_value < to->min_value))
5064642e01fSmrg                        dflt = pScreen->width;
5074642e01fSmrg                    else if (j == 1 && (to->max_value < to->min_value))
5084642e01fSmrg                        dflt = pScreen->height;
5094642e01fSmrg                    else
5104642e01fSmrg                        dflt = 0;
5114642e01fSmrg
5124642e01fSmrg                    /* scale from stored range into current range */
5134202a189Smrg                    coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, 0);
5144642e01fSmrg                    memcpy(ocbuf, &coord, sizeof(INT32));
5154642e01fSmrg                    ocbuf++;
5164642e01fSmrg                }
5174642e01fSmrg            } else
5184642e01fSmrg                memcpy(obuff, ibuff, size);
5194642e01fSmrg
5204642e01fSmrg            /* don't advance by size here. size may be different to the
5214642e01fSmrg             * actually written size if the MD has less valuators than MAX */
5224642e01fSmrg            if (core)
5234642e01fSmrg                obuff += sizeof(INT32) + sizeof(Time);
5244642e01fSmrg            else
5254642e01fSmrg                obuff += (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
52605b261ecSmrg            ret++;
52705b261ecSmrg        }
52805b261ecSmrg    }
52905b261ecSmrg
53005b261ecSmrg    return ret;
53105b261ecSmrg}
53205b261ecSmrg
53305b261ecSmrg
53405b261ecSmrg/**
53505b261ecSmrg * Update the motion history for a specific device, with the list of
53605b261ecSmrg * valuators.
5374642e01fSmrg *
5384642e01fSmrg * Layout of the history buffer:
5394642e01fSmrg *   for SDs: [time] [val0] [val1] ... [valn]
5404642e01fSmrg *   for MDs: [time] [min_val0] [max_val0] [val0] [min_val1] ... [valn]
5414642e01fSmrg *
54265b04b38Smrg * For events that have some valuators unset:
5434642e01fSmrg *      min_val == max_val == val == 0.
54405b261ecSmrg */
54505b261ecSmrgstatic void
54665b04b38SmrgupdateMotionHistory(DeviceIntPtr pDev, CARD32 ms, ValuatorMask *mask,
54765b04b38Smrg                    int *valuators)
54805b261ecSmrg{
54905b261ecSmrg    char *buff = (char *) pDev->valuator->motion;
5504642e01fSmrg    ValuatorClassPtr v;
5514642e01fSmrg    int i;
55205b261ecSmrg
55305b261ecSmrg    if (!pDev->valuator->numMotionEvents)
55405b261ecSmrg        return;
55505b261ecSmrg
5564642e01fSmrg    v = pDev->valuator;
5574202a189Smrg    if (IsMaster(pDev))
5584642e01fSmrg    {
5594642e01fSmrg        buff += ((sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(CARD32)) *
5604642e01fSmrg                v->last_motion;
5614642e01fSmrg
5624642e01fSmrg        memcpy(buff, &ms, sizeof(Time));
5634642e01fSmrg        buff += sizeof(Time);
5644642e01fSmrg
5654642e01fSmrg        memset(buff, 0, sizeof(INT32) * 3 * MAX_VALUATORS);
5664642e01fSmrg
56765b04b38Smrg        for (i = 0; i < v->numAxes; i++)
5684642e01fSmrg        {
56965b04b38Smrg            /* XI1 doesn't support mixed mode devices */
57065b04b38Smrg            if (valuator_get_mode(pDev, i) != valuator_get_mode(pDev, 0))
5714642e01fSmrg                break;
57265b04b38Smrg            if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i))
57365b04b38Smrg            {
57465b04b38Smrg                buff += 3 * sizeof(INT32);
57565b04b38Smrg                continue;
57665b04b38Smrg            }
5774642e01fSmrg            memcpy(buff, &v->axes[i].min_value, sizeof(INT32));
5784642e01fSmrg            buff += sizeof(INT32);
5794642e01fSmrg            memcpy(buff, &v->axes[i].max_value, sizeof(INT32));
5804642e01fSmrg            buff += sizeof(INT32);
58165b04b38Smrg            memcpy(buff, &valuators[i], sizeof(INT32));
5824642e01fSmrg            buff += sizeof(INT32);
5834642e01fSmrg        }
5844642e01fSmrg    } else
5854642e01fSmrg    {
5864642e01fSmrg
5874642e01fSmrg        buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) *
58805b261ecSmrg            pDev->valuator->last_motion;
58905b261ecSmrg
5904642e01fSmrg        memcpy(buff, &ms, sizeof(Time));
5914642e01fSmrg        buff += sizeof(Time);
59205b261ecSmrg
5934642e01fSmrg        memset(buff, 0, sizeof(INT32) * pDev->valuator->numAxes);
59405b261ecSmrg
59565b04b38Smrg        for (i = 0; i < MAX_VALUATORS; i++)
59665b04b38Smrg        {
59765b04b38Smrg            if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i))
59865b04b38Smrg            {
59965b04b38Smrg                buff += sizeof(INT32);
60065b04b38Smrg                continue;
60165b04b38Smrg            }
60265b04b38Smrg            memcpy(buff, &valuators[i], sizeof(INT32));
60365b04b38Smrg            buff += sizeof(INT32);
60465b04b38Smrg        }
6054642e01fSmrg    }
60605b261ecSmrg
6074642e01fSmrg    pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) %
6084642e01fSmrg        pDev->valuator->numMotionEvents;
60905b261ecSmrg    /* If we're wrapping around, just keep the circular buffer going. */
61005b261ecSmrg    if (pDev->valuator->first_motion == pDev->valuator->last_motion)
61105b261ecSmrg        pDev->valuator->first_motion = (pDev->valuator->first_motion + 1) %
61205b261ecSmrg                                       pDev->valuator->numMotionEvents;
61305b261ecSmrg
61405b261ecSmrg    return;
61505b261ecSmrg}
61605b261ecSmrg
61705b261ecSmrg
61805b261ecSmrg/**
61905b261ecSmrg * Returns the maximum number of events GetKeyboardEvents,
62005b261ecSmrg * GetKeyboardValuatorEvents, and GetPointerEvents will ever return.
62105b261ecSmrg *
6224642e01fSmrg * This MUST be absolutely constant, from init until exit.
62305b261ecSmrg */
6244202a189Smrgint
62505b261ecSmrgGetMaximumEventsNum(void) {
6264202a189Smrg    /* One raw event
6274202a189Smrg     * One device event
6284202a189Smrg     * One possible device changed event
6294202a189Smrg     */
6304202a189Smrg    return 3;
63105b261ecSmrg}
63205b261ecSmrg
63305b261ecSmrg
63405b261ecSmrg/**
63505b261ecSmrg * Clip an axis to its bounds, which are declared in the call to
63605b261ecSmrg * InitValuatorAxisClassStruct.
63705b261ecSmrg */
63805b261ecSmrgstatic void
63905b261ecSmrgclipAxis(DeviceIntPtr pDev, int axisNum, int *val)
64005b261ecSmrg{
6414202a189Smrg    AxisInfoPtr axis;
6424202a189Smrg
6434202a189Smrg    if (axisNum >= pDev->valuator->numAxes)
6444202a189Smrg        return;
6454202a189Smrg
6464202a189Smrg    axis = pDev->valuator->axes + axisNum;
6474642e01fSmrg
6484642e01fSmrg    /* If a value range is defined, clip. If not, do nothing */
6494642e01fSmrg    if (axis->max_value <= axis->min_value)
6504642e01fSmrg        return;
6514642e01fSmrg
6524642e01fSmrg    if (*val < axis->min_value)
6534642e01fSmrg        *val = axis->min_value;
6544642e01fSmrg    if (*val > axis->max_value)
6554642e01fSmrg        *val = axis->max_value;
65605b261ecSmrg}
65705b261ecSmrg
65805b261ecSmrg/**
65905b261ecSmrg * Clip every axis in the list of valuators to its bounds.
66005b261ecSmrg */
66105b261ecSmrgstatic void
66265b04b38SmrgclipValuators(DeviceIntPtr pDev, ValuatorMask *mask)
66305b261ecSmrg{
66405b261ecSmrg    int i;
66505b261ecSmrg
66665b04b38Smrg    for (i = 0; i < valuator_mask_size(mask); i++)
66765b04b38Smrg        if (valuator_mask_isset(mask, i))
66865b04b38Smrg        {
66965b04b38Smrg            int val = valuator_mask_get(mask, i);
67065b04b38Smrg            clipAxis(pDev, i, &val);
67165b04b38Smrg            valuator_mask_set(mask, i, val);
67265b04b38Smrg        }
67305b261ecSmrg}
67405b261ecSmrg
6754642e01fSmrg/**
6764642e01fSmrg * Create the DCCE event (does not update the master's device state yet, this
6774642e01fSmrg * is done in the event processing).
6784642e01fSmrg * Pull in the coordinates from the MD if necessary.
6794642e01fSmrg *
6804642e01fSmrg * @param events Pointer to a pre-allocated event list.
6814642e01fSmrg * @param dev The slave device that generated an event.
6824202a189Smrg * @param type Either DEVCHANGE_POINTER_EVENT and/or DEVCHANGE_KEYBOARD_EVENT
6834642e01fSmrg * @param num_events The current number of events, returns the number of
6844642e01fSmrg *        events if a DCCE was generated.
6854642e01fSmrg * @return The updated @events pointer.
6864642e01fSmrg */
6874202a189SmrgEventListPtr
6884202a189SmrgUpdateFromMaster(EventListPtr events, DeviceIntPtr dev, int type, int *num_events)
6894642e01fSmrg{
6904202a189Smrg    DeviceIntPtr master;
6914202a189Smrg
6924202a189Smrg    master = GetMaster(dev, (type & DEVCHANGE_POINTER_EVENT) ?  MASTER_POINTER : MASTER_KEYBOARD);
6934202a189Smrg
6944202a189Smrg    if (master && master->last.slave != dev)
6954642e01fSmrg    {
6964202a189Smrg        CreateClassesChangedEvent(events, master, dev, type);
6974202a189Smrg        if (IsPointerDevice(master))
6984202a189Smrg        {
6994202a189Smrg            updateSlaveDeviceCoords(master, dev);
7004202a189Smrg            master->last.numValuators = dev->last.numValuators;
7014202a189Smrg        }
7024202a189Smrg        master->last.slave = dev;
7034202a189Smrg        (*num_events)++;
7044202a189Smrg        events++;
7054642e01fSmrg    }
7064642e01fSmrg    return events;
7074642e01fSmrg}
7084642e01fSmrg
7094642e01fSmrg/**
7104642e01fSmrg * Move the device's pointer to the position given in the valuators.
7114642e01fSmrg *
7124642e01fSmrg * @param dev The device which's pointer is to be moved.
7134642e01fSmrg * @param x Returns the x position of the pointer after the move.
7144642e01fSmrg * @param y Returns the y position of the pointer after the move.
71565b04b38Smrg * @param mask Bit mask of valid valuators.
7164642e01fSmrg * @param valuators Valuator data for each axis between @first and
7174642e01fSmrg *        @first+@num.
7184642e01fSmrg */
7194642e01fSmrgstatic void
72065b04b38SmrgmoveAbsolute(DeviceIntPtr dev, int *x, int *y, ValuatorMask *mask)
7214642e01fSmrg{
7224642e01fSmrg    int i;
7234642e01fSmrg
72465b04b38Smrg    if (valuator_mask_isset(mask, 0))
72565b04b38Smrg        *x = valuator_mask_get(mask, 0);
7264642e01fSmrg    else
7274642e01fSmrg        *x = dev->last.valuators[0];
7284642e01fSmrg
72965b04b38Smrg    if (valuator_mask_isset(mask, 1))
73065b04b38Smrg        *y = valuator_mask_get(mask, 1);
7314642e01fSmrg    else
7324642e01fSmrg        *y = dev->last.valuators[1];
7334642e01fSmrg
7344642e01fSmrg    clipAxis(dev, 0, x);
7354642e01fSmrg    clipAxis(dev, 1, y);
7364642e01fSmrg
73765b04b38Smrg    for (i = 2; i < valuator_mask_size(mask); i++)
7384642e01fSmrg    {
73965b04b38Smrg        if (valuator_mask_isset(mask, i))
74065b04b38Smrg        {
74165b04b38Smrg            dev->last.valuators[i] = valuator_mask_get(mask, i);
74265b04b38Smrg            clipAxis(dev, i, &dev->last.valuators[i]);
74365b04b38Smrg        }
7444642e01fSmrg    }
7454642e01fSmrg}
7464642e01fSmrg
7474642e01fSmrg/**
7484642e01fSmrg * Move the device's pointer by the values given in @valuators.
7494642e01fSmrg *
7504642e01fSmrg * @param dev The device which's pointer is to be moved.
7514642e01fSmrg * @param x Returns the x position of the pointer after the move.
7524642e01fSmrg * @param y Returns the y position of the pointer after the move.
75365b04b38Smrg * @param mask Bit mask of valid valuators.
7544642e01fSmrg * @param valuators Valuator data for each axis between @first and
7554642e01fSmrg *        @first+@num.
7564642e01fSmrg */
7574642e01fSmrgstatic void
75865b04b38SmrgmoveRelative(DeviceIntPtr dev, int *x, int *y, ValuatorMask *mask)
7594642e01fSmrg{
7604642e01fSmrg    int i;
7614642e01fSmrg
7624642e01fSmrg    *x = dev->last.valuators[0];
7634642e01fSmrg    *y = dev->last.valuators[1];
7644642e01fSmrg
76565b04b38Smrg    if (valuator_mask_isset(mask, 0))
76665b04b38Smrg        *x += valuator_mask_get(mask, 0);
7674642e01fSmrg
76865b04b38Smrg    if (valuator_mask_isset(mask, 1))
76965b04b38Smrg        *y += valuator_mask_get(mask, 1);
7704642e01fSmrg
7714642e01fSmrg    /* if attached, clip both x and y to the defined limits (usually
7724642e01fSmrg     * co-ord space limit). If it is attached, we need x/y to go over the
7734642e01fSmrg     * limits to be able to change screens. */
77465b04b38Smrg    if(dev->u.master && dev->valuator) {
77565b04b38Smrg        if (valuator_get_mode(dev, 0) == Absolute)
77665b04b38Smrg            clipAxis(dev, 0, x);
77765b04b38Smrg        if (valuator_get_mode(dev, 1) == Absolute)
77865b04b38Smrg            clipAxis(dev, 1, y);
7794642e01fSmrg    }
7804642e01fSmrg
7814642e01fSmrg    /* calc other axes, clip, drop back into valuators */
78265b04b38Smrg    for (i = 2; i < valuator_mask_size(mask); i++)
7834642e01fSmrg    {
78465b04b38Smrg        if (valuator_mask_isset(mask, i))
78565b04b38Smrg        {
78665b04b38Smrg            dev->last.valuators[i] += valuator_mask_get(mask, i);
78765b04b38Smrg            if (valuator_get_mode(dev, i) == Absolute)
78865b04b38Smrg                clipAxis(dev, i, &dev->last.valuators[i]);
78965b04b38Smrg            valuator_mask_set(mask, i, dev->last.valuators[i]);
79065b04b38Smrg        }
7914642e01fSmrg    }
7924642e01fSmrg}
7934642e01fSmrg
7944642e01fSmrg/**
7954642e01fSmrg * Accelerate the data in valuators based on the device's acceleration scheme.
7964642e01fSmrg *
7974642e01fSmrg * @param dev The device which's pointer is to be moved.
7984642e01fSmrg * @param first The first valuator in @valuators
7994642e01fSmrg * @param num Total number of valuators in @valuators.
8004642e01fSmrg * @param valuators Valuator data for each axis between @first and
8014642e01fSmrg *        @first+@num.
8024642e01fSmrg * @param ms Current time.
8034642e01fSmrg */
8044642e01fSmrgstatic void
8054642e01fSmrgaccelPointer(DeviceIntPtr dev, int first, int num, int *valuators, CARD32 ms)
8064642e01fSmrg{
8074642e01fSmrg    if (dev->valuator->accelScheme.AccelSchemeProc)
8084642e01fSmrg        dev->valuator->accelScheme.AccelSchemeProc(dev, first, num, valuators, ms);
8094642e01fSmrg}
8104642e01fSmrg
8114642e01fSmrg/**
8124642e01fSmrg * If we have HW cursors, this actually moves the visible sprite. If not, we
8134642e01fSmrg * just do all the screen crossing, etc.
8144642e01fSmrg *
8154642e01fSmrg * We scale from device to screen coordinates here, call
8164642e01fSmrg * miPointerSetPosition() and then scale back into device coordinates (if
8174642e01fSmrg * needed). miPSP will change x/y if the screen was crossed.
8184642e01fSmrg *
8194642e01fSmrg * @param dev The device to be moved.
8204642e01fSmrg * @param x Pointer to current x-axis value, may be modified.
8214642e01fSmrg * @param y Pointer to current y-axis value, may be modified.
8224202a189Smrg * @param x_frac Fractional part of current x-axis value, may be modified.
8234202a189Smrg * @param y_frac Fractional part of current y-axis value, may be modified.
8244642e01fSmrg * @param scr Screen the device's sprite is currently on.
8254642e01fSmrg * @param screenx Screen x coordinate the sprite is on after the update.
8264642e01fSmrg * @param screeny Screen y coordinate the sprite is on after the update.
8274202a189Smrg * @param screenx_frac Fractional part of screen x coordinate, as above.
8284202a189Smrg * @param screeny_frac Fractional part of screen y coordinate, as above.
8294642e01fSmrg */
8304642e01fSmrgstatic void
8314202a189SmrgpositionSprite(DeviceIntPtr dev, int *x, int *y, float x_frac, float y_frac,
8324202a189Smrg               ScreenPtr scr, int *screenx, int *screeny, float *screenx_frac, float *screeny_frac)
8334642e01fSmrg{
8344202a189Smrg    int old_screenx, old_screeny;
8354202a189Smrg
8364642e01fSmrg    /* scale x&y to screen */
83765b04b38Smrg    if (dev->valuator && dev->valuator->numAxes > 0) {
8384202a189Smrg        *screenx = rescaleValuatorAxis(*x, x_frac, screenx_frac,
8394202a189Smrg                dev->valuator->axes + 0, NULL, scr->width);
8404202a189Smrg    } else {
8414202a189Smrg        *screenx = dev->last.valuators[0];
8424202a189Smrg        *screenx_frac = dev->last.remainder[0];
8434202a189Smrg    }
8444202a189Smrg
84565b04b38Smrg    if (dev->valuator && dev->valuator->numAxes > 1) {
8464202a189Smrg        *screeny = rescaleValuatorAxis(*y, y_frac, screeny_frac,
8474202a189Smrg                dev->valuator->axes + 1, NULL, scr->height);
8484202a189Smrg    } else {
8494202a189Smrg        *screeny = dev->last.valuators[1];
8504202a189Smrg        *screeny_frac = dev->last.remainder[1];
8514202a189Smrg    }
8524202a189Smrg
8534202a189Smrg    /* Hit the left screen edge? */
8544202a189Smrg    if (*screenx <= 0 && *screenx_frac < 0.0f)
8554202a189Smrg    {
8564202a189Smrg        *screenx_frac = 0.0f;
8574202a189Smrg        x_frac = 0.0f;
8584202a189Smrg    }
8594202a189Smrg    if (*screeny <= 0 && *screeny_frac < 0.0f)
8604202a189Smrg    {
8614202a189Smrg        *screeny_frac = 0.0f;
8624202a189Smrg        y_frac = 0.0f;
8634202a189Smrg    }
8644202a189Smrg
8654642e01fSmrg
8664202a189Smrg    old_screenx = *screenx;
8674202a189Smrg    old_screeny = *screeny;
8684642e01fSmrg    /* This takes care of crossing screens for us, as well as clipping
8694642e01fSmrg     * to the current screen. */
8704202a189Smrg    miPointerSetPosition(dev, screenx, screeny);
8714642e01fSmrg
8724202a189Smrg    if (dev->u.master) {
8734202a189Smrg        dev->u.master->last.valuators[0] = *screenx;
8744202a189Smrg        dev->u.master->last.valuators[1] = *screeny;
8754202a189Smrg        dev->u.master->last.remainder[0] = *screenx_frac;
8764202a189Smrg        dev->u.master->last.remainder[1] = *screeny_frac;
8774642e01fSmrg    }
8784642e01fSmrg
87965b04b38Smrg    if (dev->valuator)
8804642e01fSmrg    {
88165b04b38Smrg        /* Crossed screen? Scale back to device coordiantes */
88265b04b38Smrg        if(*screenx != old_screenx)
88365b04b38Smrg        {
88465b04b38Smrg            scr = miPointerGetScreen(dev);
88565b04b38Smrg            *x = rescaleValuatorAxis(*screenx, *screenx_frac, &x_frac, NULL,
88665b04b38Smrg                                    dev->valuator->axes + 0, scr->width);
88765b04b38Smrg        }
88865b04b38Smrg        if(*screeny != old_screeny)
88965b04b38Smrg        {
89065b04b38Smrg            scr = miPointerGetScreen(dev);
89165b04b38Smrg            *y = rescaleValuatorAxis(*screeny, *screeny_frac, &y_frac, NULL,
89265b04b38Smrg                                     dev->valuator->axes + 1, scr->height);
89365b04b38Smrg        }
8944642e01fSmrg    }
8954642e01fSmrg
8964642e01fSmrg    /* dropy x/y (device coordinates) back into valuators for next event */
8974642e01fSmrg    dev->last.valuators[0] = *x;
8984642e01fSmrg    dev->last.valuators[1] = *y;
8994202a189Smrg    dev->last.remainder[0] = x_frac;
9004202a189Smrg    dev->last.remainder[1] = y_frac;
9014642e01fSmrg}
9024642e01fSmrg
9034642e01fSmrg/**
9044642e01fSmrg * Update the motion history for the device and (if appropriate) for its
9054642e01fSmrg * master device.
9064642e01fSmrg * @param dev Slave device to update.
90765b04b38Smrg * @param mask Bit mask of valid valuators to append to history.
9084642e01fSmrg * @param num Total number of valuators to append to history.
9094642e01fSmrg * @param ms Current time
9104642e01fSmrg */
9114642e01fSmrgstatic void
91265b04b38SmrgupdateHistory(DeviceIntPtr dev, ValuatorMask *mask, CARD32 ms)
9134642e01fSmrg{
91465b04b38Smrg    if (!dev->valuator)
91565b04b38Smrg        return;
91665b04b38Smrg
91765b04b38Smrg    updateMotionHistory(dev, ms, mask, dev->last.valuators);
9184642e01fSmrg    if (dev->u.master)
9194202a189Smrg    {
9204202a189Smrg        DeviceIntPtr master = GetMaster(dev, MASTER_POINTER);
92165b04b38Smrg        updateMotionHistory(master, ms, mask, dev->last.valuators);
9224202a189Smrg    }
9234642e01fSmrg}
92405b261ecSmrg
92505b261ecSmrg/**
92605b261ecSmrg * Convenience wrapper around GetKeyboardValuatorEvents, that takes no
92705b261ecSmrg * valuators.
92805b261ecSmrg */
9294202a189Smrgint
9304642e01fSmrgGetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code) {
93165b04b38Smrg    ValuatorMask mask;
93265b04b38Smrg
93365b04b38Smrg    valuator_mask_zero(&mask);
93465b04b38Smrg    return GetKeyboardValuatorEvents(events, pDev, type, key_code, &mask);
93505b261ecSmrg}
93605b261ecSmrg
93705b261ecSmrg
93805b261ecSmrg/**
93965b04b38Smrg * Returns a set of InternalEvents for KeyPress/KeyRelease, optionally
94065b04b38Smrg * also with valuator events.
9414642e01fSmrg *
94205b261ecSmrg * events is not NULL-terminated; the return value is the number of events.
94305b261ecSmrg * The DDX is responsible for allocating the event structure in the first
94405b261ecSmrg * place via GetMaximumEventsNum(), and for freeing it.
94505b261ecSmrg */
9464202a189Smrgint
9474642e01fSmrgGetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
94865b04b38Smrg                          int key_code, const ValuatorMask *mask_in) {
9494202a189Smrg    int num_events = 0;
95005b261ecSmrg    CARD32 ms = 0;
9514202a189Smrg    DeviceEvent *event;
9524202a189Smrg    RawDeviceEvent *raw;
95365b04b38Smrg    ValuatorMask mask;
9544202a189Smrg
9554202a189Smrg    /* refuse events from disabled devices */
9564202a189Smrg    if (!pDev->enabled)
9574202a189Smrg        return 0;
95805b261ecSmrg
9594642e01fSmrg    if (!events ||!pDev->key || !pDev->focus || !pDev->kbdfeed ||
9604642e01fSmrg       (type != KeyPress && type != KeyRelease) ||
9614642e01fSmrg       (key_code < 8 || key_code > 255))
96205b261ecSmrg        return 0;
96305b261ecSmrg
9644202a189Smrg    num_events = 1;
96505b261ecSmrg
9664202a189Smrg    events = UpdateFromMaster(events, pDev, DEVCHANGE_KEYBOARD_EVENT, &num_events);
96705b261ecSmrg
9684202a189Smrg    /* Handle core repeating, via press/release/press/release. */
9694202a189Smrg    if (type == KeyPress && key_is_down(pDev, key_code, KEY_POSTED)) {
97005b261ecSmrg        /* If autorepeating is disabled either globally or just for that key,
97105b261ecSmrg         * or we have a modifier, don't generate a repeat event. */
97205b261ecSmrg        if (!pDev->kbdfeed->ctrl.autoRepeat ||
97305b261ecSmrg            !key_autorepeats(pDev, key_code) ||
9744202a189Smrg            pDev->key->xkbInfo->desc->map->modmap[key_code])
97505b261ecSmrg            return 0;
97605b261ecSmrg    }
97705b261ecSmrg
97805b261ecSmrg    ms = GetTimeInMillis();
97905b261ecSmrg
9804202a189Smrg    raw = (RawDeviceEvent*)events->event;
9814202a189Smrg    events++;
9824202a189Smrg    num_events++;
9834202a189Smrg
98465b04b38Smrg    valuator_mask_copy(&mask, mask_in);
9854202a189Smrg
9864202a189Smrg    init_raw(pDev, raw, ms, type, key_code);
98765b04b38Smrg    set_raw_valuators(raw, &mask, raw->valuators.data_raw);
9884202a189Smrg
98965b04b38Smrg    clipValuators(pDev, &mask);
9904202a189Smrg
99165b04b38Smrg    set_raw_valuators(raw, &mask, raw->valuators.data);
9924202a189Smrg
9934202a189Smrg    event = (DeviceEvent*) events->event;
9944202a189Smrg    init_event(pDev, event, ms);
9954202a189Smrg    event->detail.key = key_code;
9964202a189Smrg
99705b261ecSmrg    if (type == KeyPress) {
9984202a189Smrg        event->type = ET_KeyPress;
9994202a189Smrg	set_key_down(pDev, key_code, KEY_POSTED);
100005b261ecSmrg    }
100105b261ecSmrg    else if (type == KeyRelease) {
10024202a189Smrg        event->type = ET_KeyRelease;
10034202a189Smrg	set_key_up(pDev, key_code, KEY_POSTED);
100405b261ecSmrg    }
100505b261ecSmrg
100665b04b38Smrg    clipValuators(pDev, &mask);
100705b261ecSmrg
100865b04b38Smrg    set_valuators(pDev, event, &mask);
10094202a189Smrg
10104202a189Smrg    return num_events;
101105b261ecSmrg}
101205b261ecSmrg
10134642e01fSmrg/**
10144642e01fSmrg * Initialize an event list and fill with 32 byte sized events.
10154642e01fSmrg * This event list is to be passed into GetPointerEvents() and
10164642e01fSmrg * GetKeyboardEvents().
10174642e01fSmrg *
10184642e01fSmrg * @param num_events Number of elements in list.
10194642e01fSmrg */
10204642e01fSmrgEventListPtr
10214642e01fSmrgInitEventList(int num_events)
10224642e01fSmrg{
10234642e01fSmrg    EventListPtr events;
10244642e01fSmrg    int i;
10254642e01fSmrg
10264202a189Smrg    events = (EventListPtr)calloc(num_events, sizeof(EventList));
10274642e01fSmrg    if (!events)
10284642e01fSmrg        return NULL;
10294642e01fSmrg
10304642e01fSmrg    for (i = 0; i < num_events; i++)
10314642e01fSmrg    {
10324202a189Smrg        events[i].evlen = sizeof(InternalEvent);
10334202a189Smrg        events[i].event = calloc(1, sizeof(InternalEvent));
10344642e01fSmrg        if (!events[i].event)
10354642e01fSmrg        {
10364642e01fSmrg            /* rollback */
10374642e01fSmrg            while(i--)
10384202a189Smrg                free(events[i].event);
10394202a189Smrg            free(events);
10404642e01fSmrg            events = NULL;
10414642e01fSmrg            break;
10424642e01fSmrg        }
10434642e01fSmrg    }
10444642e01fSmrg
10454642e01fSmrg    return events;
10464642e01fSmrg}
10474642e01fSmrg
10484642e01fSmrg/**
10494642e01fSmrg * Free an event list.
10504642e01fSmrg *
10514642e01fSmrg * @param list The list to be freed.
10524642e01fSmrg * @param num_events Number of elements in list.
10534642e01fSmrg */
10544202a189Smrgvoid
10554642e01fSmrgFreeEventList(EventListPtr list, int num_events)
10564642e01fSmrg{
10574642e01fSmrg    if (!list)
10584642e01fSmrg        return;
10594642e01fSmrg    while(num_events--)
10604202a189Smrg        free(list[num_events].event);
10614202a189Smrg    free(list);
10624202a189Smrg}
10634202a189Smrg
10644202a189Smrgstatic void
106565b04b38SmrgtransformAbsolute(DeviceIntPtr dev, ValuatorMask *mask)
10664202a189Smrg{
106765b04b38Smrg    struct pixman_f_vector p;
10684202a189Smrg
10694202a189Smrg    /* p' = M * p in homogeneous coordinates */
107065b04b38Smrg    p.v[0] = (valuator_mask_isset(mask, 0) ? valuator_mask_get(mask, 0) :
107165b04b38Smrg              dev->last.valuators[0]);
107265b04b38Smrg    p.v[1] = (valuator_mask_isset(mask, 1) ? valuator_mask_get(mask, 1) :
107365b04b38Smrg              dev->last.valuators[1]);
107465b04b38Smrg    p.v[2] = 1.0;
10754202a189Smrg
10764202a189Smrg    pixman_f_transform_point(&dev->transform, &p);
10774202a189Smrg
107865b04b38Smrg    if (lround(p.v[0]) != dev->last.valuators[0])
107965b04b38Smrg        valuator_mask_set(mask, 0, lround(p.v[0]));
108065b04b38Smrg    if (lround(p.v[1]) != dev->last.valuators[1])
108165b04b38Smrg        valuator_mask_set(mask, 1, lround(p.v[1]));
10824642e01fSmrg}
108305b261ecSmrg
108405b261ecSmrg/**
108565b04b38Smrg * Generate a series of InternalEvents (filled into the EventList)
108665b04b38Smrg * representing pointer motion, or button presses.
108705b261ecSmrg *
108805b261ecSmrg * events is not NULL-terminated; the return value is the number of events.
108905b261ecSmrg * The DDX is responsible for allocating the event structure in the first
10904642e01fSmrg * place via InitEventList() and GetMaximumEventsNum(), and for freeing it.
10914642e01fSmrg *
10924642e01fSmrg * In the generated events rootX/Y will be in absolute screen coords and
10934642e01fSmrg * the valuator information in the absolute or relative device coords.
10944642e01fSmrg *
10954642e01fSmrg * last.valuators[x] of the device is always in absolute device coords.
10964642e01fSmrg * last.valuators[x] of the master device is in absolute screen coords.
10974642e01fSmrg *
10984642e01fSmrg * master->last.valuators[x] for x > 2 is undefined.
109905b261ecSmrg */
11004202a189Smrgint
11014642e01fSmrgGetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
110265b04b38Smrg                 int flags, const ValuatorMask *mask_in) {
11034642e01fSmrg    int num_events = 1;
11044642e01fSmrg    CARD32 ms;
11054202a189Smrg    DeviceEvent *event;
11064202a189Smrg    RawDeviceEvent    *raw;
11074202a189Smrg    int x = 0, y = 0, /* device coords */
11084642e01fSmrg        cx, cy; /* only screen coordinates */
11094202a189Smrg    float x_frac = 0.0, y_frac = 0.0, cx_frac, cy_frac;
111005b261ecSmrg    ScreenPtr scr = miPointerGetScreen(pDev);
111165b04b38Smrg    ValuatorMask mask;
11124202a189Smrg
11134202a189Smrg    /* refuse events from disabled devices */
11144202a189Smrg    if (!pDev->enabled)
11154202a189Smrg        return 0;
111605b261ecSmrg
111765b04b38Smrg    if (!scr)
111805b261ecSmrg        return 0;
111905b261ecSmrg
112065b04b38Smrg    switch (type)
112165b04b38Smrg    {
112265b04b38Smrg        case MotionNotify:
112365b04b38Smrg            if (!mask_in || valuator_mask_num_valuators(mask_in) <= 0)
112465b04b38Smrg                return 0;
112565b04b38Smrg            break;
112665b04b38Smrg        case ButtonPress:
112765b04b38Smrg        case ButtonRelease:
112865b04b38Smrg            if (!pDev->button || !buttons)
112965b04b38Smrg                return 0;
113065b04b38Smrg            break;
113165b04b38Smrg        default:
113265b04b38Smrg            return 0;
113365b04b38Smrg    }
113465b04b38Smrg
113565b04b38Smrg    ms = GetTimeInMillis(); /* before pointer update to help precision */
113665b04b38Smrg
11374202a189Smrg    events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
11384202a189Smrg
11394202a189Smrg    raw = (RawDeviceEvent*)events->event;
11404202a189Smrg    events++;
11414202a189Smrg    num_events++;
114205b261ecSmrg
114365b04b38Smrg    valuator_mask_copy(&mask, mask_in);
11444202a189Smrg
11454202a189Smrg    init_raw(pDev, raw, ms, type, buttons);
114665b04b38Smrg    set_raw_valuators(raw, &mask, raw->valuators.data_raw);
114705b261ecSmrg
11484642e01fSmrg    if (flags & POINTER_ABSOLUTE)
11494642e01fSmrg    {
11504642e01fSmrg        if (flags & POINTER_SCREEN) /* valuators are in screen coords */
11514642e01fSmrg        {
115265b04b38Smrg            int scaled;
115305b261ecSmrg
115465b04b38Smrg            if (valuator_mask_isset(&mask, 0))
115565b04b38Smrg            {
115665b04b38Smrg                scaled = rescaleValuatorAxis(valuator_mask_get(&mask, 0),
115765b04b38Smrg                                             0.0, &x_frac, NULL,
115865b04b38Smrg                                             pDev->valuator->axes + 0,
115965b04b38Smrg                                             scr->width);
116065b04b38Smrg                valuator_mask_set(&mask, 0, scaled);
116165b04b38Smrg            }
116265b04b38Smrg            if (valuator_mask_isset(&mask, 1))
116365b04b38Smrg            {
116465b04b38Smrg                scaled = rescaleValuatorAxis(valuator_mask_get(&mask, 1),
116565b04b38Smrg                                             0.0, &y_frac, NULL,
116665b04b38Smrg                                             pDev->valuator->axes + 1,
116765b04b38Smrg                                             scr->height);
116865b04b38Smrg                valuator_mask_set(&mask, 1, scaled);
116965b04b38Smrg            }
117005b261ecSmrg        }
117105b261ecSmrg
117265b04b38Smrg        transformAbsolute(pDev, &mask);
117365b04b38Smrg        moveAbsolute(pDev, &x, &y, &mask);
11744642e01fSmrg    } else {
11754202a189Smrg        if (flags & POINTER_ACCELERATE) {
117665b04b38Smrg            /* FIXME: Pointer acceleration only requires X and Y values. This
117765b04b38Smrg             * should be converted to masked valuators. */
117865b04b38Smrg            int vals[2];
117965b04b38Smrg            vals[0] = valuator_mask_isset(&mask, 0) ?
118065b04b38Smrg                      valuator_mask_get(&mask, 0) : 0;
118165b04b38Smrg            vals[1] = valuator_mask_isset(&mask, 1) ?
118265b04b38Smrg                      valuator_mask_get(&mask, 1) : 0;
118365b04b38Smrg            accelPointer(pDev, 0, 2, vals, ms);
118465b04b38Smrg
118565b04b38Smrg            if (valuator_mask_isset(&mask, 0))
118665b04b38Smrg                valuator_mask_set(&mask, 0, vals[0]);
118765b04b38Smrg            if (valuator_mask_isset(&mask, 1))
118865b04b38Smrg                valuator_mask_set(&mask, 1, vals[1]);
118965b04b38Smrg
11904202a189Smrg            /* The pointer acceleration code modifies the fractional part
11914202a189Smrg             * in-place, so we need to extract this information first */
11924202a189Smrg            x_frac = pDev->last.remainder[0];
11934202a189Smrg            y_frac = pDev->last.remainder[1];
11944202a189Smrg        }
119565b04b38Smrg        moveRelative(pDev, &x, &y, &mask);
119605b261ecSmrg    }
119705b261ecSmrg
119865b04b38Smrg    set_raw_valuators(raw, &mask, raw->valuators.data);
119905b261ecSmrg
12004202a189Smrg    positionSprite(pDev, &x, &y, x_frac, y_frac, scr, &cx, &cy, &cx_frac, &cy_frac);
120165b04b38Smrg    updateHistory(pDev, &mask, ms);
120205b261ecSmrg
12034642e01fSmrg    /* Update the valuators with the true value sent to the client*/
120465b04b38Smrg    if (valuator_mask_isset(&mask, 0))
120565b04b38Smrg        valuator_mask_set(&mask, 0, x);
120665b04b38Smrg    if (valuator_mask_isset(&mask, 1))
120765b04b38Smrg        valuator_mask_set(&mask, 1, y);
120805b261ecSmrg
120965b04b38Smrg    clipValuators(pDev, &mask);
12104202a189Smrg
12114202a189Smrg    event = (DeviceEvent*) events->event;
12124202a189Smrg    init_event(pDev, event, ms);
121305b261ecSmrg
12144642e01fSmrg    if (type == MotionNotify) {
12154202a189Smrg        event->type = ET_Motion;
12164202a189Smrg        event->detail.button = 0;
12174642e01fSmrg    }
12184642e01fSmrg    else {
12194202a189Smrg        if (type == ButtonPress) {
12204202a189Smrg            event->type = ET_ButtonPress;
12214202a189Smrg            set_button_down(pDev, buttons, BUTTON_POSTED);
12224202a189Smrg        }
12234202a189Smrg        else if (type == ButtonRelease) {
12244202a189Smrg            event->type = ET_ButtonRelease;
12254202a189Smrg            set_button_up(pDev, buttons, BUTTON_POSTED);
12264202a189Smrg        }
12274202a189Smrg        event->detail.button = buttons;
12284642e01fSmrg    }
122905b261ecSmrg
12304202a189Smrg    event->root_x = cx; /* root_x/y always in screen coords */
12314202a189Smrg    event->root_y = cy;
12324202a189Smrg    event->root_x_frac = cx_frac;
12334202a189Smrg    event->root_y_frac = cy_frac;
123405b261ecSmrg
123565b04b38Smrg    set_valuators(pDev, event, &mask);
123605b261ecSmrg
123705b261ecSmrg    return num_events;
123805b261ecSmrg}
123905b261ecSmrg
124005b261ecSmrg
124105b261ecSmrg/**
124265b04b38Smrg * Generate ProximityIn/ProximityOut InternalEvents, accompanied by
124365b04b38Smrg * valuators.
124405b261ecSmrg *
124505b261ecSmrg * events is not NULL-terminated; the return value is the number of events.
124605b261ecSmrg * The DDX is responsible for allocating the event structure in the first
124705b261ecSmrg * place via GetMaximumEventsNum(), and for freeing it.
124805b261ecSmrg */
12494202a189Smrgint
125065b04b38SmrgGetProximityEvents(EventList *events, DeviceIntPtr pDev, int type, const ValuatorMask *mask_in)
125105b261ecSmrg{
125265b04b38Smrg    int num_events = 1, i;
12534202a189Smrg    DeviceEvent *event;
125465b04b38Smrg    ValuatorMask mask;
12554202a189Smrg
12564202a189Smrg    /* refuse events from disabled devices */
12574202a189Smrg    if (!pDev->enabled)
12584202a189Smrg        return 0;
125905b261ecSmrg
126005b261ecSmrg    /* Sanity checks. */
126165b04b38Smrg    if ((type != ProximityIn && type != ProximityOut) || !mask_in)
126205b261ecSmrg        return 0;
126305b261ecSmrg    if (!pDev->valuator)
126405b261ecSmrg        return 0;
126505b261ecSmrg
126665b04b38Smrg    valuator_mask_copy(&mask, mask_in);
126765b04b38Smrg
126865b04b38Smrg    /* ignore relative axes for proximity. */
126965b04b38Smrg    for (i = 0; i < valuator_mask_size(&mask); i++)
127065b04b38Smrg    {
127165b04b38Smrg        if (valuator_mask_isset(&mask, i) &&
127265b04b38Smrg            valuator_get_mode(pDev, i) == Relative)
127365b04b38Smrg            valuator_mask_unset(&mask, i);
127465b04b38Smrg    }
127565b04b38Smrg
127665b04b38Smrg    /* FIXME: posting proximity events with relative valuators only results
127765b04b38Smrg     * in an empty event, EventToXI() will fail to convert → no event sent
127865b04b38Smrg     * to client. */
127905b261ecSmrg
12804202a189Smrg    events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
12814642e01fSmrg
12824202a189Smrg    event = (DeviceEvent *) events->event;
12834202a189Smrg    init_event(pDev, event, GetTimeInMillis());
12844202a189Smrg    event->type = (type == ProximityIn) ? ET_ProximityIn : ET_ProximityOut;
128505b261ecSmrg
128665b04b38Smrg    clipValuators(pDev, &mask);
128705b261ecSmrg
128865b04b38Smrg    set_valuators(pDev, event, &mask);
12894202a189Smrg
129005b261ecSmrg    return num_events;
129105b261ecSmrg}
129205b261ecSmrg
129305b261ecSmrg/**
129405b261ecSmrg * Synthesize a single motion event for the core pointer.
129505b261ecSmrg *
129605b261ecSmrg * Used in cursor functions, e.g. when cursor confinement changes, and we need
129705b261ecSmrg * to shift the pointer to get it inside the new bounds.
129805b261ecSmrg */
129905b261ecSmrgvoid
13004642e01fSmrgPostSyntheticMotion(DeviceIntPtr pDev,
13014642e01fSmrg                    int x,
13024642e01fSmrg                    int y,
13034642e01fSmrg                    int screen,
13044642e01fSmrg                    unsigned long time)
130505b261ecSmrg{
13064202a189Smrg    DeviceEvent ev;
130705b261ecSmrg
130805b261ecSmrg#ifdef PANORAMIX
130905b261ecSmrg    /* Translate back to the sprite screen since processInputProc
131005b261ecSmrg       will translate from sprite screen to screen 0 upon reentry
131105b261ecSmrg       to the DIX layer. */
131205b261ecSmrg    if (!noPanoramiXExtension) {
13134202a189Smrg        x += screenInfo.screens[0]->x - screenInfo.screens[screen]->x;
13144202a189Smrg        y += screenInfo.screens[0]->y - screenInfo.screens[screen]->y;
131505b261ecSmrg    }
131605b261ecSmrg#endif
131705b261ecSmrg
13184202a189Smrg    memset(&ev, 0, sizeof(DeviceEvent));
13194202a189Smrg    init_event(pDev, &ev, time);
13204202a189Smrg    ev.root_x = x;
13214202a189Smrg    ev.root_y = y;
13224202a189Smrg    ev.type = ET_Motion;
13234202a189Smrg    ev.time = time;
132405b261ecSmrg
13254202a189Smrg    /* FIXME: MD/SD considerations? */
13264202a189Smrg    (*pDev->public.processInputProc)((InternalEvent*)&ev, pDev);
132705b261ecSmrg}
1328