getevents.c revision 4642e01f
105b261ecSmrg/*
205b261ecSmrg * Copyright © 2006 Nokia Corporation
305b261ecSmrg * Copyright © 2006-2007 Daniel Stone
405b261ecSmrg *
505b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a
605b261ecSmrg * copy of this software and associated documentation files (the "Software"),
705b261ecSmrg * to deal in the Software without restriction, including without limitation
805b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
905b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the
1005b261ecSmrg * Software is furnished to do so, subject to the following conditions:
1105b261ecSmrg *
1205b261ecSmrg * The above copyright notice and this permission notice (including the next
1305b261ecSmrg * paragraph) shall be included in all copies or substantial portions of the
1405b261ecSmrg * Software.
1505b261ecSmrg *
1605b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1705b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1805b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1905b261ecSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2005b261ecSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2105b261ecSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2205b261ecSmrg * DEALINGS IN THE SOFTWARE.
2305b261ecSmrg *
2405b261ecSmrg * Author: Daniel Stone <daniel@fooishbar.org>
2505b261ecSmrg */
2605b261ecSmrg
2705b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
2805b261ecSmrg#include <dix-config.h>
2905b261ecSmrg#endif
3005b261ecSmrg
3105b261ecSmrg#include <X11/X.h>
3205b261ecSmrg#include <X11/keysym.h>
3305b261ecSmrg#define NEED_EVENTS
3405b261ecSmrg#define NEED_REPLIES
3505b261ecSmrg#include <X11/Xproto.h>
3605b261ecSmrg
3705b261ecSmrg#include "misc.h"
3805b261ecSmrg#include "resource.h"
3905b261ecSmrg#include "inputstr.h"
4005b261ecSmrg#include "scrnintstr.h"
4105b261ecSmrg#include "cursorstr.h"
4205b261ecSmrg#include "dixstruct.h"
4305b261ecSmrg#include "globals.h"
4405b261ecSmrg#include "dixevents.h"
4505b261ecSmrg#include "mipointer.h"
4605b261ecSmrg
4705b261ecSmrg#ifdef XKB
4805b261ecSmrg#include <X11/extensions/XKBproto.h>
4905b261ecSmrg#include <xkbsrv.h>
5005b261ecSmrg#endif
5105b261ecSmrg
5205b261ecSmrg#ifdef PANORAMIX
5305b261ecSmrg#include "panoramiX.h"
5405b261ecSmrg#include "panoramiXsrv.h"
5505b261ecSmrg#endif
5605b261ecSmrg
5705b261ecSmrg#include <X11/extensions/XI.h>
5805b261ecSmrg#include <X11/extensions/XIproto.h>
5905b261ecSmrg#include "exglobals.h"
6005b261ecSmrg#include "exevents.h"
6105b261ecSmrg#include "exglobals.h"
6205b261ecSmrg#include "extnsionst.h"
6305b261ecSmrg
6405b261ecSmrg/* Number of motion history events to store. */
6505b261ecSmrg#define MOTION_HISTORY_SIZE 256
6605b261ecSmrg
674642e01fSmrg/* InputEventList is the container list for all input events generated by the
684642e01fSmrg * DDX. The DDX is expected to call GetEventList() and then pass the list into
694642e01fSmrg * Get{Pointer|Keyboard}Events.
704642e01fSmrg */
714642e01fSmrgEventListPtr InputEventList = NULL;
724642e01fSmrgint InputEventListLen = 0;
734642e01fSmrg
744642e01fSmrg_X_EXPORT int
754642e01fSmrgGetEventList(EventListPtr* list)
764642e01fSmrg{
774642e01fSmrg    *list = InputEventList;
784642e01fSmrg    return InputEventListLen;
794642e01fSmrg}
8005b261ecSmrg
8105b261ecSmrg/**
8205b261ecSmrg * Pick some arbitrary size for Xi motion history.
8305b261ecSmrg */
8405b261ecSmrg_X_EXPORT int
8505b261ecSmrgGetMotionHistorySize(void)
8605b261ecSmrg{
8705b261ecSmrg    return MOTION_HISTORY_SIZE;
8805b261ecSmrg}
8905b261ecSmrg
9005b261ecSmrgstatic void
9105b261ecSmrgset_key_down(DeviceIntPtr pDev, int key_code)
9205b261ecSmrg{
9305b261ecSmrg    pDev->key->postdown[key_code >> 3] |= (1 << (key_code & 7));
9405b261ecSmrg}
9505b261ecSmrg
9605b261ecSmrgstatic void
9705b261ecSmrgset_key_up(DeviceIntPtr pDev, int key_code)
9805b261ecSmrg{
9905b261ecSmrg    pDev->key->postdown[key_code >> 3] &= ~(1 << (key_code & 7));
10005b261ecSmrg}
10105b261ecSmrg
10205b261ecSmrgstatic Bool
10305b261ecSmrgkey_is_down(DeviceIntPtr pDev, int key_code)
10405b261ecSmrg{
10505b261ecSmrg    return !!(pDev->key->postdown[key_code >> 3] & (1 << (key_code & 7)));
10605b261ecSmrg}
10705b261ecSmrg
10805b261ecSmrgstatic Bool
10905b261ecSmrgkey_autorepeats(DeviceIntPtr pDev, int key_code)
11005b261ecSmrg{
11105b261ecSmrg    return !!(pDev->kbdfeed->ctrl.autoRepeats[key_code >> 3] &
11205b261ecSmrg              (1 << (key_code & 7)));
11305b261ecSmrg}
11405b261ecSmrg
1154642e01fSmrg/**
1164642e01fSmrg * Rescale the coord between the two axis ranges.
1174642e01fSmrg */
1184642e01fSmrgstatic int
1194642e01fSmrgrescaleValuatorAxis(int coord, AxisInfoPtr from, AxisInfoPtr to,
1204642e01fSmrg                    int defmax)
1214642e01fSmrg{
1224642e01fSmrg    int fmin = 0, tmin = 0, fmax = defmax, tmax = defmax;
1234642e01fSmrg
1244642e01fSmrg    if(from && from->min_value < from->max_value) {
1254642e01fSmrg        fmin = from->min_value;
1264642e01fSmrg        fmax = from->max_value;
1274642e01fSmrg    }
1284642e01fSmrg    if(to && to->min_value < to->max_value) {
1294642e01fSmrg        tmin = to->min_value;
1304642e01fSmrg        tmax = to->max_value;
1314642e01fSmrg    }
1324642e01fSmrg
1334642e01fSmrg    if(fmin == tmin && fmax == tmax)
1344642e01fSmrg        return coord;
1354642e01fSmrg
1364642e01fSmrg    if(fmax == fmin) /* avoid division by 0 */
1374642e01fSmrg        return 0;
1384642e01fSmrg
1394642e01fSmrg    return roundf(((float)(coord - fmin)) * (tmax - tmin) /
1404642e01fSmrg                 (fmax - fmin)) + tmin;
1414642e01fSmrg}
1424642e01fSmrg
1434642e01fSmrg/**
1444642e01fSmrg * Update all coordinates when changing to a different SD
1454642e01fSmrg * to ensure that relative reporting will work as expected
1464642e01fSmrg * without loss of precision.
1474642e01fSmrg *
1484642e01fSmrg * pDev->last.valuators will be in absolute device coordinates after this
1494642e01fSmrg * function.
1504642e01fSmrg */
1514642e01fSmrgstatic void
1524642e01fSmrgupdateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
1534642e01fSmrg{
1544642e01fSmrg    ScreenPtr scr = miPointerGetScreen(pDev);
1554642e01fSmrg    int i;
1564642e01fSmrg    DeviceIntPtr lastSlave;
1574642e01fSmrg
1584642e01fSmrg    /* master->last.valuators[0]/[1] is in screen coords and the actual
1594642e01fSmrg     * position of the pointer */
1604642e01fSmrg    pDev->last.valuators[0] = master->last.valuators[0];
1614642e01fSmrg    pDev->last.valuators[1] = master->last.valuators[1];
1624642e01fSmrg
1634642e01fSmrg    if (!pDev->valuator)
1644642e01fSmrg        return;
1654642e01fSmrg
1664642e01fSmrg    /* scale back to device coordinates */
1674642e01fSmrg    if(pDev->valuator->numAxes > 0)
1684642e01fSmrg        pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0], NULL, pDev->valuator->axes + 0, scr->width);
1694642e01fSmrg    if(pDev->valuator->numAxes > 1)
1704642e01fSmrg        pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1], NULL, pDev->valuator->axes + 1, scr->height);
1714642e01fSmrg
1724642e01fSmrg    /* calculate the other axis as well based on info from the old
1734642e01fSmrg     * slave-device. If the old slave had less axes than this one,
1744642e01fSmrg     * last.valuators is reset to 0.
1754642e01fSmrg     */
1764642e01fSmrg    if ((lastSlave = master->u.lastSlave) && lastSlave->valuator) {
1774642e01fSmrg        for (i = 2; i < pDev->valuator->numAxes; i++) {
1784642e01fSmrg            if (i >= lastSlave->valuator->numAxes)
1794642e01fSmrg                pDev->last.valuators[i] = 0;
1804642e01fSmrg            else
1814642e01fSmrg                pDev->last.valuators[i] =
1824642e01fSmrg                    rescaleValuatorAxis(pDev->last.valuators[i],
1834642e01fSmrg                            lastSlave->valuator->axes + i,
1844642e01fSmrg                            pDev->valuator->axes + i, 0);
1854642e01fSmrg        }
1864642e01fSmrg    }
1874642e01fSmrg
1884642e01fSmrg}
1894642e01fSmrg
19005b261ecSmrg/**
19105b261ecSmrg * Allocate the motion history buffer.
19205b261ecSmrg */
19305b261ecSmrg_X_EXPORT void
19405b261ecSmrgAllocateMotionHistory(DeviceIntPtr pDev)
19505b261ecSmrg{
1964642e01fSmrg    int size;
19705b261ecSmrg    if (pDev->valuator->motion)
19805b261ecSmrg        xfree(pDev->valuator->motion);
19905b261ecSmrg
20005b261ecSmrg    if (pDev->valuator->numMotionEvents < 1)
20105b261ecSmrg        return;
20205b261ecSmrg
2034642e01fSmrg    /* An MD must have a motion history size large enough to keep all
2044642e01fSmrg     * potential valuators, plus the respective range of the valuators.
2054642e01fSmrg     * 3 * INT32 for (min_val, max_val, curr_val))
2064642e01fSmrg     */
2074642e01fSmrg    if (pDev->isMaster)
2084642e01fSmrg        size = sizeof(INT32) * 3 * MAX_VALUATORS;
2094642e01fSmrg    else
2104642e01fSmrg        size = sizeof(INT32) * pDev->valuator->numAxes;
2114642e01fSmrg
2124642e01fSmrg    size += sizeof(Time);
2134642e01fSmrg
2144642e01fSmrg    pDev->valuator->motion = xcalloc(pDev->valuator->numMotionEvents, size);
21505b261ecSmrg    pDev->valuator->first_motion = 0;
21605b261ecSmrg    pDev->valuator->last_motion = 0;
2174642e01fSmrg    if (!pDev->valuator->motion)
2184642e01fSmrg        ErrorF("[dix] %s: Failed to alloc motion history (%d bytes).\n",
2194642e01fSmrg                pDev->name, size * pDev->valuator->numMotionEvents);
22005b261ecSmrg}
22105b261ecSmrg
22205b261ecSmrg/**
22305b261ecSmrg * Dump the motion history between start and stop into the supplied buffer.
22405b261ecSmrg * Only records the event for a given screen in theory, but in practice, we
22505b261ecSmrg * sort of ignore this.
2264642e01fSmrg *
2274642e01fSmrg * If core is set, we only generate x/y, in INT16, scaled to screen coords.
22805b261ecSmrg */
22905b261ecSmrg_X_EXPORT int
2304642e01fSmrgGetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
2314642e01fSmrg                 unsigned long stop, ScreenPtr pScreen, BOOL core)
23205b261ecSmrg{
2334642e01fSmrg    char *ibuff = NULL, *obuff;
23405b261ecSmrg    int i = 0, ret = 0;
2354642e01fSmrg    int j, coord;
23605b261ecSmrg    Time current;
23705b261ecSmrg    /* The size of a single motion event. */
2384642e01fSmrg    int size;
2394642e01fSmrg    int dflt;
2404642e01fSmrg    AxisInfo from, *to; /* for scaling */
2414642e01fSmrg    INT32 *ocbuf, *icbuf; /* pointer to coordinates for copying */
2424642e01fSmrg    INT16 *corebuf;
2434642e01fSmrg    AxisInfo core_axis = {0};
24405b261ecSmrg
24505b261ecSmrg    if (!pDev->valuator || !pDev->valuator->numMotionEvents)
24605b261ecSmrg        return 0;
24705b261ecSmrg
2484642e01fSmrg    if (core && !pScreen)
2494642e01fSmrg        return 0;
2504642e01fSmrg
2514642e01fSmrg    if (pDev->isMaster)
2524642e01fSmrg        size = (sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(Time);
2534642e01fSmrg    else
2544642e01fSmrg        size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
2554642e01fSmrg
2564642e01fSmrg    *buff = xalloc(size * pDev->valuator->numMotionEvents);
2574642e01fSmrg    if (!(*buff))
2584642e01fSmrg        return 0;
2594642e01fSmrg    obuff = (char *)*buff;
2604642e01fSmrg
26105b261ecSmrg    for (i = pDev->valuator->first_motion;
26205b261ecSmrg         i != pDev->valuator->last_motion;
26305b261ecSmrg         i = (i + 1) % pDev->valuator->numMotionEvents) {
26405b261ecSmrg        /* We index the input buffer by which element we're accessing, which
26505b261ecSmrg         * is not monotonic, and the output buffer by how many events we've
26605b261ecSmrg         * written so far. */
26705b261ecSmrg        ibuff = (char *) pDev->valuator->motion + (i * size);
26805b261ecSmrg        memcpy(&current, ibuff, sizeof(Time));
26905b261ecSmrg
27005b261ecSmrg        if (current > stop) {
27105b261ecSmrg            return ret;
27205b261ecSmrg        }
27305b261ecSmrg        else if (current >= start) {
2744642e01fSmrg            if (core)
2754642e01fSmrg            {
2764642e01fSmrg                memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */
2774642e01fSmrg
2784642e01fSmrg                icbuf = (INT32*)(ibuff + sizeof(Time));
2794642e01fSmrg                corebuf = (INT16*)(obuff + sizeof(Time));
2804642e01fSmrg
2814642e01fSmrg                /* fetch x coordinate + range */
2824642e01fSmrg                memcpy(&from.min_value, icbuf++, sizeof(INT32));
2834642e01fSmrg                memcpy(&from.max_value, icbuf++, sizeof(INT32));
2844642e01fSmrg                memcpy(&coord, icbuf++, sizeof(INT32));
2854642e01fSmrg
2864642e01fSmrg                /* scale to screen coords */
2874642e01fSmrg                to = &core_axis;
2884642e01fSmrg                to->max_value = pScreen->width;
2894642e01fSmrg                coord = rescaleValuatorAxis(coord, &from, to, pScreen->width);
2904642e01fSmrg
2914642e01fSmrg                memcpy(corebuf, &coord, sizeof(INT16));
2924642e01fSmrg                corebuf++;
2934642e01fSmrg
2944642e01fSmrg                /* fetch y coordinate + range */
2954642e01fSmrg                memcpy(&from.min_value, icbuf++, sizeof(INT32));
2964642e01fSmrg                memcpy(&from.max_value, icbuf++, sizeof(INT32));
2974642e01fSmrg                memcpy(&coord, icbuf++, sizeof(INT32));
2984642e01fSmrg
2994642e01fSmrg                to->max_value = pScreen->height;
3004642e01fSmrg                coord = rescaleValuatorAxis(coord, &from, to, pScreen->height);
3014642e01fSmrg                memcpy(corebuf, &coord, sizeof(INT16));
3024642e01fSmrg
3034642e01fSmrg            } else if (pDev->isMaster)
3044642e01fSmrg            {
3054642e01fSmrg                memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */
3064642e01fSmrg
3074642e01fSmrg                ocbuf = (INT32*)(obuff + sizeof(Time));
3084642e01fSmrg                icbuf = (INT32*)(ibuff + sizeof(Time));
3094642e01fSmrg                for (j = 0; j < MAX_VALUATORS; j++)
3104642e01fSmrg                {
3114642e01fSmrg                    if (j >= pDev->valuator->numAxes)
3124642e01fSmrg                        break;
3134642e01fSmrg
3144642e01fSmrg                    /* fetch min/max/coordinate */
3154642e01fSmrg                    memcpy(&from.min_value, icbuf++, sizeof(INT32));
3164642e01fSmrg                    memcpy(&from.max_value, icbuf++, sizeof(INT32));
3174642e01fSmrg                    memcpy(&coord, icbuf++, sizeof(INT32));
3184642e01fSmrg
3194642e01fSmrg                    to = (j < pDev->valuator->numAxes) ? &pDev->valuator->axes[j] : NULL;
3204642e01fSmrg
3214642e01fSmrg                    /* x/y scaled to screen if no range is present */
3224642e01fSmrg                    if (j == 0 && (from.max_value < from.min_value))
3234642e01fSmrg                        from.max_value = pScreen->width;
3244642e01fSmrg                    else if (j == 1 && (from.max_value < from.min_value))
3254642e01fSmrg                        from.max_value = pScreen->height;
3264642e01fSmrg
3274642e01fSmrg                    if (j == 0 && (to->max_value < to->min_value))
3284642e01fSmrg                        dflt = pScreen->width;
3294642e01fSmrg                    else if (j == 1 && (to->max_value < to->min_value))
3304642e01fSmrg                        dflt = pScreen->height;
3314642e01fSmrg                    else
3324642e01fSmrg                        dflt = 0;
3334642e01fSmrg
3344642e01fSmrg                    /* scale from stored range into current range */
3354642e01fSmrg                    coord = rescaleValuatorAxis(coord, &from, to, 0);
3364642e01fSmrg                    memcpy(ocbuf, &coord, sizeof(INT32));
3374642e01fSmrg                    ocbuf++;
3384642e01fSmrg                }
3394642e01fSmrg            } else
3404642e01fSmrg                memcpy(obuff, ibuff, size);
3414642e01fSmrg
3424642e01fSmrg            /* don't advance by size here. size may be different to the
3434642e01fSmrg             * actually written size if the MD has less valuators than MAX */
3444642e01fSmrg            if (core)
3454642e01fSmrg                obuff += sizeof(INT32) + sizeof(Time);
3464642e01fSmrg            else
3474642e01fSmrg                obuff += (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
34805b261ecSmrg            ret++;
34905b261ecSmrg        }
35005b261ecSmrg    }
35105b261ecSmrg
35205b261ecSmrg    return ret;
35305b261ecSmrg}
35405b261ecSmrg
35505b261ecSmrg
35605b261ecSmrg/**
35705b261ecSmrg * Update the motion history for a specific device, with the list of
35805b261ecSmrg * valuators.
3594642e01fSmrg *
3604642e01fSmrg * Layout of the history buffer:
3614642e01fSmrg *   for SDs: [time] [val0] [val1] ... [valn]
3624642e01fSmrg *   for MDs: [time] [min_val0] [max_val0] [val0] [min_val1] ... [valn]
3634642e01fSmrg *
3644642e01fSmrg * For events that have some valuators unset (first_valuator > 0):
3654642e01fSmrg *      min_val == max_val == val == 0.
36605b261ecSmrg */
36705b261ecSmrgstatic void
36805b261ecSmrgupdateMotionHistory(DeviceIntPtr pDev, CARD32 ms, int first_valuator,
36905b261ecSmrg                    int num_valuators, int *valuators)
37005b261ecSmrg{
37105b261ecSmrg    char *buff = (char *) pDev->valuator->motion;
3724642e01fSmrg    ValuatorClassPtr v;
3734642e01fSmrg    int i;
37405b261ecSmrg
37505b261ecSmrg    if (!pDev->valuator->numMotionEvents)
37605b261ecSmrg        return;
37705b261ecSmrg
3784642e01fSmrg    v = pDev->valuator;
3794642e01fSmrg    if (pDev->isMaster)
3804642e01fSmrg    {
3814642e01fSmrg        buff += ((sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(CARD32)) *
3824642e01fSmrg                v->last_motion;
3834642e01fSmrg
3844642e01fSmrg        memcpy(buff, &ms, sizeof(Time));
3854642e01fSmrg        buff += sizeof(Time);
3864642e01fSmrg
3874642e01fSmrg        memset(buff, 0, sizeof(INT32) * 3 * MAX_VALUATORS);
3884642e01fSmrg        buff += 3 * sizeof(INT32) * first_valuator;
3894642e01fSmrg
3904642e01fSmrg        for (i = first_valuator; i < first_valuator + num_valuators; i++)
3914642e01fSmrg        {
3924642e01fSmrg            if (i >= v->numAxes)
3934642e01fSmrg                break;
3944642e01fSmrg            memcpy(buff, &v->axes[i].min_value, sizeof(INT32));
3954642e01fSmrg            buff += sizeof(INT32);
3964642e01fSmrg            memcpy(buff, &v->axes[i].max_value, sizeof(INT32));
3974642e01fSmrg            buff += sizeof(INT32);
3984642e01fSmrg            memcpy(buff, &valuators[i - first_valuator], sizeof(INT32));
3994642e01fSmrg            buff += sizeof(INT32);
4004642e01fSmrg        }
4014642e01fSmrg    } else
4024642e01fSmrg    {
4034642e01fSmrg
4044642e01fSmrg        buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) *
40505b261ecSmrg            pDev->valuator->last_motion;
40605b261ecSmrg
4074642e01fSmrg        memcpy(buff, &ms, sizeof(Time));
4084642e01fSmrg        buff += sizeof(Time);
40905b261ecSmrg
4104642e01fSmrg        memset(buff, 0, sizeof(INT32) * pDev->valuator->numAxes);
4114642e01fSmrg        buff += sizeof(INT32) * first_valuator;
41205b261ecSmrg
4134642e01fSmrg        memcpy(buff, valuators, sizeof(INT32) * num_valuators);
4144642e01fSmrg    }
41505b261ecSmrg
4164642e01fSmrg    pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) %
4174642e01fSmrg        pDev->valuator->numMotionEvents;
41805b261ecSmrg    /* If we're wrapping around, just keep the circular buffer going. */
41905b261ecSmrg    if (pDev->valuator->first_motion == pDev->valuator->last_motion)
42005b261ecSmrg        pDev->valuator->first_motion = (pDev->valuator->first_motion + 1) %
42105b261ecSmrg                                       pDev->valuator->numMotionEvents;
42205b261ecSmrg
42305b261ecSmrg    return;
42405b261ecSmrg}
42505b261ecSmrg
42605b261ecSmrg
42705b261ecSmrg/**
42805b261ecSmrg * Returns the maximum number of events GetKeyboardEvents,
42905b261ecSmrg * GetKeyboardValuatorEvents, and GetPointerEvents will ever return.
43005b261ecSmrg *
43105b261ecSmrg * Should be used in DIX as:
43205b261ecSmrg * xEvent *events = xcalloc(sizeof(xEvent), GetMaximumEventsNum());
4334642e01fSmrg *
4344642e01fSmrg * This MUST be absolutely constant, from init until exit.
43505b261ecSmrg */
43605b261ecSmrg_X_EXPORT int
43705b261ecSmrgGetMaximumEventsNum(void) {
4384642e01fSmrg    /* One base event -- device, plus valuator events.
4394642e01fSmrg     *  Multiply by two if we're doing non-XKB key repeats. */
4404642e01fSmrg    int ret = 1 + MAX_VALUATOR_EVENTS;
44105b261ecSmrg
44205b261ecSmrg#ifdef XKB
44305b261ecSmrg    if (noXkbExtension)
44405b261ecSmrg#endif
44505b261ecSmrg        ret *= 2;
44605b261ecSmrg
44705b261ecSmrg    return ret;
44805b261ecSmrg}
44905b261ecSmrg
45005b261ecSmrg
45105b261ecSmrg/**
45205b261ecSmrg * Clip an axis to its bounds, which are declared in the call to
45305b261ecSmrg * InitValuatorAxisClassStruct.
45405b261ecSmrg */
45505b261ecSmrgstatic void
45605b261ecSmrgclipAxis(DeviceIntPtr pDev, int axisNum, int *val)
45705b261ecSmrg{
4584642e01fSmrg    AxisInfoPtr axis = pDev->valuator->axes + axisNum;
4594642e01fSmrg    /* InitValuatoraAxisStruct ensures that (min < max). */
4604642e01fSmrg
4614642e01fSmrg    /* If a value range is defined, clip. If not, do nothing */
4624642e01fSmrg    if (axis->max_value <= axis->min_value)
4634642e01fSmrg        return;
4644642e01fSmrg
4654642e01fSmrg    if (*val < axis->min_value)
4664642e01fSmrg        *val = axis->min_value;
4674642e01fSmrg    if (*val > axis->max_value)
4684642e01fSmrg        *val = axis->max_value;
46905b261ecSmrg}
47005b261ecSmrg
47105b261ecSmrg/**
47205b261ecSmrg * Clip every axis in the list of valuators to its bounds.
47305b261ecSmrg */
47405b261ecSmrgstatic void
47505b261ecSmrgclipValuators(DeviceIntPtr pDev, int first_valuator, int num_valuators,
47605b261ecSmrg              int *valuators)
47705b261ecSmrg{
47805b261ecSmrg    AxisInfoPtr axes = pDev->valuator->axes + first_valuator;
47905b261ecSmrg    int i;
48005b261ecSmrg
48105b261ecSmrg    for (i = 0; i < num_valuators; i++, axes++)
48205b261ecSmrg        clipAxis(pDev, i + first_valuator, &(valuators[i]));
48305b261ecSmrg}
48405b261ecSmrg
48505b261ecSmrg
48605b261ecSmrg/**
48705b261ecSmrg * Fills events with valuator events for pDev, as given by the other
48805b261ecSmrg * parameters.
48905b261ecSmrg */
4904642e01fSmrgstatic EventList *
4914642e01fSmrggetValuatorEvents(EventList *events, DeviceIntPtr pDev,
4924642e01fSmrg        int first_valuator, int num_valuators, int *valuators) {
4934642e01fSmrg    deviceValuator *xv;
4944642e01fSmrg    int i;
49505b261ecSmrg
4964642e01fSmrg    for (i = 0; i < num_valuators; i += 6, events++) {
4974642e01fSmrg        xv = (deviceValuator*)events->event;
49805b261ecSmrg        xv->type = DeviceValuator;
4994642e01fSmrg        xv->first_valuator = first_valuator + i;
5004642e01fSmrg        xv->num_valuators = ((num_valuators - i) > 6) ? 6 : (num_valuators - i);
50105b261ecSmrg        xv->deviceid = pDev->id;
5024642e01fSmrg        switch (num_valuators - i) {
50305b261ecSmrg        case 6:
50405b261ecSmrg            xv->valuator5 = valuators[i + 5];
50505b261ecSmrg        case 5:
50605b261ecSmrg            xv->valuator4 = valuators[i + 4];
50705b261ecSmrg        case 4:
50805b261ecSmrg            xv->valuator3 = valuators[i + 3];
50905b261ecSmrg        case 3:
51005b261ecSmrg            xv->valuator2 = valuators[i + 2];
51105b261ecSmrg        case 2:
51205b261ecSmrg            xv->valuator1 = valuators[i + 1];
51305b261ecSmrg        case 1:
5144642e01fSmrg            xv->valuator0 = valuators[i + 0];
51505b261ecSmrg        }
51605b261ecSmrg
5174642e01fSmrg        if (i + 6 < num_valuators)
51805b261ecSmrg            xv->deviceid |= MORE_EVENTS;
51905b261ecSmrg    }
52005b261ecSmrg
52105b261ecSmrg    return events;
52205b261ecSmrg}
52305b261ecSmrg
5244642e01fSmrg/**
5254642e01fSmrg * Create the DCCE event (does not update the master's device state yet, this
5264642e01fSmrg * is done in the event processing).
5274642e01fSmrg * Pull in the coordinates from the MD if necessary.
5284642e01fSmrg *
5294642e01fSmrg * @param events Pointer to a pre-allocated event list.
5304642e01fSmrg * @param dev The slave device that generated an event.
5314642e01fSmrg * @param num_events The current number of events, returns the number of
5324642e01fSmrg *        events if a DCCE was generated.
5334642e01fSmrg * @return The updated @events pointer.
5344642e01fSmrg */
5354642e01fSmrgstatic EventListPtr
5364642e01fSmrgupdateFromMaster(EventListPtr events, DeviceIntPtr dev, int *num_events)
5374642e01fSmrg{
5384642e01fSmrg    DeviceIntPtr master = dev->u.master;
5394642e01fSmrg    if (master && master->u.lastSlave != dev)
5404642e01fSmrg    {
5414642e01fSmrg        updateSlaveDeviceCoords(master, dev);
5424642e01fSmrg        master->u.lastSlave = dev;
5434642e01fSmrg        master->last.numValuators = dev->last.numValuators;
5444642e01fSmrg    }
5454642e01fSmrg    return events;
5464642e01fSmrg}
5474642e01fSmrg
5484642e01fSmrg/**
5494642e01fSmrg * Move the device's pointer to the position given in the valuators.
5504642e01fSmrg *
5514642e01fSmrg * @param dev The device which's pointer is to be moved.
5524642e01fSmrg * @param x Returns the x position of the pointer after the move.
5534642e01fSmrg * @param y Returns the y position of the pointer after the move.
5544642e01fSmrg * @param first The first valuator in @valuators
5554642e01fSmrg * @param num Total number of valuators in @valuators.
5564642e01fSmrg * @param valuators Valuator data for each axis between @first and
5574642e01fSmrg *        @first+@num.
5584642e01fSmrg */
5594642e01fSmrgstatic void
5604642e01fSmrgmoveAbsolute(DeviceIntPtr dev, int *x, int *y,
5614642e01fSmrg             int first, int num, int *valuators)
5624642e01fSmrg{
5634642e01fSmrg    int i;
5644642e01fSmrg
5654642e01fSmrg
5664642e01fSmrg    if (num >= 1 && first == 0)
5674642e01fSmrg        *x = *(valuators + 0);
5684642e01fSmrg    else
5694642e01fSmrg        *x = dev->last.valuators[0];
5704642e01fSmrg
5714642e01fSmrg    if (first <= 1 && num >= (2 - first))
5724642e01fSmrg        *y = *(valuators + 1 - first);
5734642e01fSmrg    else
5744642e01fSmrg        *y = dev->last.valuators[1];
5754642e01fSmrg
5764642e01fSmrg    clipAxis(dev, 0, x);
5774642e01fSmrg    clipAxis(dev, 1, y);
5784642e01fSmrg
5794642e01fSmrg    i = (first > 2) ? 0 : 2;
5804642e01fSmrg    for (; i < num; i++)
5814642e01fSmrg    {
5824642e01fSmrg        dev->last.valuators[i + first] = valuators[i];
5834642e01fSmrg        clipAxis(dev, i, &dev->last.valuators[i + first]);
5844642e01fSmrg    }
5854642e01fSmrg}
5864642e01fSmrg
5874642e01fSmrg/**
5884642e01fSmrg * Move the device's pointer by the values given in @valuators.
5894642e01fSmrg *
5904642e01fSmrg * @param dev The device which's pointer is to be moved.
5914642e01fSmrg * @param x Returns the x position of the pointer after the move.
5924642e01fSmrg * @param y Returns the y position of the pointer after the move.
5934642e01fSmrg * @param first The first valuator in @valuators
5944642e01fSmrg * @param num Total number of valuators in @valuators.
5954642e01fSmrg * @param valuators Valuator data for each axis between @first and
5964642e01fSmrg *        @first+@num.
5974642e01fSmrg */
5984642e01fSmrgstatic void
5994642e01fSmrgmoveRelative(DeviceIntPtr dev, int *x, int *y,
6004642e01fSmrg             int first, int num, int *valuators)
6014642e01fSmrg{
6024642e01fSmrg    int i;
6034642e01fSmrg
6044642e01fSmrg    *x = dev->last.valuators[0];
6054642e01fSmrg    *y = dev->last.valuators[1];
6064642e01fSmrg
6074642e01fSmrg    if (num >= 1 && first == 0)
6084642e01fSmrg        *x += *(valuators +0);
6094642e01fSmrg
6104642e01fSmrg    if (first <= 1 && num >= (2 - first))
6114642e01fSmrg        *y += *(valuators + 1 - first);
6124642e01fSmrg
6134642e01fSmrg    /* if attached, clip both x and y to the defined limits (usually
6144642e01fSmrg     * co-ord space limit). If it is attached, we need x/y to go over the
6154642e01fSmrg     * limits to be able to change screens. */
6164642e01fSmrg    if(dev->u.master) {
6174642e01fSmrg        clipAxis(dev, 0, x);
6184642e01fSmrg        clipAxis(dev, 1, y);
6194642e01fSmrg    }
6204642e01fSmrg
6214642e01fSmrg    /* calc other axes, clip, drop back into valuators */
6224642e01fSmrg    i = (first > 2) ? 0 : 2;
6234642e01fSmrg    for (; i < num; i++)
6244642e01fSmrg    {
6254642e01fSmrg        dev->last.valuators[i + first] += valuators[i];
6264642e01fSmrg        clipAxis(dev, i, &dev->last.valuators[i + first]);
6274642e01fSmrg        valuators[i] = dev->last.valuators[i + first];
6284642e01fSmrg    }
6294642e01fSmrg}
6304642e01fSmrg
6314642e01fSmrg/**
6324642e01fSmrg * Accelerate the data in valuators based on the device's acceleration scheme.
6334642e01fSmrg *
6344642e01fSmrg * @param dev The device which's pointer is to be moved.
6354642e01fSmrg * @param first The first valuator in @valuators
6364642e01fSmrg * @param num Total number of valuators in @valuators.
6374642e01fSmrg * @param valuators Valuator data for each axis between @first and
6384642e01fSmrg *        @first+@num.
6394642e01fSmrg * @param ms Current time.
6404642e01fSmrg */
6414642e01fSmrgstatic void
6424642e01fSmrgaccelPointer(DeviceIntPtr dev, int first, int num, int *valuators, CARD32 ms)
6434642e01fSmrg{
6444642e01fSmrg    if (dev->valuator->accelScheme.AccelSchemeProc)
6454642e01fSmrg        dev->valuator->accelScheme.AccelSchemeProc(dev, first, num, valuators, ms);
6464642e01fSmrg}
6474642e01fSmrg
6484642e01fSmrg/**
6494642e01fSmrg * If we have HW cursors, this actually moves the visible sprite. If not, we
6504642e01fSmrg * just do all the screen crossing, etc.
6514642e01fSmrg *
6524642e01fSmrg * We scale from device to screen coordinates here, call
6534642e01fSmrg * miPointerSetPosition() and then scale back into device coordinates (if
6544642e01fSmrg * needed). miPSP will change x/y if the screen was crossed.
6554642e01fSmrg *
6564642e01fSmrg * @param dev The device to be moved.
6574642e01fSmrg * @param x Pointer to current x-axis value, may be modified.
6584642e01fSmrg * @param y Pointer to current y-axis value, may be modified.
6594642e01fSmrg * @param scr Screen the device's sprite is currently on.
6604642e01fSmrg * @param screenx Screen x coordinate the sprite is on after the update.
6614642e01fSmrg * @param screeny Screen y coordinate the sprite is on after the update.
6624642e01fSmrg */
6634642e01fSmrgstatic void
6644642e01fSmrgpositionSprite(DeviceIntPtr dev, int *x, int *y,
6654642e01fSmrg               ScreenPtr scr, int *screenx, int *screeny)
6664642e01fSmrg{
6674642e01fSmrg    /* scale x&y to screen */
6684642e01fSmrg    *screenx = rescaleValuatorAxis(*x, dev->valuator->axes + 0, NULL, scr->width);
6694642e01fSmrg    *screeny = rescaleValuatorAxis(*y, dev->valuator->axes + 1, NULL, scr->height);
6704642e01fSmrg    dev->last.valuators[0] = *screenx;
6714642e01fSmrg    dev->last.valuators[1] = *screeny;
6724642e01fSmrg
6734642e01fSmrg    /* This takes care of crossing screens for us, as well as clipping
6744642e01fSmrg     * to the current screen. */
6754642e01fSmrg    miPointerSetPosition(dev, &dev->last.valuators[0], &dev->last.valuators[1]);
6764642e01fSmrg
6774642e01fSmrg    if (dev->u.master) {
6784642e01fSmrg        dev->u.master->last.valuators[0] = dev->last.valuators[0];
6794642e01fSmrg        dev->u.master->last.valuators[1] = dev->last.valuators[1];
6804642e01fSmrg    }
6814642e01fSmrg
6824642e01fSmrg    /* Crossed screen? Scale back to device coordiantes */
6834642e01fSmrg    if(*screenx != dev->last.valuators[0])
6844642e01fSmrg    {
6854642e01fSmrg        scr = miPointerGetScreen(dev);
6864642e01fSmrg        *x = rescaleValuatorAxis(dev->last.valuators[0], NULL,
6874642e01fSmrg                                dev->valuator->axes + 0, scr->width);
6884642e01fSmrg        *screenx = dev->last.valuators[0];
6894642e01fSmrg    }
6904642e01fSmrg    if(*screeny != dev->last.valuators[1])
6914642e01fSmrg    {
6924642e01fSmrg        scr = miPointerGetScreen(dev);
6934642e01fSmrg        *screeny = dev->last.valuators[1];
6944642e01fSmrg        *y = rescaleValuatorAxis(dev->last.valuators[1], NULL,
6954642e01fSmrg                                 dev->valuator->axes + 1, scr->height);
6964642e01fSmrg    }
6974642e01fSmrg
6984642e01fSmrg    /* dropy x/y (device coordinates) back into valuators for next event */
6994642e01fSmrg    dev->last.valuators[0] = *x;
7004642e01fSmrg    dev->last.valuators[1] = *y;
7014642e01fSmrg}
7024642e01fSmrg
7034642e01fSmrg/**
7044642e01fSmrg * Update the motion history for the device and (if appropriate) for its
7054642e01fSmrg * master device.
7064642e01fSmrg * @param dev Slave device to update.
7074642e01fSmrg * @param first First valuator to append to history.
7084642e01fSmrg * @param num Total number of valuators to append to history.
7094642e01fSmrg * @param ms Current time
7104642e01fSmrg */
7114642e01fSmrgstatic void
7124642e01fSmrgupdateHistory(DeviceIntPtr dev, int first, int num, CARD32 ms)
7134642e01fSmrg{
7144642e01fSmrg    updateMotionHistory(dev, ms, first, num, &dev->last.valuators[first]);
7154642e01fSmrg    if (dev->u.master)
7164642e01fSmrg        updateMotionHistory(dev->u.master, ms, first, num,
7174642e01fSmrg                            &dev->last.valuators[first]);
7184642e01fSmrg}
7194642e01fSmrg
7204642e01fSmrg/**
7214642e01fSmrg * Calculate how many DeviceValuator events are needed given a number of
7224642e01fSmrg * valuators.
7234642e01fSmrg * @param num_valuators Number of valuators to attach to event.
7244642e01fSmrg * @return the number of DeviceValuator events needed.
7254642e01fSmrg */
7264642e01fSmrgstatic int
7274642e01fSmrgcountValuatorEvents(int num_valuators)
7284642e01fSmrg{
7294642e01fSmrg    if (num_valuators) {
7304642e01fSmrg        if (((num_valuators - 1) / 6) + 1 > MAX_VALUATOR_EVENTS)
7314642e01fSmrg            num_valuators = MAX_VALUATOR_EVENTS * 6;
7324642e01fSmrg        return ((num_valuators - 1)/ 6) + 1;
7334642e01fSmrg    } else
7344642e01fSmrg        return 0;
7354642e01fSmrg}
73605b261ecSmrg
73705b261ecSmrg/**
73805b261ecSmrg * Convenience wrapper around GetKeyboardValuatorEvents, that takes no
73905b261ecSmrg * valuators.
74005b261ecSmrg */
74105b261ecSmrg_X_EXPORT int
7424642e01fSmrgGetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code) {
74305b261ecSmrg    return GetKeyboardValuatorEvents(events, pDev, type, key_code, 0, 0, NULL);
74405b261ecSmrg}
74505b261ecSmrg
74605b261ecSmrg
74705b261ecSmrg/**
74805b261ecSmrg * Returns a set of keyboard events for KeyPress/KeyRelease, optionally
74905b261ecSmrg * also with valuator events.  Handles Xi and XKB.
75005b261ecSmrg *
7514642e01fSmrg * DOES NOT GENERATE CORE EVENTS! Core events are created when processing the
7524642e01fSmrg * event (ProcessOtherEvent).
7534642e01fSmrg *
75405b261ecSmrg * events is not NULL-terminated; the return value is the number of events.
75505b261ecSmrg * The DDX is responsible for allocating the event structure in the first
75605b261ecSmrg * place via GetMaximumEventsNum(), and for freeing it.
75705b261ecSmrg *
75805b261ecSmrg * This function does not change the core keymap to that of the device;
75905b261ecSmrg * that is done by SwitchCoreKeyboard, which is called from
76005b261ecSmrg * mieqProcessInputEvents.  If replacing that function, take care to call
76105b261ecSmrg * SetCoreKeyboard before processInputProc, so keymaps are altered to suit.
76205b261ecSmrg *
76305b261ecSmrg * Note that this function recurses!  If called for non-XKB, a repeating
76405b261ecSmrg * key press will trigger a matching KeyRelease, as well as the
76505b261ecSmrg * KeyPresses.
76605b261ecSmrg */
76705b261ecSmrg_X_EXPORT int
7684642e01fSmrgGetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
76905b261ecSmrg                          int key_code, int first_valuator,
77005b261ecSmrg                          int num_valuators, int *valuators) {
77105b261ecSmrg    int numEvents = 0;
77205b261ecSmrg    CARD32 ms = 0;
7734642e01fSmrg    KeySym *map;
7744642e01fSmrg    KeySym sym;
77505b261ecSmrg    deviceKeyButtonPointer *kbp = NULL;
77605b261ecSmrg
7774642e01fSmrg    if (!events ||!pDev->key || !pDev->focus || !pDev->kbdfeed ||
7784642e01fSmrg       (type != KeyPress && type != KeyRelease) ||
7794642e01fSmrg       (key_code < 8 || key_code > 255))
78005b261ecSmrg        return 0;
78105b261ecSmrg
7824642e01fSmrg    numEvents = 1;
78305b261ecSmrg
7844642e01fSmrg    map = pDev->key->curKeySyms.map;
7854642e01fSmrg    sym = map[(key_code - pDev->key->curKeySyms.minKeyCode)
7864642e01fSmrg              * pDev->key->curKeySyms.mapWidth];
78705b261ecSmrg
7884642e01fSmrg    events = updateFromMaster(events, pDev, &numEvents);
78905b261ecSmrg
7904642e01fSmrg    numEvents += countValuatorEvents(num_valuators);
79105b261ecSmrg
79205b261ecSmrg#ifdef XKB
79305b261ecSmrg    if (noXkbExtension)
79405b261ecSmrg#endif
79505b261ecSmrg    {
79605b261ecSmrg        switch (sym) {
79705b261ecSmrg            case XK_Num_Lock:
79805b261ecSmrg            case XK_Caps_Lock:
79905b261ecSmrg            case XK_Scroll_Lock:
80005b261ecSmrg            case XK_Shift_Lock:
80105b261ecSmrg                if (type == KeyRelease)
80205b261ecSmrg                    return 0;
80305b261ecSmrg                else if (type == KeyPress && key_is_down(pDev, key_code))
80405b261ecSmrg                    type = KeyRelease;
80505b261ecSmrg        }
80605b261ecSmrg    }
80705b261ecSmrg
80805b261ecSmrg    /* Handle core repeating, via press/release/press/release.
80905b261ecSmrg     * FIXME: In theory, if you're repeating with two keyboards in non-XKB,
81005b261ecSmrg     *        you could get unbalanced events here. */
81105b261ecSmrg    if (type == KeyPress && key_is_down(pDev, key_code)) {
81205b261ecSmrg        /* If autorepeating is disabled either globally or just for that key,
81305b261ecSmrg         * or we have a modifier, don't generate a repeat event. */
81405b261ecSmrg        if (!pDev->kbdfeed->ctrl.autoRepeat ||
81505b261ecSmrg            !key_autorepeats(pDev, key_code) ||
81605b261ecSmrg            pDev->key->modifierMap[key_code])
81705b261ecSmrg            return 0;
81805b261ecSmrg
81905b261ecSmrg#ifdef XKB
82005b261ecSmrg        if (noXkbExtension)
82105b261ecSmrg#endif
82205b261ecSmrg        {
8234642e01fSmrg            int numReleaseEvents;
8244642e01fSmrg
8254642e01fSmrg            numReleaseEvents = GetKeyboardValuatorEvents(events, pDev,
8264642e01fSmrg                                                         KeyRelease, key_code,
8274642e01fSmrg                                                         first_valuator,
8284642e01fSmrg                                                         num_valuators,
8294642e01fSmrg                                                         valuators);
8304642e01fSmrg            numEvents += numReleaseEvents;
8314642e01fSmrg            events += numReleaseEvents;
83205b261ecSmrg        }
83305b261ecSmrg    }
83405b261ecSmrg
83505b261ecSmrg    ms = GetTimeInMillis();
83605b261ecSmrg
8374642e01fSmrg    kbp = (deviceKeyButtonPointer *) events->event;
83805b261ecSmrg    kbp->time = ms;
83905b261ecSmrg    kbp->deviceid = pDev->id;
84005b261ecSmrg    kbp->detail = key_code;
84105b261ecSmrg    if (type == KeyPress) {
84205b261ecSmrg        kbp->type = DeviceKeyPress;
84305b261ecSmrg	set_key_down(pDev, key_code);
84405b261ecSmrg    }
84505b261ecSmrg    else if (type == KeyRelease) {
84605b261ecSmrg        kbp->type = DeviceKeyRelease;
84705b261ecSmrg	set_key_up(pDev, key_code);
84805b261ecSmrg    }
84905b261ecSmrg
85005b261ecSmrg    events++;
85105b261ecSmrg    if (num_valuators) {
85205b261ecSmrg        kbp->deviceid |= MORE_EVENTS;
85305b261ecSmrg        clipValuators(pDev, first_valuator, num_valuators, valuators);
85405b261ecSmrg        events = getValuatorEvents(events, pDev, first_valuator,
85505b261ecSmrg                                   num_valuators, valuators);
85605b261ecSmrg    }
85705b261ecSmrg
85805b261ecSmrg    return numEvents;
85905b261ecSmrg}
86005b261ecSmrg
8614642e01fSmrg/**
8624642e01fSmrg * Initialize an event list and fill with 32 byte sized events.
8634642e01fSmrg * This event list is to be passed into GetPointerEvents() and
8644642e01fSmrg * GetKeyboardEvents().
8654642e01fSmrg *
8664642e01fSmrg * @param num_events Number of elements in list.
8674642e01fSmrg */
8684642e01fSmrgEventListPtr
8694642e01fSmrgInitEventList(int num_events)
8704642e01fSmrg{
8714642e01fSmrg    EventListPtr events;
8724642e01fSmrg    int i;
8734642e01fSmrg
8744642e01fSmrg    events = (EventListPtr)xcalloc(num_events, sizeof(EventList));
8754642e01fSmrg    if (!events)
8764642e01fSmrg        return NULL;
8774642e01fSmrg
8784642e01fSmrg    for (i = 0; i < num_events; i++)
8794642e01fSmrg    {
8804642e01fSmrg        events[i].evlen = sizeof(xEvent);
8814642e01fSmrg        events[i].event = xcalloc(1, sizeof(xEvent));
8824642e01fSmrg        if (!events[i].event)
8834642e01fSmrg        {
8844642e01fSmrg            /* rollback */
8854642e01fSmrg            while(i--)
8864642e01fSmrg                xfree(events[i].event);
8874642e01fSmrg            xfree(events);
8884642e01fSmrg            events = NULL;
8894642e01fSmrg            break;
8904642e01fSmrg        }
8914642e01fSmrg    }
8924642e01fSmrg
8934642e01fSmrg    return events;
8944642e01fSmrg}
8954642e01fSmrg
8964642e01fSmrg/**
8974642e01fSmrg * Allocs min_size memory for each event in the list.
8984642e01fSmrg */
8994642e01fSmrg_X_EXPORT void
9004642e01fSmrgSetMinimumEventSize(EventListPtr list, int num_events, int min_size)
9014642e01fSmrg{
9024642e01fSmrg    if (!list)
9034642e01fSmrg        return;
9044642e01fSmrg
9054642e01fSmrg    while(num_events--)
9064642e01fSmrg    {
9074642e01fSmrg        if (list[num_events].evlen < min_size)
9084642e01fSmrg        {
9094642e01fSmrg            list[num_events].evlen = min_size;
9104642e01fSmrg            list[num_events].event = realloc(list[num_events].event, min_size);
9114642e01fSmrg            if (!list[num_events].event)
9124642e01fSmrg            {
9134642e01fSmrg                FatalError("[dix] Failed to set event list's "
9144642e01fSmrg                        "min_size to %d.\n", min_size);
9154642e01fSmrg            }
9164642e01fSmrg        }
9174642e01fSmrg    }
9184642e01fSmrg}
9194642e01fSmrg
9204642e01fSmrg/**
9214642e01fSmrg * Free an event list.
9224642e01fSmrg *
9234642e01fSmrg * @param list The list to be freed.
9244642e01fSmrg * @param num_events Number of elements in list.
9254642e01fSmrg */
9264642e01fSmrg_X_EXPORT void
9274642e01fSmrgFreeEventList(EventListPtr list, int num_events)
9284642e01fSmrg{
9294642e01fSmrg    if (!list)
9304642e01fSmrg        return;
9314642e01fSmrg    while(num_events--)
9324642e01fSmrg        xfree(list[num_events].event);
9334642e01fSmrg    xfree(list);
9344642e01fSmrg}
93505b261ecSmrg
93605b261ecSmrg/**
9374642e01fSmrg * Generate a series of xEvents (filled into the EventList) representing
9384642e01fSmrg * pointer motion, or button presses.  Xi and XKB-aware.
9394642e01fSmrg *
9404642e01fSmrg * DOES NOT GENERATE CORE EVENTS! Core events are created when processing the
9414642e01fSmrg * event (ProcessOtherEvent).
94205b261ecSmrg *
94305b261ecSmrg * events is not NULL-terminated; the return value is the number of events.
94405b261ecSmrg * The DDX is responsible for allocating the event structure in the first
9454642e01fSmrg * place via InitEventList() and GetMaximumEventsNum(), and for freeing it.
9464642e01fSmrg *
9474642e01fSmrg * In the generated events rootX/Y will be in absolute screen coords and
9484642e01fSmrg * the valuator information in the absolute or relative device coords.
9494642e01fSmrg *
9504642e01fSmrg * last.valuators[x] of the device is always in absolute device coords.
9514642e01fSmrg * last.valuators[x] of the master device is in absolute screen coords.
9524642e01fSmrg *
9534642e01fSmrg * master->last.valuators[x] for x > 2 is undefined.
95405b261ecSmrg */
95505b261ecSmrg_X_EXPORT int
9564642e01fSmrgGetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
95705b261ecSmrg                 int flags, int first_valuator, int num_valuators,
95805b261ecSmrg                 int *valuators) {
9594642e01fSmrg    int num_events = 1;
9604642e01fSmrg    CARD32 ms;
96105b261ecSmrg    deviceKeyButtonPointer *kbp = NULL;
9624642e01fSmrg    int x, y, /* switches between device and screen coords */
9634642e01fSmrg        cx, cy; /* only screen coordinates */
96405b261ecSmrg    ScreenPtr scr = miPointerGetScreen(pDev);
96505b261ecSmrg
9664642e01fSmrg    ms = GetTimeInMillis(); /* before pointer update to help precision */
96705b261ecSmrg
9684642e01fSmrg    if (!scr || !pDev->valuator || first_valuator < 0 ||
9694642e01fSmrg        ((num_valuators + first_valuator) > pDev->valuator->numAxes) ||
9704642e01fSmrg        (type != MotionNotify && type != ButtonPress && type != ButtonRelease) ||
9714642e01fSmrg        (type != MotionNotify && !pDev->button) ||
9724642e01fSmrg        (type == MotionNotify && num_valuators <= 0))
97305b261ecSmrg        return 0;
97405b261ecSmrg
9754642e01fSmrg    num_events += countValuatorEvents(num_valuators);
97605b261ecSmrg
9774642e01fSmrg    events = updateFromMaster(events, pDev, &num_events);
97805b261ecSmrg
9794642e01fSmrg    if (flags & POINTER_ABSOLUTE)
9804642e01fSmrg    {
9814642e01fSmrg        if (flags & POINTER_SCREEN) /* valuators are in screen coords */
9824642e01fSmrg        {
98305b261ecSmrg
9844642e01fSmrg            valuators[0] = rescaleValuatorAxis(valuators[0], NULL,
9854642e01fSmrg                                               pDev->valuator->axes + 0,
9864642e01fSmrg                                               scr->width);
9874642e01fSmrg            valuators[1] = rescaleValuatorAxis(valuators[1], NULL,
9884642e01fSmrg                                               pDev->valuator->axes + 1,
9894642e01fSmrg                                               scr->height);
99005b261ecSmrg        }
99105b261ecSmrg
9924642e01fSmrg        moveAbsolute(pDev, &x, &y, first_valuator, num_valuators, valuators);
9934642e01fSmrg    } else {
99405b261ecSmrg        if (flags & POINTER_ACCELERATE)
9954642e01fSmrg            accelPointer(pDev, first_valuator, num_valuators, valuators, ms);
9964642e01fSmrg        moveRelative(pDev, &x, &y, first_valuator, num_valuators, valuators);
99705b261ecSmrg    }
99805b261ecSmrg
9994642e01fSmrg    positionSprite(pDev, &x, &y, scr, &cx, &cy);
10004642e01fSmrg    updateHistory(pDev, first_valuator, num_valuators, ms);
100105b261ecSmrg
100205b261ecSmrg
10034642e01fSmrg    /* Update the valuators with the true value sent to the client*/
10044642e01fSmrg    if (num_valuators >= 1 && first_valuator == 0)
10054642e01fSmrg        valuators[0] = x;
100605b261ecSmrg    if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
10074642e01fSmrg        valuators[1 - first_valuator] = y;
100805b261ecSmrg
10094642e01fSmrg    kbp = (deviceKeyButtonPointer *) events->event;
10104642e01fSmrg    kbp->time = ms;
10114642e01fSmrg    kbp->deviceid = pDev->id;
101205b261ecSmrg
10134642e01fSmrg    if (type == MotionNotify) {
10144642e01fSmrg        kbp->type = DeviceMotionNotify;
10154642e01fSmrg    }
10164642e01fSmrg    else {
10174642e01fSmrg        if (type == ButtonPress)
10184642e01fSmrg            kbp->type = DeviceButtonPress;
10194642e01fSmrg        else if (type == ButtonRelease)
10204642e01fSmrg            kbp->type = DeviceButtonRelease;
10214642e01fSmrg        kbp->detail = buttons;
10224642e01fSmrg    }
102305b261ecSmrg
10244642e01fSmrg    kbp->root_x = cx; /* root_x/y always in screen coords */
10254642e01fSmrg    kbp->root_y = cy;
102605b261ecSmrg
10274642e01fSmrg    events++;
10284642e01fSmrg    if (num_valuators) {
10294642e01fSmrg        kbp->deviceid |= MORE_EVENTS;
10304642e01fSmrg        if (flags & POINTER_ABSOLUTE)
103105b261ecSmrg            clipValuators(pDev, first_valuator, num_valuators, valuators);
10324642e01fSmrg        events = getValuatorEvents(events, pDev, first_valuator,
10334642e01fSmrg                                   num_valuators, valuators);
103405b261ecSmrg    }
103505b261ecSmrg
103605b261ecSmrg    return num_events;
103705b261ecSmrg}
103805b261ecSmrg
103905b261ecSmrg
104005b261ecSmrg/**
104105b261ecSmrg * Post ProximityIn/ProximityOut events, accompanied by valuators.
104205b261ecSmrg *
104305b261ecSmrg * events is not NULL-terminated; the return value is the number of events.
104405b261ecSmrg * The DDX is responsible for allocating the event structure in the first
104505b261ecSmrg * place via GetMaximumEventsNum(), and for freeing it.
104605b261ecSmrg */
104705b261ecSmrg_X_EXPORT int
10484642e01fSmrgGetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
104905b261ecSmrg                   int first_valuator, int num_valuators, int *valuators)
105005b261ecSmrg{
105105b261ecSmrg    int num_events = 1;
10524642e01fSmrg    deviceKeyButtonPointer *kbp;
10534642e01fSmrg    DeviceIntPtr master;
105405b261ecSmrg
105505b261ecSmrg    /* Sanity checks. */
105605b261ecSmrg    if (type != ProximityIn && type != ProximityOut)
105705b261ecSmrg        return 0;
105805b261ecSmrg    if (!pDev->valuator)
105905b261ecSmrg        return 0;
106005b261ecSmrg    /* Do we need to send a DeviceValuator event? */
106105b261ecSmrg    if ((pDev->valuator->mode & 1) == Relative)
106205b261ecSmrg        num_valuators = 0;
106305b261ecSmrg
106405b261ecSmrg    if (num_valuators) {
106505b261ecSmrg        if ((((num_valuators - 1) / 6) + 1) > MAX_VALUATOR_EVENTS)
106605b261ecSmrg            num_valuators = MAX_VALUATOR_EVENTS * 6;
106705b261ecSmrg        num_events += ((num_valuators - 1) / 6) + 1;
106805b261ecSmrg    }
106905b261ecSmrg
107005b261ecSmrg    /* You fail. */
107105b261ecSmrg    if (first_valuator < 0 ||
107205b261ecSmrg        (num_valuators + first_valuator) > pDev->valuator->numAxes)
107305b261ecSmrg        return 0;
107405b261ecSmrg
10754642e01fSmrg    master = pDev->u.master;
10764642e01fSmrg    if (master && master->u.lastSlave != pDev)
10774642e01fSmrg    {
10784642e01fSmrg        updateSlaveDeviceCoords(master, pDev);
10794642e01fSmrg        master->u.lastSlave = pDev;
10804642e01fSmrg        master->last.numValuators = pDev->last.numValuators;
10814642e01fSmrg    }
10824642e01fSmrg
10834642e01fSmrg    kbp = (deviceKeyButtonPointer *) events->event;
108405b261ecSmrg    kbp->type = type;
108505b261ecSmrg    kbp->deviceid = pDev->id;
108605b261ecSmrg    kbp->detail = 0;
108705b261ecSmrg    kbp->time = GetTimeInMillis();
108805b261ecSmrg
108905b261ecSmrg    if (num_valuators) {
109005b261ecSmrg        kbp->deviceid |= MORE_EVENTS;
109105b261ecSmrg        events++;
109205b261ecSmrg        clipValuators(pDev, first_valuator, num_valuators, valuators);
109305b261ecSmrg        events = getValuatorEvents(events, pDev, first_valuator,
109405b261ecSmrg                                   num_valuators, valuators);
109505b261ecSmrg    }
109605b261ecSmrg
109705b261ecSmrg    return num_events;
109805b261ecSmrg}
109905b261ecSmrg
110005b261ecSmrg/**
110105b261ecSmrg * Synthesize a single motion event for the core pointer.
110205b261ecSmrg *
110305b261ecSmrg * Used in cursor functions, e.g. when cursor confinement changes, and we need
110405b261ecSmrg * to shift the pointer to get it inside the new bounds.
110505b261ecSmrg */
110605b261ecSmrgvoid
11074642e01fSmrgPostSyntheticMotion(DeviceIntPtr pDev,
11084642e01fSmrg                    int x,
11094642e01fSmrg                    int y,
11104642e01fSmrg                    int screen,
11114642e01fSmrg                    unsigned long time)
111205b261ecSmrg{
111305b261ecSmrg    xEvent xE;
111405b261ecSmrg
111505b261ecSmrg#ifdef PANORAMIX
111605b261ecSmrg    /* Translate back to the sprite screen since processInputProc
111705b261ecSmrg       will translate from sprite screen to screen 0 upon reentry
111805b261ecSmrg       to the DIX layer. */
111905b261ecSmrg    if (!noPanoramiXExtension) {
112005b261ecSmrg        x += panoramiXdataPtr[0].x - panoramiXdataPtr[screen].x;
112105b261ecSmrg        y += panoramiXdataPtr[0].y - panoramiXdataPtr[screen].y;
112205b261ecSmrg    }
112305b261ecSmrg#endif
112405b261ecSmrg
112505b261ecSmrg    memset(&xE, 0, sizeof(xEvent));
112605b261ecSmrg    xE.u.u.type = MotionNotify;
112705b261ecSmrg    xE.u.keyButtonPointer.rootX = x;
112805b261ecSmrg    xE.u.keyButtonPointer.rootY = y;
112905b261ecSmrg    xE.u.keyButtonPointer.time = time;
113005b261ecSmrg
11314642e01fSmrg    (*pDev->public.processInputProc)(&xE, pDev, 1);
113205b261ecSmrg}
1133