getevents.c revision 1b684552
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"
4905b261ecSmrg
5005b261ecSmrg#include <X11/extensions/XKBproto.h>
514202a189Smrg#include "xkbsrv.h"
5205b261ecSmrg
5305b261ecSmrg#ifdef PANORAMIX
5405b261ecSmrg#include "panoramiX.h"
5505b261ecSmrg#include "panoramiXsrv.h"
5605b261ecSmrg#endif
5705b261ecSmrg
5805b261ecSmrg#include <X11/extensions/XI.h>
5905b261ecSmrg#include <X11/extensions/XIproto.h>
604202a189Smrg#include <pixman.h>
6105b261ecSmrg#include "exglobals.h"
6205b261ecSmrg#include "exevents.h"
6305b261ecSmrg#include "exglobals.h"
6405b261ecSmrg#include "extnsionst.h"
654202a189Smrg#include "listdev.h" /* for sizing up DeviceClassesChangedEvent */
6605b261ecSmrg
6705b261ecSmrg/* Number of motion history events to store. */
6805b261ecSmrg#define MOTION_HISTORY_SIZE 256
6905b261ecSmrg
704642e01fSmrg/* InputEventList is the container list for all input events generated by the
714642e01fSmrg * DDX. The DDX is expected to call GetEventList() and then pass the list into
724642e01fSmrg * Get{Pointer|Keyboard}Events.
734642e01fSmrg */
744642e01fSmrgEventListPtr InputEventList = NULL;
754642e01fSmrgint InputEventListLen = 0;
764642e01fSmrg
774202a189Smrgint
784642e01fSmrgGetEventList(EventListPtr* list)
794642e01fSmrg{
804642e01fSmrg    *list = InputEventList;
814642e01fSmrg    return InputEventListLen;
824642e01fSmrg}
8305b261ecSmrg
8405b261ecSmrg/**
8505b261ecSmrg * Pick some arbitrary size for Xi motion history.
8605b261ecSmrg */
874202a189Smrgint
8805b261ecSmrgGetMotionHistorySize(void)
8905b261ecSmrg{
9005b261ecSmrg    return MOTION_HISTORY_SIZE;
9105b261ecSmrg}
9205b261ecSmrg
934202a189Smrgvoid
944202a189Smrgset_button_down(DeviceIntPtr pDev, int button, int type)
9505b261ecSmrg{
964202a189Smrg    if (type == BUTTON_PROCESSED)
974202a189Smrg        SetBit(pDev->button->down, button);
984202a189Smrg    else
994202a189Smrg        SetBit(pDev->button->postdown, button);
10005b261ecSmrg}
10105b261ecSmrg
1024202a189Smrgvoid
1034202a189Smrgset_button_up(DeviceIntPtr pDev, int button, int type)
10405b261ecSmrg{
1054202a189Smrg    if (type == BUTTON_PROCESSED)
1064202a189Smrg        ClearBit(pDev->button->down, button);
1074202a189Smrg    else
1084202a189Smrg        ClearBit(pDev->button->postdown, button);
10905b261ecSmrg}
11005b261ecSmrg
1114202a189SmrgBool
1124202a189Smrgbutton_is_down(DeviceIntPtr pDev, int button, int type)
1134202a189Smrg{
1141b684552Smrg    Bool ret = FALSE;
1154202a189Smrg
1164202a189Smrg    if (type & BUTTON_PROCESSED)
1171b684552Smrg        ret = ret || BitIsOn(pDev->button->down, button);
1184202a189Smrg    if (type & BUTTON_POSTED)
1191b684552Smrg        ret = ret || BitIsOn(pDev->button->postdown, button);
1204202a189Smrg
1214202a189Smrg    return ret;
1224202a189Smrg}
1234202a189Smrg
1244202a189Smrgvoid
1254202a189Smrgset_key_down(DeviceIntPtr pDev, int key_code, int type)
12605b261ecSmrg{
1274202a189Smrg    if (type == KEY_PROCESSED)
1284202a189Smrg        SetBit(pDev->key->down, key_code);
1294202a189Smrg    else
1304202a189Smrg        SetBit(pDev->key->postdown, key_code);
1314202a189Smrg}
1324202a189Smrg
1334202a189Smrgvoid
1344202a189Smrgset_key_up(DeviceIntPtr pDev, int key_code, int type)
1354202a189Smrg{
1364202a189Smrg    if (type == KEY_PROCESSED)
1374202a189Smrg        ClearBit(pDev->key->down, key_code);
1384202a189Smrg    else
1394202a189Smrg        ClearBit(pDev->key->postdown, key_code);
1404202a189Smrg}
1414202a189Smrg
1424202a189SmrgBool
1434202a189Smrgkey_is_down(DeviceIntPtr pDev, int key_code, int type)
1444202a189Smrg{
1451b684552Smrg    Bool ret = FALSE;
1464202a189Smrg
1474202a189Smrg    if (type & KEY_PROCESSED)
1481b684552Smrg        ret = ret || BitIsOn(pDev->key->down, key_code);
1494202a189Smrg    if (type & KEY_POSTED)
1501b684552Smrg        ret = ret || BitIsOn(pDev->key->postdown, key_code);
1514202a189Smrg
1524202a189Smrg    return ret;
15305b261ecSmrg}
15405b261ecSmrg
15505b261ecSmrgstatic Bool
15605b261ecSmrgkey_autorepeats(DeviceIntPtr pDev, int key_code)
15705b261ecSmrg{
15805b261ecSmrg    return !!(pDev->kbdfeed->ctrl.autoRepeats[key_code >> 3] &
15905b261ecSmrg              (1 << (key_code & 7)));
16005b261ecSmrg}
16105b261ecSmrg
1624202a189Smrgstatic void
1634202a189Smrginit_event(DeviceIntPtr dev, DeviceEvent* event, Time ms)
1644202a189Smrg{
1654202a189Smrg    memset(event, 0, sizeof(DeviceEvent));
1664202a189Smrg    event->header = ET_Internal;
1674202a189Smrg    event->length = sizeof(DeviceEvent);
1684202a189Smrg    event->time = ms;
1694202a189Smrg    event->deviceid = dev->id;
1704202a189Smrg    event->sourceid = dev->id;
1714202a189Smrg}
1724202a189Smrg
1734202a189Smrgstatic void
1744202a189Smrginit_raw(DeviceIntPtr dev, RawDeviceEvent *event, Time ms, int type, int detail)
1754202a189Smrg{
1764202a189Smrg    memset(event, 0, sizeof(RawDeviceEvent));
1774202a189Smrg    event->header = ET_Internal;
1784202a189Smrg    event->length = sizeof(RawDeviceEvent);
1794202a189Smrg    event->type = ET_RawKeyPress - ET_KeyPress + type;
1804202a189Smrg    event->time = ms;
1814202a189Smrg    event->deviceid = dev->id;
1824202a189Smrg    event->sourceid = dev->id;
1834202a189Smrg    event->detail.button = detail;
1844202a189Smrg}
1854202a189Smrg
1864202a189Smrgstatic void
1874202a189Smrgset_raw_valuators(RawDeviceEvent *event, int first, int num, int *valuators, int32_t* data)
1884202a189Smrg{
1894202a189Smrg    int i;
1904202a189Smrg    for (i = first; i < first + num; i++)
1914202a189Smrg        SetBit(event->valuators.mask, i);
1924202a189Smrg
1934202a189Smrg    memcpy(&data[first], valuators, num * sizeof(uint32_t));
1944202a189Smrg}
1954202a189Smrg
1964202a189Smrg
1974202a189Smrgstatic void
1984202a189Smrgset_valuators(DeviceIntPtr dev, DeviceEvent* event, int first_valuator,
1994202a189Smrg              int num_valuators, int *valuators)
2004202a189Smrg{
2014202a189Smrg    int i;
2024202a189Smrg
2034202a189Smrg    for (i = first_valuator; i < first_valuator + num_valuators; i++)
2044202a189Smrg    {
2054202a189Smrg        SetBit(event->valuators.mask, i);
2064202a189Smrg        if (dev->valuator->mode == Absolute)
2074202a189Smrg            SetBit(event->valuators.mode, i);
2084202a189Smrg        event->valuators.data_frac[i] =
2094202a189Smrg            dev->last.remainder[i] * (1 << 16) * (1 << 16);
2104202a189Smrg    }
2114202a189Smrg
2124202a189Smrg    memcpy(&event->valuators.data[first_valuator],
2131b684552Smrg           valuators, num_valuators * sizeof(int32_t));
2144202a189Smrg
2154202a189Smrg}
2164202a189Smrg
2174202a189Smrgvoid
2184202a189SmrgCreateClassesChangedEvent(EventList* event,
2194202a189Smrg                          DeviceIntPtr master,
2204202a189Smrg                          DeviceIntPtr slave,
2214202a189Smrg                          int type)
2224202a189Smrg{
2234202a189Smrg    int i;
2244202a189Smrg    DeviceChangedEvent *dce;
2254202a189Smrg    CARD32 ms = GetTimeInMillis();
2264202a189Smrg
2274202a189Smrg    dce = (DeviceChangedEvent*)event->event;
2284202a189Smrg    memset(dce, 0, sizeof(DeviceChangedEvent));
2294202a189Smrg    dce->deviceid = slave->id;
2304202a189Smrg    dce->masterid = master->id;
2314202a189Smrg    dce->header = ET_Internal;
2324202a189Smrg    dce->length = sizeof(DeviceChangedEvent);
2334202a189Smrg    dce->type = ET_DeviceChanged;
2344202a189Smrg    dce->time = ms;
2354202a189Smrg    dce->flags = type;
2364202a189Smrg    dce->flags |= DEVCHANGE_SLAVE_SWITCH;
2374202a189Smrg    dce->sourceid = slave->id;
2384202a189Smrg
2394202a189Smrg    if (slave->button)
2404202a189Smrg    {
2414202a189Smrg        dce->buttons.num_buttons = slave->button->numButtons;
2424202a189Smrg        for (i = 0; i < dce->buttons.num_buttons; i++)
2434202a189Smrg            dce->buttons.names[i] = slave->button->labels[i];
2444202a189Smrg    }
2454202a189Smrg    if (slave->valuator)
2464202a189Smrg    {
2474202a189Smrg        dce->num_valuators = slave->valuator->numAxes;
2484202a189Smrg        for (i = 0; i < dce->num_valuators; i++)
2494202a189Smrg        {
2504202a189Smrg            dce->valuators[i].min = slave->valuator->axes[i].min_value;
2514202a189Smrg            dce->valuators[i].max = slave->valuator->axes[i].max_value;
2524202a189Smrg            dce->valuators[i].resolution = slave->valuator->axes[i].resolution;
2534202a189Smrg            /* This should, eventually, be a per-axis mode */
2544202a189Smrg            dce->valuators[i].mode = slave->valuator->mode;
2554202a189Smrg            dce->valuators[i].name = slave->valuator->axes[i].label;
2564202a189Smrg        }
2574202a189Smrg    }
2584202a189Smrg    if (slave->key)
2594202a189Smrg    {
2604202a189Smrg        dce->keys.min_keycode = slave->key->xkbInfo->desc->min_key_code;
2614202a189Smrg        dce->keys.max_keycode = slave->key->xkbInfo->desc->max_key_code;
2624202a189Smrg    }
2634202a189Smrg}
2644202a189Smrg
2654642e01fSmrg/**
2664642e01fSmrg * Rescale the coord between the two axis ranges.
2674642e01fSmrg */
2684642e01fSmrgstatic int
2694202a189SmrgrescaleValuatorAxis(int coord, float remainder, float *remainder_return, AxisInfoPtr from, AxisInfoPtr to,
2704642e01fSmrg                    int defmax)
2714642e01fSmrg{
2724202a189Smrg    int fmin = 0, tmin = 0, fmax = defmax, tmax = defmax, coord_return;
2734202a189Smrg    float value;
2744642e01fSmrg
2754642e01fSmrg    if(from && from->min_value < from->max_value) {
2764642e01fSmrg        fmin = from->min_value;
2774642e01fSmrg        fmax = from->max_value;
2784642e01fSmrg    }
2794642e01fSmrg    if(to && to->min_value < to->max_value) {
2804642e01fSmrg        tmin = to->min_value;
2814642e01fSmrg        tmax = to->max_value;
2824642e01fSmrg    }
2834642e01fSmrg
2844202a189Smrg    if(fmin == tmin && fmax == tmax) {
2854202a189Smrg        if (remainder_return)
2864202a189Smrg            *remainder_return = remainder;
2874642e01fSmrg        return coord;
2884202a189Smrg    }
2894642e01fSmrg
2904202a189Smrg    if(fmax == fmin) { /* avoid division by 0 */
2914202a189Smrg        if (remainder_return)
2924202a189Smrg            *remainder_return = 0.0;
2934642e01fSmrg        return 0;
2944202a189Smrg    }
2954642e01fSmrg
2964202a189Smrg    value = (coord + remainder - fmin) * (tmax - tmin) / (fmax - fmin) + tmin;
2974202a189Smrg    coord_return = lroundf(value);
2984202a189Smrg    if (remainder_return)
2994202a189Smrg        *remainder_return = value - coord_return;
3004202a189Smrg    return coord_return;
3014642e01fSmrg}
3024642e01fSmrg
3034642e01fSmrg/**
3044642e01fSmrg * Update all coordinates when changing to a different SD
3054642e01fSmrg * to ensure that relative reporting will work as expected
3064642e01fSmrg * without loss of precision.
3074642e01fSmrg *
3084642e01fSmrg * pDev->last.valuators will be in absolute device coordinates after this
3094642e01fSmrg * function.
3104642e01fSmrg */
3114642e01fSmrgstatic void
3124642e01fSmrgupdateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
3134642e01fSmrg{
3144642e01fSmrg    ScreenPtr scr = miPointerGetScreen(pDev);
3154642e01fSmrg    int i;
3164642e01fSmrg    DeviceIntPtr lastSlave;
3174642e01fSmrg
3184642e01fSmrg    /* master->last.valuators[0]/[1] is in screen coords and the actual
3194642e01fSmrg     * position of the pointer */
3204642e01fSmrg    pDev->last.valuators[0] = master->last.valuators[0];
3214642e01fSmrg    pDev->last.valuators[1] = master->last.valuators[1];
3224642e01fSmrg
3234642e01fSmrg    if (!pDev->valuator)
3244642e01fSmrg        return;
3254642e01fSmrg
3264642e01fSmrg    /* scale back to device coordinates */
3274642e01fSmrg    if(pDev->valuator->numAxes > 0)
3284202a189Smrg        pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0], pDev->last.remainder[0],
3294202a189Smrg                        &pDev->last.remainder[0], NULL, pDev->valuator->axes + 0, scr->width);
3304642e01fSmrg    if(pDev->valuator->numAxes > 1)
3314202a189Smrg        pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1], pDev->last.remainder[1],
3324202a189Smrg                        &pDev->last.remainder[1], NULL, pDev->valuator->axes + 1, scr->height);
3334642e01fSmrg
3344642e01fSmrg    /* calculate the other axis as well based on info from the old
3354642e01fSmrg     * slave-device. If the old slave had less axes than this one,
3364642e01fSmrg     * last.valuators is reset to 0.
3374642e01fSmrg     */
3384202a189Smrg    if ((lastSlave = master->last.slave) && lastSlave->valuator) {
3394642e01fSmrg        for (i = 2; i < pDev->valuator->numAxes; i++) {
3404642e01fSmrg            if (i >= lastSlave->valuator->numAxes)
3414642e01fSmrg                pDev->last.valuators[i] = 0;
3424642e01fSmrg            else
3434642e01fSmrg                pDev->last.valuators[i] =
3444642e01fSmrg                    rescaleValuatorAxis(pDev->last.valuators[i],
3454202a189Smrg                            pDev->last.remainder[i],
3464202a189Smrg                            &pDev->last.remainder[i],
3474642e01fSmrg                            lastSlave->valuator->axes + i,
3484642e01fSmrg                            pDev->valuator->axes + i, 0);
3494642e01fSmrg        }
3504642e01fSmrg    }
3514642e01fSmrg
3524642e01fSmrg}
3534642e01fSmrg
35405b261ecSmrg/**
35505b261ecSmrg * Allocate the motion history buffer.
35605b261ecSmrg */
3574202a189Smrgvoid
35805b261ecSmrgAllocateMotionHistory(DeviceIntPtr pDev)
35905b261ecSmrg{
3604642e01fSmrg    int size;
3614202a189Smrg    free(pDev->valuator->motion);
36205b261ecSmrg
36305b261ecSmrg    if (pDev->valuator->numMotionEvents < 1)
36405b261ecSmrg        return;
36505b261ecSmrg
3664642e01fSmrg    /* An MD must have a motion history size large enough to keep all
3674642e01fSmrg     * potential valuators, plus the respective range of the valuators.
3684642e01fSmrg     * 3 * INT32 for (min_val, max_val, curr_val))
3694642e01fSmrg     */
3704202a189Smrg    if (IsMaster(pDev))
3714642e01fSmrg        size = sizeof(INT32) * 3 * MAX_VALUATORS;
3724642e01fSmrg    else
3734642e01fSmrg        size = sizeof(INT32) * pDev->valuator->numAxes;
3744642e01fSmrg
3754642e01fSmrg    size += sizeof(Time);
3764642e01fSmrg
3774202a189Smrg    pDev->valuator->motion = calloc(pDev->valuator->numMotionEvents, size);
37805b261ecSmrg    pDev->valuator->first_motion = 0;
37905b261ecSmrg    pDev->valuator->last_motion = 0;
3804642e01fSmrg    if (!pDev->valuator->motion)
3814642e01fSmrg        ErrorF("[dix] %s: Failed to alloc motion history (%d bytes).\n",
3824642e01fSmrg                pDev->name, size * pDev->valuator->numMotionEvents);
38305b261ecSmrg}
38405b261ecSmrg
38505b261ecSmrg/**
38605b261ecSmrg * Dump the motion history between start and stop into the supplied buffer.
38705b261ecSmrg * Only records the event for a given screen in theory, but in practice, we
38805b261ecSmrg * sort of ignore this.
3894642e01fSmrg *
3904642e01fSmrg * If core is set, we only generate x/y, in INT16, scaled to screen coords.
39105b261ecSmrg */
3924202a189Smrgint
3934642e01fSmrgGetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
3944642e01fSmrg                 unsigned long stop, ScreenPtr pScreen, BOOL core)
39505b261ecSmrg{
3964642e01fSmrg    char *ibuff = NULL, *obuff;
39705b261ecSmrg    int i = 0, ret = 0;
3984642e01fSmrg    int j, coord;
39905b261ecSmrg    Time current;
40005b261ecSmrg    /* The size of a single motion event. */
4014642e01fSmrg    int size;
4024642e01fSmrg    int dflt;
4034642e01fSmrg    AxisInfo from, *to; /* for scaling */
4044642e01fSmrg    INT32 *ocbuf, *icbuf; /* pointer to coordinates for copying */
4054642e01fSmrg    INT16 *corebuf;
4064642e01fSmrg    AxisInfo core_axis = {0};
40705b261ecSmrg
40805b261ecSmrg    if (!pDev->valuator || !pDev->valuator->numMotionEvents)
40905b261ecSmrg        return 0;
41005b261ecSmrg
4114642e01fSmrg    if (core && !pScreen)
4124642e01fSmrg        return 0;
4134642e01fSmrg
4144202a189Smrg    if (IsMaster(pDev))
4154642e01fSmrg        size = (sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(Time);
4164642e01fSmrg    else
4174642e01fSmrg        size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
4184642e01fSmrg
4194202a189Smrg    *buff = malloc(size * pDev->valuator->numMotionEvents);
4204642e01fSmrg    if (!(*buff))
4214642e01fSmrg        return 0;
4224642e01fSmrg    obuff = (char *)*buff;
4234642e01fSmrg
42405b261ecSmrg    for (i = pDev->valuator->first_motion;
42505b261ecSmrg         i != pDev->valuator->last_motion;
42605b261ecSmrg         i = (i + 1) % pDev->valuator->numMotionEvents) {
42705b261ecSmrg        /* We index the input buffer by which element we're accessing, which
42805b261ecSmrg         * is not monotonic, and the output buffer by how many events we've
42905b261ecSmrg         * written so far. */
43005b261ecSmrg        ibuff = (char *) pDev->valuator->motion + (i * size);
43105b261ecSmrg        memcpy(&current, ibuff, sizeof(Time));
43205b261ecSmrg
43305b261ecSmrg        if (current > stop) {
43405b261ecSmrg            return ret;
43505b261ecSmrg        }
43605b261ecSmrg        else if (current >= start) {
4374642e01fSmrg            if (core)
4384642e01fSmrg            {
4394642e01fSmrg                memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */
4404642e01fSmrg
4414642e01fSmrg                icbuf = (INT32*)(ibuff + sizeof(Time));
4424642e01fSmrg                corebuf = (INT16*)(obuff + sizeof(Time));
4434642e01fSmrg
4444642e01fSmrg                /* fetch x coordinate + range */
4454642e01fSmrg                memcpy(&from.min_value, icbuf++, sizeof(INT32));
4464642e01fSmrg                memcpy(&from.max_value, icbuf++, sizeof(INT32));
4474642e01fSmrg                memcpy(&coord, icbuf++, sizeof(INT32));
4484642e01fSmrg
4494642e01fSmrg                /* scale to screen coords */
4504642e01fSmrg                to = &core_axis;
4514642e01fSmrg                to->max_value = pScreen->width;
4524202a189Smrg                coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->width);
4534642e01fSmrg
4544642e01fSmrg                memcpy(corebuf, &coord, sizeof(INT16));
4554642e01fSmrg                corebuf++;
4564642e01fSmrg
4574642e01fSmrg                /* fetch y coordinate + range */
4584642e01fSmrg                memcpy(&from.min_value, icbuf++, sizeof(INT32));
4594642e01fSmrg                memcpy(&from.max_value, icbuf++, sizeof(INT32));
4604642e01fSmrg                memcpy(&coord, icbuf++, sizeof(INT32));
4614642e01fSmrg
4624642e01fSmrg                to->max_value = pScreen->height;
4634202a189Smrg                coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->height);
4644642e01fSmrg                memcpy(corebuf, &coord, sizeof(INT16));
4654642e01fSmrg
4664202a189Smrg            } else if (IsMaster(pDev))
4674642e01fSmrg            {
4684642e01fSmrg                memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */
4694642e01fSmrg
4704642e01fSmrg                ocbuf = (INT32*)(obuff + sizeof(Time));
4714642e01fSmrg                icbuf = (INT32*)(ibuff + sizeof(Time));
4724642e01fSmrg                for (j = 0; j < MAX_VALUATORS; j++)
4734642e01fSmrg                {
4744642e01fSmrg                    if (j >= pDev->valuator->numAxes)
4754642e01fSmrg                        break;
4764642e01fSmrg
4774642e01fSmrg                    /* fetch min/max/coordinate */
4784642e01fSmrg                    memcpy(&from.min_value, icbuf++, sizeof(INT32));
4794642e01fSmrg                    memcpy(&from.max_value, icbuf++, sizeof(INT32));
4804642e01fSmrg                    memcpy(&coord, icbuf++, sizeof(INT32));
4814642e01fSmrg
4824642e01fSmrg                    to = (j < pDev->valuator->numAxes) ? &pDev->valuator->axes[j] : NULL;
4834642e01fSmrg
4844642e01fSmrg                    /* x/y scaled to screen if no range is present */
4854642e01fSmrg                    if (j == 0 && (from.max_value < from.min_value))
4864642e01fSmrg                        from.max_value = pScreen->width;
4874642e01fSmrg                    else if (j == 1 && (from.max_value < from.min_value))
4884642e01fSmrg                        from.max_value = pScreen->height;
4894642e01fSmrg
4904642e01fSmrg                    if (j == 0 && (to->max_value < to->min_value))
4914642e01fSmrg                        dflt = pScreen->width;
4924642e01fSmrg                    else if (j == 1 && (to->max_value < to->min_value))
4934642e01fSmrg                        dflt = pScreen->height;
4944642e01fSmrg                    else
4954642e01fSmrg                        dflt = 0;
4964642e01fSmrg
4974642e01fSmrg                    /* scale from stored range into current range */
4984202a189Smrg                    coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, 0);
4994642e01fSmrg                    memcpy(ocbuf, &coord, sizeof(INT32));
5004642e01fSmrg                    ocbuf++;
5014642e01fSmrg                }
5024642e01fSmrg            } else
5034642e01fSmrg                memcpy(obuff, ibuff, size);
5044642e01fSmrg
5054642e01fSmrg            /* don't advance by size here. size may be different to the
5064642e01fSmrg             * actually written size if the MD has less valuators than MAX */
5074642e01fSmrg            if (core)
5084642e01fSmrg                obuff += sizeof(INT32) + sizeof(Time);
5094642e01fSmrg            else
5104642e01fSmrg                obuff += (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
51105b261ecSmrg            ret++;
51205b261ecSmrg        }
51305b261ecSmrg    }
51405b261ecSmrg
51505b261ecSmrg    return ret;
51605b261ecSmrg}
51705b261ecSmrg
51805b261ecSmrg
51905b261ecSmrg/**
52005b261ecSmrg * Update the motion history for a specific device, with the list of
52105b261ecSmrg * valuators.
5224642e01fSmrg *
5234642e01fSmrg * Layout of the history buffer:
5244642e01fSmrg *   for SDs: [time] [val0] [val1] ... [valn]
5254642e01fSmrg *   for MDs: [time] [min_val0] [max_val0] [val0] [min_val1] ... [valn]
5264642e01fSmrg *
5274642e01fSmrg * For events that have some valuators unset (first_valuator > 0):
5284642e01fSmrg *      min_val == max_val == val == 0.
52905b261ecSmrg */
53005b261ecSmrgstatic void
53105b261ecSmrgupdateMotionHistory(DeviceIntPtr pDev, CARD32 ms, int first_valuator,
53205b261ecSmrg                    int num_valuators, int *valuators)
53305b261ecSmrg{
53405b261ecSmrg    char *buff = (char *) pDev->valuator->motion;
5354642e01fSmrg    ValuatorClassPtr v;
5364642e01fSmrg    int i;
53705b261ecSmrg
53805b261ecSmrg    if (!pDev->valuator->numMotionEvents)
53905b261ecSmrg        return;
54005b261ecSmrg
5414642e01fSmrg    v = pDev->valuator;
5424202a189Smrg    if (IsMaster(pDev))
5434642e01fSmrg    {
5444642e01fSmrg        buff += ((sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(CARD32)) *
5454642e01fSmrg                v->last_motion;
5464642e01fSmrg
5474642e01fSmrg        memcpy(buff, &ms, sizeof(Time));
5484642e01fSmrg        buff += sizeof(Time);
5494642e01fSmrg
5504642e01fSmrg        memset(buff, 0, sizeof(INT32) * 3 * MAX_VALUATORS);
5514642e01fSmrg        buff += 3 * sizeof(INT32) * first_valuator;
5524642e01fSmrg
5534642e01fSmrg        for (i = first_valuator; i < first_valuator + num_valuators; i++)
5544642e01fSmrg        {
5554642e01fSmrg            if (i >= v->numAxes)
5564642e01fSmrg                break;
5574642e01fSmrg            memcpy(buff, &v->axes[i].min_value, sizeof(INT32));
5584642e01fSmrg            buff += sizeof(INT32);
5594642e01fSmrg            memcpy(buff, &v->axes[i].max_value, sizeof(INT32));
5604642e01fSmrg            buff += sizeof(INT32);
5614642e01fSmrg            memcpy(buff, &valuators[i - first_valuator], sizeof(INT32));
5624642e01fSmrg            buff += sizeof(INT32);
5634642e01fSmrg        }
5644642e01fSmrg    } else
5654642e01fSmrg    {
5664642e01fSmrg
5674642e01fSmrg        buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) *
56805b261ecSmrg            pDev->valuator->last_motion;
56905b261ecSmrg
5704642e01fSmrg        memcpy(buff, &ms, sizeof(Time));
5714642e01fSmrg        buff += sizeof(Time);
57205b261ecSmrg
5734642e01fSmrg        memset(buff, 0, sizeof(INT32) * pDev->valuator->numAxes);
5744642e01fSmrg        buff += sizeof(INT32) * first_valuator;
57505b261ecSmrg
5764642e01fSmrg        memcpy(buff, valuators, sizeof(INT32) * num_valuators);
5774642e01fSmrg    }
57805b261ecSmrg
5794642e01fSmrg    pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) %
5804642e01fSmrg        pDev->valuator->numMotionEvents;
58105b261ecSmrg    /* If we're wrapping around, just keep the circular buffer going. */
58205b261ecSmrg    if (pDev->valuator->first_motion == pDev->valuator->last_motion)
58305b261ecSmrg        pDev->valuator->first_motion = (pDev->valuator->first_motion + 1) %
58405b261ecSmrg                                       pDev->valuator->numMotionEvents;
58505b261ecSmrg
58605b261ecSmrg    return;
58705b261ecSmrg}
58805b261ecSmrg
58905b261ecSmrg
59005b261ecSmrg/**
59105b261ecSmrg * Returns the maximum number of events GetKeyboardEvents,
59205b261ecSmrg * GetKeyboardValuatorEvents, and GetPointerEvents will ever return.
59305b261ecSmrg *
5944642e01fSmrg * This MUST be absolutely constant, from init until exit.
59505b261ecSmrg */
5964202a189Smrgint
59705b261ecSmrgGetMaximumEventsNum(void) {
5984202a189Smrg    /* One raw event
5994202a189Smrg     * One device event
6004202a189Smrg     * One possible device changed event
6014202a189Smrg     */
6024202a189Smrg    return 3;
60305b261ecSmrg}
60405b261ecSmrg
60505b261ecSmrg
60605b261ecSmrg/**
60705b261ecSmrg * Clip an axis to its bounds, which are declared in the call to
60805b261ecSmrg * InitValuatorAxisClassStruct.
60905b261ecSmrg */
61005b261ecSmrgstatic void
61105b261ecSmrgclipAxis(DeviceIntPtr pDev, int axisNum, int *val)
61205b261ecSmrg{
6134202a189Smrg    AxisInfoPtr axis;
6144202a189Smrg
6154202a189Smrg    if (axisNum >= pDev->valuator->numAxes)
6164202a189Smrg        return;
6174202a189Smrg
6184202a189Smrg    axis = pDev->valuator->axes + axisNum;
6194642e01fSmrg
6204642e01fSmrg    /* If a value range is defined, clip. If not, do nothing */
6214642e01fSmrg    if (axis->max_value <= axis->min_value)
6224642e01fSmrg        return;
6234642e01fSmrg
6244642e01fSmrg    if (*val < axis->min_value)
6254642e01fSmrg        *val = axis->min_value;
6264642e01fSmrg    if (*val > axis->max_value)
6274642e01fSmrg        *val = axis->max_value;
62805b261ecSmrg}
62905b261ecSmrg
63005b261ecSmrg/**
63105b261ecSmrg * Clip every axis in the list of valuators to its bounds.
63205b261ecSmrg */
63305b261ecSmrgstatic void
63405b261ecSmrgclipValuators(DeviceIntPtr pDev, int first_valuator, int num_valuators,
63505b261ecSmrg              int *valuators)
63605b261ecSmrg{
63705b261ecSmrg    int i;
63805b261ecSmrg
6394202a189Smrg    for (i = 0; i < num_valuators; i++)
64005b261ecSmrg        clipAxis(pDev, i + first_valuator, &(valuators[i]));
64105b261ecSmrg}
64205b261ecSmrg
6434642e01fSmrg/**
6444642e01fSmrg * Create the DCCE event (does not update the master's device state yet, this
6454642e01fSmrg * is done in the event processing).
6464642e01fSmrg * Pull in the coordinates from the MD if necessary.
6474642e01fSmrg *
6484642e01fSmrg * @param events Pointer to a pre-allocated event list.
6494642e01fSmrg * @param dev The slave device that generated an event.
6504202a189Smrg * @param type Either DEVCHANGE_POINTER_EVENT and/or DEVCHANGE_KEYBOARD_EVENT
6514642e01fSmrg * @param num_events The current number of events, returns the number of
6524642e01fSmrg *        events if a DCCE was generated.
6534642e01fSmrg * @return The updated @events pointer.
6544642e01fSmrg */
6554202a189SmrgEventListPtr
6564202a189SmrgUpdateFromMaster(EventListPtr events, DeviceIntPtr dev, int type, int *num_events)
6574642e01fSmrg{
6584202a189Smrg    DeviceIntPtr master;
6594202a189Smrg
6604202a189Smrg    master = GetMaster(dev, (type & DEVCHANGE_POINTER_EVENT) ?  MASTER_POINTER : MASTER_KEYBOARD);
6614202a189Smrg
6624202a189Smrg    if (master && master->last.slave != dev)
6634642e01fSmrg    {
6644202a189Smrg        CreateClassesChangedEvent(events, master, dev, type);
6654202a189Smrg        if (IsPointerDevice(master))
6664202a189Smrg        {
6674202a189Smrg            updateSlaveDeviceCoords(master, dev);
6684202a189Smrg            master->last.numValuators = dev->last.numValuators;
6694202a189Smrg        }
6704202a189Smrg        master->last.slave = dev;
6714202a189Smrg        (*num_events)++;
6724202a189Smrg        events++;
6734642e01fSmrg    }
6744642e01fSmrg    return events;
6754642e01fSmrg}
6764642e01fSmrg
6774642e01fSmrg/**
6784642e01fSmrg * Move the device's pointer to the position given in the valuators.
6794642e01fSmrg *
6804642e01fSmrg * @param dev The device which's pointer is to be moved.
6814642e01fSmrg * @param x Returns the x position of the pointer after the move.
6824642e01fSmrg * @param y Returns the y position of the pointer after the move.
6834642e01fSmrg * @param first The first valuator in @valuators
6844642e01fSmrg * @param num Total number of valuators in @valuators.
6854642e01fSmrg * @param valuators Valuator data for each axis between @first and
6864642e01fSmrg *        @first+@num.
6874642e01fSmrg */
6884642e01fSmrgstatic void
6894642e01fSmrgmoveAbsolute(DeviceIntPtr dev, int *x, int *y,
6904642e01fSmrg             int first, int num, int *valuators)
6914642e01fSmrg{
6924642e01fSmrg    int i;
6934642e01fSmrg
6944642e01fSmrg
6954642e01fSmrg    if (num >= 1 && first == 0)
6964642e01fSmrg        *x = *(valuators + 0);
6974642e01fSmrg    else
6984642e01fSmrg        *x = dev->last.valuators[0];
6994642e01fSmrg
7004642e01fSmrg    if (first <= 1 && num >= (2 - first))
7014642e01fSmrg        *y = *(valuators + 1 - first);
7024642e01fSmrg    else
7034642e01fSmrg        *y = dev->last.valuators[1];
7044642e01fSmrg
7054642e01fSmrg    clipAxis(dev, 0, x);
7064642e01fSmrg    clipAxis(dev, 1, y);
7074642e01fSmrg
7084642e01fSmrg    i = (first > 2) ? 0 : 2;
7094642e01fSmrg    for (; i < num; i++)
7104642e01fSmrg    {
7114642e01fSmrg        dev->last.valuators[i + first] = valuators[i];
7124642e01fSmrg        clipAxis(dev, i, &dev->last.valuators[i + first]);
7134642e01fSmrg    }
7144642e01fSmrg}
7154642e01fSmrg
7164642e01fSmrg/**
7174642e01fSmrg * Move the device's pointer by the values given in @valuators.
7184642e01fSmrg *
7194642e01fSmrg * @param dev The device which's pointer is to be moved.
7204642e01fSmrg * @param x Returns the x position of the pointer after the move.
7214642e01fSmrg * @param y Returns the y position of the pointer after the move.
7224642e01fSmrg * @param first The first valuator in @valuators
7234642e01fSmrg * @param num Total number of valuators in @valuators.
7244642e01fSmrg * @param valuators Valuator data for each axis between @first and
7254642e01fSmrg *        @first+@num.
7264642e01fSmrg */
7274642e01fSmrgstatic void
7284642e01fSmrgmoveRelative(DeviceIntPtr dev, int *x, int *y,
7294642e01fSmrg             int first, int num, int *valuators)
7304642e01fSmrg{
7314642e01fSmrg    int i;
7324642e01fSmrg
7334642e01fSmrg    *x = dev->last.valuators[0];
7344642e01fSmrg    *y = dev->last.valuators[1];
7354642e01fSmrg
7364642e01fSmrg    if (num >= 1 && first == 0)
7374642e01fSmrg        *x += *(valuators +0);
7384642e01fSmrg
7394642e01fSmrg    if (first <= 1 && num >= (2 - first))
7404642e01fSmrg        *y += *(valuators + 1 - first);
7414642e01fSmrg
7424642e01fSmrg    /* if attached, clip both x and y to the defined limits (usually
7434642e01fSmrg     * co-ord space limit). If it is attached, we need x/y to go over the
7444642e01fSmrg     * limits to be able to change screens. */
7454202a189Smrg    if(dev->u.master && dev->valuator->mode == Absolute) {
7464642e01fSmrg        clipAxis(dev, 0, x);
7474642e01fSmrg        clipAxis(dev, 1, y);
7484642e01fSmrg    }
7494642e01fSmrg
7504642e01fSmrg    /* calc other axes, clip, drop back into valuators */
7514642e01fSmrg    i = (first > 2) ? 0 : 2;
7524642e01fSmrg    for (; i < num; i++)
7534642e01fSmrg    {
7544642e01fSmrg        dev->last.valuators[i + first] += valuators[i];
7554202a189Smrg        if (dev->valuator->mode == Absolute)
7564202a189Smrg            clipAxis(dev, i, &dev->last.valuators[i + first]);
7574642e01fSmrg        valuators[i] = dev->last.valuators[i + first];
7584642e01fSmrg    }
7594642e01fSmrg}
7604642e01fSmrg
7614642e01fSmrg/**
7624642e01fSmrg * Accelerate the data in valuators based on the device's acceleration scheme.
7634642e01fSmrg *
7644642e01fSmrg * @param dev The device which's pointer is to be moved.
7654642e01fSmrg * @param first The first valuator in @valuators
7664642e01fSmrg * @param num Total number of valuators in @valuators.
7674642e01fSmrg * @param valuators Valuator data for each axis between @first and
7684642e01fSmrg *        @first+@num.
7694642e01fSmrg * @param ms Current time.
7704642e01fSmrg */
7714642e01fSmrgstatic void
7724642e01fSmrgaccelPointer(DeviceIntPtr dev, int first, int num, int *valuators, CARD32 ms)
7734642e01fSmrg{
7744642e01fSmrg    if (dev->valuator->accelScheme.AccelSchemeProc)
7754642e01fSmrg        dev->valuator->accelScheme.AccelSchemeProc(dev, first, num, valuators, ms);
7764642e01fSmrg}
7774642e01fSmrg
7784642e01fSmrg/**
7794642e01fSmrg * If we have HW cursors, this actually moves the visible sprite. If not, we
7804642e01fSmrg * just do all the screen crossing, etc.
7814642e01fSmrg *
7824642e01fSmrg * We scale from device to screen coordinates here, call
7834642e01fSmrg * miPointerSetPosition() and then scale back into device coordinates (if
7844642e01fSmrg * needed). miPSP will change x/y if the screen was crossed.
7854642e01fSmrg *
7864642e01fSmrg * @param dev The device to be moved.
7874642e01fSmrg * @param x Pointer to current x-axis value, may be modified.
7884642e01fSmrg * @param y Pointer to current y-axis value, may be modified.
7894202a189Smrg * @param x_frac Fractional part of current x-axis value, may be modified.
7904202a189Smrg * @param y_frac Fractional part of current y-axis value, may be modified.
7914642e01fSmrg * @param scr Screen the device's sprite is currently on.
7924642e01fSmrg * @param screenx Screen x coordinate the sprite is on after the update.
7934642e01fSmrg * @param screeny Screen y coordinate the sprite is on after the update.
7944202a189Smrg * @param screenx_frac Fractional part of screen x coordinate, as above.
7954202a189Smrg * @param screeny_frac Fractional part of screen y coordinate, as above.
7964642e01fSmrg */
7974642e01fSmrgstatic void
7984202a189SmrgpositionSprite(DeviceIntPtr dev, int *x, int *y, float x_frac, float y_frac,
7994202a189Smrg               ScreenPtr scr, int *screenx, int *screeny, float *screenx_frac, float *screeny_frac)
8004642e01fSmrg{
8014202a189Smrg    int old_screenx, old_screeny;
8024202a189Smrg
8034642e01fSmrg    /* scale x&y to screen */
8044202a189Smrg    if (dev->valuator->numAxes > 0) {
8054202a189Smrg        *screenx = rescaleValuatorAxis(*x, x_frac, screenx_frac,
8064202a189Smrg                dev->valuator->axes + 0, NULL, scr->width);
8074202a189Smrg    } else {
8084202a189Smrg        *screenx = dev->last.valuators[0];
8094202a189Smrg        *screenx_frac = dev->last.remainder[0];
8104202a189Smrg    }
8114202a189Smrg
8124202a189Smrg    if (dev->valuator->numAxes > 1) {
8134202a189Smrg        *screeny = rescaleValuatorAxis(*y, y_frac, screeny_frac,
8144202a189Smrg                dev->valuator->axes + 1, NULL, scr->height);
8154202a189Smrg    } else {
8164202a189Smrg        *screeny = dev->last.valuators[1];
8174202a189Smrg        *screeny_frac = dev->last.remainder[1];
8184202a189Smrg    }
8194202a189Smrg
8204202a189Smrg    /* Hit the left screen edge? */
8214202a189Smrg    if (*screenx <= 0 && *screenx_frac < 0.0f)
8224202a189Smrg    {
8234202a189Smrg        *screenx_frac = 0.0f;
8244202a189Smrg        x_frac = 0.0f;
8254202a189Smrg    }
8264202a189Smrg    if (*screeny <= 0 && *screeny_frac < 0.0f)
8274202a189Smrg    {
8284202a189Smrg        *screeny_frac = 0.0f;
8294202a189Smrg        y_frac = 0.0f;
8304202a189Smrg    }
8314202a189Smrg
8324642e01fSmrg
8334202a189Smrg    old_screenx = *screenx;
8344202a189Smrg    old_screeny = *screeny;
8354642e01fSmrg    /* This takes care of crossing screens for us, as well as clipping
8364642e01fSmrg     * to the current screen. */
8374202a189Smrg    miPointerSetPosition(dev, screenx, screeny);
8384642e01fSmrg
8394202a189Smrg    if (dev->u.master) {
8404202a189Smrg        dev->u.master->last.valuators[0] = *screenx;
8414202a189Smrg        dev->u.master->last.valuators[1] = *screeny;
8424202a189Smrg        dev->u.master->last.remainder[0] = *screenx_frac;
8434202a189Smrg        dev->u.master->last.remainder[1] = *screeny_frac;
8444642e01fSmrg    }
8454642e01fSmrg
8464642e01fSmrg    /* Crossed screen? Scale back to device coordiantes */
8474202a189Smrg    if(*screenx != old_screenx)
8484642e01fSmrg    {
8494642e01fSmrg        scr = miPointerGetScreen(dev);
8504202a189Smrg        *x = rescaleValuatorAxis(*screenx, *screenx_frac, &x_frac, NULL,
8514642e01fSmrg                                dev->valuator->axes + 0, scr->width);
8524642e01fSmrg    }
8534202a189Smrg    if(*screeny != old_screeny)
8544642e01fSmrg    {
8554642e01fSmrg        scr = miPointerGetScreen(dev);
8564202a189Smrg        *y = rescaleValuatorAxis(*screeny, *screeny_frac, &y_frac, NULL,
8574642e01fSmrg                                 dev->valuator->axes + 1, scr->height);
8584642e01fSmrg    }
8594642e01fSmrg
8604642e01fSmrg    /* dropy x/y (device coordinates) back into valuators for next event */
8614642e01fSmrg    dev->last.valuators[0] = *x;
8624642e01fSmrg    dev->last.valuators[1] = *y;
8634202a189Smrg    dev->last.remainder[0] = x_frac;
8644202a189Smrg    dev->last.remainder[1] = y_frac;
8654642e01fSmrg}
8664642e01fSmrg
8674642e01fSmrg/**
8684642e01fSmrg * Update the motion history for the device and (if appropriate) for its
8694642e01fSmrg * master device.
8704642e01fSmrg * @param dev Slave device to update.
8714642e01fSmrg * @param first First valuator to append to history.
8724642e01fSmrg * @param num Total number of valuators to append to history.
8734642e01fSmrg * @param ms Current time
8744642e01fSmrg */
8754642e01fSmrgstatic void
8764642e01fSmrgupdateHistory(DeviceIntPtr dev, int first, int num, CARD32 ms)
8774642e01fSmrg{
8784642e01fSmrg    updateMotionHistory(dev, ms, first, num, &dev->last.valuators[first]);
8794642e01fSmrg    if (dev->u.master)
8804202a189Smrg    {
8814202a189Smrg        DeviceIntPtr master = GetMaster(dev, MASTER_POINTER);
8824202a189Smrg        updateMotionHistory(master, ms, first, num, &dev->last.valuators[first]);
8834202a189Smrg    }
8844642e01fSmrg}
88505b261ecSmrg
88605b261ecSmrg/**
88705b261ecSmrg * Convenience wrapper around GetKeyboardValuatorEvents, that takes no
88805b261ecSmrg * valuators.
88905b261ecSmrg */
8904202a189Smrgint
8914642e01fSmrgGetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code) {
89205b261ecSmrg    return GetKeyboardValuatorEvents(events, pDev, type, key_code, 0, 0, NULL);
89305b261ecSmrg}
89405b261ecSmrg
89505b261ecSmrg
89605b261ecSmrg/**
89705b261ecSmrg * Returns a set of keyboard events for KeyPress/KeyRelease, optionally
89805b261ecSmrg * also with valuator events.  Handles Xi and XKB.
89905b261ecSmrg *
9004642e01fSmrg * DOES NOT GENERATE CORE EVENTS! Core events are created when processing the
9014642e01fSmrg * event (ProcessOtherEvent).
9024642e01fSmrg *
90305b261ecSmrg * events is not NULL-terminated; the return value is the number of events.
90405b261ecSmrg * The DDX is responsible for allocating the event structure in the first
90505b261ecSmrg * place via GetMaximumEventsNum(), and for freeing it.
90605b261ecSmrg *
90705b261ecSmrg * This function does not change the core keymap to that of the device;
90805b261ecSmrg * that is done by SwitchCoreKeyboard, which is called from
90905b261ecSmrg * mieqProcessInputEvents.  If replacing that function, take care to call
91005b261ecSmrg * SetCoreKeyboard before processInputProc, so keymaps are altered to suit.
91105b261ecSmrg */
9124202a189Smrgint
9134642e01fSmrgGetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
91405b261ecSmrg                          int key_code, int first_valuator,
9154202a189Smrg                          int num_valuators, int *valuators_in) {
9164202a189Smrg    int num_events = 0;
91705b261ecSmrg    CARD32 ms = 0;
9184202a189Smrg    DeviceEvent *event;
9194202a189Smrg    RawDeviceEvent *raw;
9204202a189Smrg    int valuators[MAX_VALUATORS];
9214202a189Smrg
9224202a189Smrg    /* refuse events from disabled devices */
9234202a189Smrg    if (!pDev->enabled)
9244202a189Smrg        return 0;
92505b261ecSmrg
9264642e01fSmrg    if (!events ||!pDev->key || !pDev->focus || !pDev->kbdfeed ||
9274202a189Smrg        num_valuators > MAX_VALUATORS ||
9284642e01fSmrg       (type != KeyPress && type != KeyRelease) ||
9294642e01fSmrg       (key_code < 8 || key_code > 255))
93005b261ecSmrg        return 0;
93105b261ecSmrg
9324202a189Smrg    num_events = 1;
93305b261ecSmrg
9344202a189Smrg    events = UpdateFromMaster(events, pDev, DEVCHANGE_KEYBOARD_EVENT, &num_events);
93505b261ecSmrg
9364202a189Smrg    /* Handle core repeating, via press/release/press/release. */
9374202a189Smrg    if (type == KeyPress && key_is_down(pDev, key_code, KEY_POSTED)) {
93805b261ecSmrg        /* If autorepeating is disabled either globally or just for that key,
93905b261ecSmrg         * or we have a modifier, don't generate a repeat event. */
94005b261ecSmrg        if (!pDev->kbdfeed->ctrl.autoRepeat ||
94105b261ecSmrg            !key_autorepeats(pDev, key_code) ||
9424202a189Smrg            pDev->key->xkbInfo->desc->map->modmap[key_code])
94305b261ecSmrg            return 0;
94405b261ecSmrg    }
94505b261ecSmrg
94605b261ecSmrg    ms = GetTimeInMillis();
94705b261ecSmrg
9484202a189Smrg    raw = (RawDeviceEvent*)events->event;
9494202a189Smrg    events++;
9504202a189Smrg    num_events++;
9514202a189Smrg
9524202a189Smrg    memcpy(valuators, valuators_in, num_valuators * sizeof(int));
9534202a189Smrg
9544202a189Smrg    init_raw(pDev, raw, ms, type, key_code);
9554202a189Smrg    set_raw_valuators(raw, first_valuator, num_valuators, valuators,
9564202a189Smrg                      raw->valuators.data_raw);
9574202a189Smrg
9584202a189Smrg    if (num_valuators)
9594202a189Smrg        clipValuators(pDev, first_valuator, num_valuators, valuators);
9604202a189Smrg
9614202a189Smrg    set_raw_valuators(raw, first_valuator, num_valuators, valuators,
9624202a189Smrg                      raw->valuators.data);
9634202a189Smrg
9644202a189Smrg    event = (DeviceEvent*) events->event;
9654202a189Smrg    init_event(pDev, event, ms);
9664202a189Smrg    event->detail.key = key_code;
9674202a189Smrg
96805b261ecSmrg    if (type == KeyPress) {
9694202a189Smrg        event->type = ET_KeyPress;
9704202a189Smrg	set_key_down(pDev, key_code, KEY_POSTED);
97105b261ecSmrg    }
97205b261ecSmrg    else if (type == KeyRelease) {
9734202a189Smrg        event->type = ET_KeyRelease;
9744202a189Smrg	set_key_up(pDev, key_code, KEY_POSTED);
97505b261ecSmrg    }
97605b261ecSmrg
9774202a189Smrg    if (num_valuators)
97805b261ecSmrg        clipValuators(pDev, first_valuator, num_valuators, valuators);
97905b261ecSmrg
9804202a189Smrg    set_valuators(pDev, event, first_valuator, num_valuators, valuators);
9814202a189Smrg
9824202a189Smrg    return num_events;
98305b261ecSmrg}
98405b261ecSmrg
9854642e01fSmrg/**
9864642e01fSmrg * Initialize an event list and fill with 32 byte sized events.
9874642e01fSmrg * This event list is to be passed into GetPointerEvents() and
9884642e01fSmrg * GetKeyboardEvents().
9894642e01fSmrg *
9904642e01fSmrg * @param num_events Number of elements in list.
9914642e01fSmrg */
9924642e01fSmrgEventListPtr
9934642e01fSmrgInitEventList(int num_events)
9944642e01fSmrg{
9954642e01fSmrg    EventListPtr events;
9964642e01fSmrg    int i;
9974642e01fSmrg
9984202a189Smrg    events = (EventListPtr)calloc(num_events, sizeof(EventList));
9994642e01fSmrg    if (!events)
10004642e01fSmrg        return NULL;
10014642e01fSmrg
10024642e01fSmrg    for (i = 0; i < num_events; i++)
10034642e01fSmrg    {
10044202a189Smrg        events[i].evlen = sizeof(InternalEvent);
10054202a189Smrg        events[i].event = calloc(1, sizeof(InternalEvent));
10064642e01fSmrg        if (!events[i].event)
10074642e01fSmrg        {
10084642e01fSmrg            /* rollback */
10094642e01fSmrg            while(i--)
10104202a189Smrg                free(events[i].event);
10114202a189Smrg            free(events);
10124642e01fSmrg            events = NULL;
10134642e01fSmrg            break;
10144642e01fSmrg        }
10154642e01fSmrg    }
10164642e01fSmrg
10174642e01fSmrg    return events;
10184642e01fSmrg}
10194642e01fSmrg
10204642e01fSmrg/**
10214642e01fSmrg * Free an event list.
10224642e01fSmrg *
10234642e01fSmrg * @param list The list to be freed.
10244642e01fSmrg * @param num_events Number of elements in list.
10254642e01fSmrg */
10264202a189Smrgvoid
10274642e01fSmrgFreeEventList(EventListPtr list, int num_events)
10284642e01fSmrg{
10294642e01fSmrg    if (!list)
10304642e01fSmrg        return;
10314642e01fSmrg    while(num_events--)
10324202a189Smrg        free(list[num_events].event);
10334202a189Smrg    free(list);
10344202a189Smrg}
10354202a189Smrg
10364202a189Smrgstatic void
10371b684552SmrgtransformAbsolute(DeviceIntPtr dev, int first, int num, int *valuators)
10384202a189Smrg{
10391b684552Smrg    struct pixman_f_vector p = { .v = {0.0, 0.0, 1.0} };
10404202a189Smrg
10414202a189Smrg    /* p' = M * p in homogeneous coordinates */
10421b684552Smrg    if (num >= 1 && first == 0)
10431b684552Smrg        p.v[0] = *(valuators + 0);
10441b684552Smrg
10451b684552Smrg    if (first <= 1 && num >= (2 - first))
10461b684552Smrg        p.v[1] = *(valuators + 1 - first);
10474202a189Smrg
10484202a189Smrg    pixman_f_transform_point(&dev->transform, &p);
10494202a189Smrg
10501b684552Smrg    valuators[0] = lround(p.v[0]);
10511b684552Smrg    valuators[1] = lround(p.v[1]);
10524642e01fSmrg}
105305b261ecSmrg
105405b261ecSmrg/**
10554642e01fSmrg * Generate a series of xEvents (filled into the EventList) representing
10564642e01fSmrg * pointer motion, or button presses.  Xi and XKB-aware.
10574642e01fSmrg *
10584642e01fSmrg * DOES NOT GENERATE CORE EVENTS! Core events are created when processing the
10594642e01fSmrg * event (ProcessOtherEvent).
106005b261ecSmrg *
106105b261ecSmrg * events is not NULL-terminated; the return value is the number of events.
106205b261ecSmrg * The DDX is responsible for allocating the event structure in the first
10634642e01fSmrg * place via InitEventList() and GetMaximumEventsNum(), and for freeing it.
10644642e01fSmrg *
10654642e01fSmrg * In the generated events rootX/Y will be in absolute screen coords and
10664642e01fSmrg * the valuator information in the absolute or relative device coords.
10674642e01fSmrg *
10684642e01fSmrg * last.valuators[x] of the device is always in absolute device coords.
10694642e01fSmrg * last.valuators[x] of the master device is in absolute screen coords.
10704642e01fSmrg *
10714642e01fSmrg * master->last.valuators[x] for x > 2 is undefined.
107205b261ecSmrg */
10734202a189Smrgint
10744642e01fSmrgGetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
107505b261ecSmrg                 int flags, int first_valuator, int num_valuators,
10764202a189Smrg                 int *valuators_in) {
10774642e01fSmrg    int num_events = 1;
10784642e01fSmrg    CARD32 ms;
10794202a189Smrg    DeviceEvent *event;
10804202a189Smrg    RawDeviceEvent    *raw;
10814202a189Smrg    int x = 0, y = 0, /* device coords */
10824642e01fSmrg        cx, cy; /* only screen coordinates */
10834202a189Smrg    float x_frac = 0.0, y_frac = 0.0, cx_frac, cy_frac;
108405b261ecSmrg    ScreenPtr scr = miPointerGetScreen(pDev);
10854202a189Smrg    int valuators[MAX_VALUATORS];
10864202a189Smrg
10874202a189Smrg    /* refuse events from disabled devices */
10884202a189Smrg    if (!pDev->enabled)
10894202a189Smrg        return 0;
109005b261ecSmrg
10914642e01fSmrg    ms = GetTimeInMillis(); /* before pointer update to help precision */
109205b261ecSmrg
10934642e01fSmrg    if (!scr || !pDev->valuator || first_valuator < 0 ||
10944202a189Smrg        num_valuators > MAX_VALUATORS ||
10954642e01fSmrg        ((num_valuators + first_valuator) > pDev->valuator->numAxes) ||
10964642e01fSmrg        (type != MotionNotify && type != ButtonPress && type != ButtonRelease) ||
10974642e01fSmrg        (type != MotionNotify && !pDev->button) ||
10984202a189Smrg        ((type == ButtonPress || type == ButtonRelease) && !buttons) ||
10994642e01fSmrg        (type == MotionNotify && num_valuators <= 0))
110005b261ecSmrg        return 0;
110105b261ecSmrg
11024202a189Smrg    events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
11034202a189Smrg
11044202a189Smrg    raw = (RawDeviceEvent*)events->event;
11054202a189Smrg    events++;
11064202a189Smrg    num_events++;
110705b261ecSmrg
11084202a189Smrg    memcpy(valuators, valuators_in, num_valuators * sizeof(int));
11094202a189Smrg
11104202a189Smrg    init_raw(pDev, raw, ms, type, buttons);
11114202a189Smrg    set_raw_valuators(raw, first_valuator, num_valuators, valuators,
11124202a189Smrg                      raw->valuators.data_raw);
111305b261ecSmrg
11144642e01fSmrg    if (flags & POINTER_ABSOLUTE)
11154642e01fSmrg    {
11164642e01fSmrg        if (flags & POINTER_SCREEN) /* valuators are in screen coords */
11174642e01fSmrg        {
111805b261ecSmrg
11194202a189Smrg            if (num_valuators >= 1 && first_valuator == 0)
11204202a189Smrg                valuators[0] = rescaleValuatorAxis(valuators[0], 0.0, &x_frac, NULL,
11214202a189Smrg                        pDev->valuator->axes + 0,
11224202a189Smrg                        scr->width);
11234202a189Smrg            if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
11244202a189Smrg                valuators[1 - first_valuator] = rescaleValuatorAxis(valuators[1 - first_valuator], 0.0, &y_frac, NULL,
11254202a189Smrg                        pDev->valuator->axes + 1,
11264202a189Smrg                        scr->height);
112705b261ecSmrg        }
112805b261ecSmrg
11291b684552Smrg        transformAbsolute(pDev, first_valuator, num_valuators, valuators);
11304642e01fSmrg        moveAbsolute(pDev, &x, &y, first_valuator, num_valuators, valuators);
11314642e01fSmrg    } else {
11324202a189Smrg        if (flags & POINTER_ACCELERATE) {
11334642e01fSmrg            accelPointer(pDev, first_valuator, num_valuators, valuators, ms);
11344202a189Smrg            /* The pointer acceleration code modifies the fractional part
11354202a189Smrg             * in-place, so we need to extract this information first */
11364202a189Smrg            x_frac = pDev->last.remainder[0];
11374202a189Smrg            y_frac = pDev->last.remainder[1];
11384202a189Smrg        }
11394642e01fSmrg        moveRelative(pDev, &x, &y, first_valuator, num_valuators, valuators);
114005b261ecSmrg    }
114105b261ecSmrg
11424202a189Smrg    set_raw_valuators(raw, first_valuator, num_valuators, valuators,
11434202a189Smrg            raw->valuators.data);
114405b261ecSmrg
11454202a189Smrg    positionSprite(pDev, &x, &y, x_frac, y_frac, scr, &cx, &cy, &cx_frac, &cy_frac);
11464202a189Smrg    updateHistory(pDev, first_valuator, num_valuators, ms);
114705b261ecSmrg
11484642e01fSmrg    /* Update the valuators with the true value sent to the client*/
11494642e01fSmrg    if (num_valuators >= 1 && first_valuator == 0)
11504642e01fSmrg        valuators[0] = x;
115105b261ecSmrg    if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
11524642e01fSmrg        valuators[1 - first_valuator] = y;
115305b261ecSmrg
11544202a189Smrg    if (num_valuators)
11554202a189Smrg        clipValuators(pDev, first_valuator, num_valuators, valuators);
11564202a189Smrg
11574202a189Smrg    event = (DeviceEvent*) events->event;
11584202a189Smrg    init_event(pDev, event, ms);
115905b261ecSmrg
11604642e01fSmrg    if (type == MotionNotify) {
11614202a189Smrg        event->type = ET_Motion;
11624202a189Smrg        event->detail.button = 0;
11634642e01fSmrg    }
11644642e01fSmrg    else {
11654202a189Smrg        if (type == ButtonPress) {
11664202a189Smrg            event->type = ET_ButtonPress;
11674202a189Smrg            set_button_down(pDev, buttons, BUTTON_POSTED);
11684202a189Smrg        }
11694202a189Smrg        else if (type == ButtonRelease) {
11704202a189Smrg            event->type = ET_ButtonRelease;
11714202a189Smrg            set_button_up(pDev, buttons, BUTTON_POSTED);
11724202a189Smrg        }
11734202a189Smrg        event->detail.button = buttons;
11744642e01fSmrg    }
117505b261ecSmrg
11764202a189Smrg    event->root_x = cx; /* root_x/y always in screen coords */
11774202a189Smrg    event->root_y = cy;
11784202a189Smrg    event->root_x_frac = cx_frac;
11794202a189Smrg    event->root_y_frac = cy_frac;
118005b261ecSmrg
11814202a189Smrg    set_valuators(pDev, event, first_valuator, num_valuators, valuators);
118205b261ecSmrg
118305b261ecSmrg    return num_events;
118405b261ecSmrg}
118505b261ecSmrg
118605b261ecSmrg
118705b261ecSmrg/**
118805b261ecSmrg * Post ProximityIn/ProximityOut events, accompanied by valuators.
118905b261ecSmrg *
119005b261ecSmrg * events is not NULL-terminated; the return value is the number of events.
119105b261ecSmrg * The DDX is responsible for allocating the event structure in the first
119205b261ecSmrg * place via GetMaximumEventsNum(), and for freeing it.
119305b261ecSmrg */
11944202a189Smrgint
11954642e01fSmrgGetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
11964202a189Smrg                   int first_valuator, int num_valuators, int *valuators_in)
119705b261ecSmrg{
119805b261ecSmrg    int num_events = 1;
11994202a189Smrg    DeviceEvent *event;
12004202a189Smrg    int valuators[MAX_VALUATORS];
12014202a189Smrg
12024202a189Smrg    /* refuse events from disabled devices */
12034202a189Smrg    if (!pDev->enabled)
12044202a189Smrg        return 0;
120505b261ecSmrg
120605b261ecSmrg    /* Sanity checks. */
120705b261ecSmrg    if (type != ProximityIn && type != ProximityOut)
120805b261ecSmrg        return 0;
120905b261ecSmrg    if (!pDev->valuator)
121005b261ecSmrg        return 0;
121105b261ecSmrg    /* Do we need to send a DeviceValuator event? */
121205b261ecSmrg    if ((pDev->valuator->mode & 1) == Relative)
121305b261ecSmrg        num_valuators = 0;
121405b261ecSmrg
121505b261ecSmrg    /* You fail. */
12164202a189Smrg    if (first_valuator < 0 || num_valuators > MAX_VALUATORS ||
121705b261ecSmrg        (num_valuators + first_valuator) > pDev->valuator->numAxes)
121805b261ecSmrg        return 0;
121905b261ecSmrg
12204202a189Smrg    events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
12214642e01fSmrg
12224202a189Smrg    event = (DeviceEvent *) events->event;
12234202a189Smrg    init_event(pDev, event, GetTimeInMillis());
12244202a189Smrg    event->type = (type == ProximityIn) ? ET_ProximityIn : ET_ProximityOut;
122505b261ecSmrg
122605b261ecSmrg    if (num_valuators) {
12274202a189Smrg        memcpy(valuators, valuators_in, num_valuators * sizeof(int));
122805b261ecSmrg        clipValuators(pDev, first_valuator, num_valuators, valuators);
122905b261ecSmrg    }
123005b261ecSmrg
12314202a189Smrg    set_valuators(pDev, event, first_valuator, num_valuators, valuators);
12324202a189Smrg
123305b261ecSmrg    return num_events;
123405b261ecSmrg}
123505b261ecSmrg
123605b261ecSmrg/**
123705b261ecSmrg * Synthesize a single motion event for the core pointer.
123805b261ecSmrg *
123905b261ecSmrg * Used in cursor functions, e.g. when cursor confinement changes, and we need
124005b261ecSmrg * to shift the pointer to get it inside the new bounds.
124105b261ecSmrg */
124205b261ecSmrgvoid
12434642e01fSmrgPostSyntheticMotion(DeviceIntPtr pDev,
12444642e01fSmrg                    int x,
12454642e01fSmrg                    int y,
12464642e01fSmrg                    int screen,
12474642e01fSmrg                    unsigned long time)
124805b261ecSmrg{
12494202a189Smrg    DeviceEvent ev;
125005b261ecSmrg
125105b261ecSmrg#ifdef PANORAMIX
125205b261ecSmrg    /* Translate back to the sprite screen since processInputProc
125305b261ecSmrg       will translate from sprite screen to screen 0 upon reentry
125405b261ecSmrg       to the DIX layer. */
125505b261ecSmrg    if (!noPanoramiXExtension) {
12564202a189Smrg        x += screenInfo.screens[0]->x - screenInfo.screens[screen]->x;
12574202a189Smrg        y += screenInfo.screens[0]->y - screenInfo.screens[screen]->y;
125805b261ecSmrg    }
125905b261ecSmrg#endif
126005b261ecSmrg
12614202a189Smrg    memset(&ev, 0, sizeof(DeviceEvent));
12624202a189Smrg    init_event(pDev, &ev, time);
12634202a189Smrg    ev.root_x = x;
12644202a189Smrg    ev.root_y = y;
12654202a189Smrg    ev.type = ET_Motion;
12664202a189Smrg    ev.time = time;
126705b261ecSmrg
12684202a189Smrg    /* FIXME: MD/SD considerations? */
12694202a189Smrg    (*pDev->public.processInputProc)((InternalEvent*)&ev, pDev);
127005b261ecSmrg}
1271