From f851244b9298d88c29331ab285c2839d8bee6925 Mon Sep 17 00:00:00 2001
From: marha <marha@users.sourceforge.net>
Date: Thu, 16 Dec 2010 16:13:08 +0000
Subject: xserver libXdmcp git update 16-12-2010

---
 xorg-server/dix/getevents.c | 2632 ++++++++++++++++++++++---------------------
 1 file changed, 1323 insertions(+), 1309 deletions(-)

(limited to 'xorg-server/dix')

diff --git a/xorg-server/dix/getevents.c b/xorg-server/dix/getevents.c
index 96b5ce29c..794df420b 100644
--- a/xorg-server/dix/getevents.c
+++ b/xorg-server/dix/getevents.c
@@ -1,1309 +1,1323 @@
-/*
- * Copyright © 2006 Nokia Corporation
- * Copyright © 2006-2007 Daniel Stone
- * Copyright © 2008 Red Hat, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors: Daniel Stone <daniel@fooishbar.org>
- *          Peter Hutterer <peter.hutterer@who-t.net>
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/keysym.h>
-#include <X11/Xproto.h>
-#include <math.h>
-
-#include "misc.h"
-#include "resource.h"
-#include "inputstr.h"
-#include "scrnintstr.h"
-#include "cursorstr.h"
-#include "dixstruct.h"
-#include "globals.h"
-#include "dixevents.h"
-#include "mipointer.h"
-#include "eventstr.h"
-#include "eventconvert.h"
-#include "inpututils.h"
-
-#include <X11/extensions/XKBproto.h>
-#include "xkbsrv.h"
-
-#ifdef PANORAMIX
-#include "panoramiX.h"
-#include "panoramiXsrv.h"
-#endif
-
-#include <X11/extensions/XI.h>
-#include <X11/extensions/XIproto.h>
-#include <pixman.h>
-#include "exglobals.h"
-#include "exevents.h"
-#include "exglobals.h"
-#include "extnsionst.h"
-#include "listdev.h" /* for sizing up DeviceClassesChangedEvent */
-
-/* Number of motion history events to store. */
-#define MOTION_HISTORY_SIZE 256
-
-/* InputEventList is the container list for all input events generated by the
- * DDX. The DDX is expected to call GetEventList() and then pass the list into
- * Get{Pointer|Keyboard}Events.
- */
-EventListPtr InputEventList = NULL;
-int InputEventListLen = 0;
-
-int
-GetEventList(EventListPtr* list)
-{
-    *list = InputEventList;
-    return InputEventListLen;
-}
-
-/**
- * Pick some arbitrary size for Xi motion history.
- */
-int
-GetMotionHistorySize(void)
-{
-    return MOTION_HISTORY_SIZE;
-}
-
-void
-set_button_down(DeviceIntPtr pDev, int button, int type)
-{
-    if (type == BUTTON_PROCESSED)
-        SetBit(pDev->button->down, button);
-    else
-        SetBit(pDev->button->postdown, button);
-}
-
-void
-set_button_up(DeviceIntPtr pDev, int button, int type)
-{
-    if (type == BUTTON_PROCESSED)
-        ClearBit(pDev->button->down, button);
-    else
-        ClearBit(pDev->button->postdown, button);
-}
-
-Bool
-button_is_down(DeviceIntPtr pDev, int button, int type)
-{
-    Bool ret = FALSE;
-
-    if (type & BUTTON_PROCESSED)
-        ret = ret || BitIsOn(pDev->button->down, button);
-    if (type & BUTTON_POSTED)
-        ret = ret || BitIsOn(pDev->button->postdown, button);
-
-    return ret;
-}
-
-void
-set_key_down(DeviceIntPtr pDev, int key_code, int type)
-{
-    if (type == KEY_PROCESSED)
-        SetBit(pDev->key->down, key_code);
-    else
-        SetBit(pDev->key->postdown, key_code);
-}
-
-void
-set_key_up(DeviceIntPtr pDev, int key_code, int type)
-{
-    if (type == KEY_PROCESSED)
-        ClearBit(pDev->key->down, key_code);
-    else
-        ClearBit(pDev->key->postdown, key_code);
-}
-
-Bool
-key_is_down(DeviceIntPtr pDev, int key_code, int type)
-{
-    Bool ret = FALSE;
-
-    if (type & KEY_PROCESSED)
-        ret = ret || BitIsOn(pDev->key->down, key_code);
-    if (type & KEY_POSTED)
-        ret = ret || BitIsOn(pDev->key->postdown, key_code);
-
-    return ret;
-}
-
-static Bool
-key_autorepeats(DeviceIntPtr pDev, int key_code)
-{
-    return !!(pDev->kbdfeed->ctrl.autoRepeats[key_code >> 3] &
-              (1 << (key_code & 7)));
-}
-
-static void
-init_event(DeviceIntPtr dev, DeviceEvent* event, Time ms)
-{
-    memset(event, 0, sizeof(DeviceEvent));
-    event->header = ET_Internal;
-    event->length = sizeof(DeviceEvent);
-    event->time = ms;
-    event->deviceid = dev->id;
-    event->sourceid = dev->id;
-}
-
-static void
-init_raw(DeviceIntPtr dev, RawDeviceEvent *event, Time ms, int type, int detail)
-{
-    memset(event, 0, sizeof(RawDeviceEvent));
-    event->header = ET_Internal;
-    event->length = sizeof(RawDeviceEvent);
-    event->type = ET_RawKeyPress - ET_KeyPress + type;
-    event->time = ms;
-    event->deviceid = dev->id;
-    event->sourceid = dev->id;
-    event->detail.button = detail;
-}
-
-static void
-set_raw_valuators(RawDeviceEvent *event, ValuatorMask *mask, int32_t* data)
-{
-    int i;
-
-    for (i = 0; i < valuator_mask_size(mask); i++)
-    {
-        if (valuator_mask_isset(mask, i))
-        {
-            SetBit(event->valuators.mask, i);
-            data[i] = valuator_mask_get(mask, i);
-        }
-    }
-}
-
-
-static void
-set_valuators(DeviceIntPtr dev, DeviceEvent* event, ValuatorMask *mask)
-{
-    int i;
-
-    for (i = 0; i < valuator_mask_size(mask); i++)
-    {
-        if (valuator_mask_isset(mask, i))
-        {
-            SetBit(event->valuators.mask, i);
-            if (valuator_get_mode(dev, i) == Absolute)
-                SetBit(event->valuators.mode, i);
-            event->valuators.data[i] = valuator_mask_get(mask, i);
-            event->valuators.data_frac[i] =
-                dev->last.remainder[i] * (1 << 16) * (1 << 16);
-        }
-    }
-}
-
-void
-CreateClassesChangedEvent(EventList* event,
-                          DeviceIntPtr master,
-                          DeviceIntPtr slave,
-                          int type)
-{
-    int i;
-    DeviceChangedEvent *dce;
-    CARD32 ms = GetTimeInMillis();
-
-    dce = (DeviceChangedEvent*)event->event;
-    memset(dce, 0, sizeof(DeviceChangedEvent));
-    dce->deviceid = slave->id;
-    dce->masterid = master->id;
-    dce->header = ET_Internal;
-    dce->length = sizeof(DeviceChangedEvent);
-    dce->type = ET_DeviceChanged;
-    dce->time = ms;
-    dce->flags = type;
-    dce->flags |= DEVCHANGE_SLAVE_SWITCH;
-    dce->sourceid = slave->id;
-
-    if (slave->button)
-    {
-        dce->buttons.num_buttons = slave->button->numButtons;
-        for (i = 0; i < dce->buttons.num_buttons; i++)
-            dce->buttons.names[i] = slave->button->labels[i];
-    }
-    if (slave->valuator)
-    {
-        dce->num_valuators = slave->valuator->numAxes;
-        for (i = 0; i < dce->num_valuators; i++)
-        {
-            dce->valuators[i].min = slave->valuator->axes[i].min_value;
-            dce->valuators[i].max = slave->valuator->axes[i].max_value;
-            dce->valuators[i].resolution = slave->valuator->axes[i].resolution;
-            dce->valuators[i].mode = slave->valuator->axes[i].mode;
-            dce->valuators[i].name = slave->valuator->axes[i].label;
-        }
-    }
-    if (slave->key)
-    {
-        dce->keys.min_keycode = slave->key->xkbInfo->desc->min_key_code;
-        dce->keys.max_keycode = slave->key->xkbInfo->desc->max_key_code;
-    }
-}
-
-/**
- * Rescale the coord between the two axis ranges.
- */
-static int
-rescaleValuatorAxis(int coord, float remainder, float *remainder_return, AxisInfoPtr from, AxisInfoPtr to,
-                    int defmax)
-{
-    int fmin = 0, tmin = 0, fmax = defmax, tmax = defmax, coord_return;
-    float value;
-
-    if(from && from->min_value < from->max_value) {
-        fmin = from->min_value;
-        fmax = from->max_value;
-    }
-    if(to && to->min_value < to->max_value) {
-        tmin = to->min_value;
-        tmax = to->max_value;
-    }
-
-    if(fmin == tmin && fmax == tmax) {
-        if (remainder_return)
-            *remainder_return = remainder;
-        return coord;
-    }
-
-    if(fmax == fmin) { /* avoid division by 0 */
-        if (remainder_return)
-            *remainder_return = 0.0;
-        return 0;
-    }
-
-    value = (coord + remainder - fmin) * (tmax - tmin) / (fmax - fmin) + tmin;
-    coord_return = lroundf(value);
-    if (remainder_return)
-        *remainder_return = value - coord_return;
-    return coord_return;
-}
-
-/**
- * Update all coordinates when changing to a different SD
- * to ensure that relative reporting will work as expected
- * without loss of precision.
- *
- * pDev->last.valuators will be in absolute device coordinates after this
- * function.
- */
-static void
-updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
-{
-    ScreenPtr scr = miPointerGetScreen(pDev);
-    int i;
-    DeviceIntPtr lastSlave;
-
-    /* master->last.valuators[0]/[1] is in screen coords and the actual
-     * position of the pointer */
-    pDev->last.valuators[0] = master->last.valuators[0];
-    pDev->last.valuators[1] = master->last.valuators[1];
-
-    if (!pDev->valuator)
-        return;
-
-    /* scale back to device coordinates */
-    if(pDev->valuator->numAxes > 0)
-        pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0], pDev->last.remainder[0],
-                        &pDev->last.remainder[0], NULL, pDev->valuator->axes + 0, scr->width);
-    if(pDev->valuator->numAxes > 1)
-        pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1], pDev->last.remainder[1],
-                        &pDev->last.remainder[1], NULL, pDev->valuator->axes + 1, scr->height);
-
-    /* calculate the other axis as well based on info from the old
-     * slave-device. If the old slave had less axes than this one,
-     * last.valuators is reset to 0.
-     */
-    if ((lastSlave = master->last.slave) && lastSlave->valuator) {
-        for (i = 2; i < pDev->valuator->numAxes; i++) {
-            if (i >= lastSlave->valuator->numAxes)
-                pDev->last.valuators[i] = 0;
-            else
-                pDev->last.valuators[i] =
-                    rescaleValuatorAxis(pDev->last.valuators[i],
-                            pDev->last.remainder[i],
-                            &pDev->last.remainder[i],
-                            lastSlave->valuator->axes + i,
-                            pDev->valuator->axes + i, 0);
-        }
-    }
-
-}
-
-/**
- * Allocate the motion history buffer.
- */
-void
-AllocateMotionHistory(DeviceIntPtr pDev)
-{
-    int size;
-    free(pDev->valuator->motion);
-
-    if (pDev->valuator->numMotionEvents < 1)
-        return;
-
-    /* An MD must have a motion history size large enough to keep all
-     * potential valuators, plus the respective range of the valuators.
-     * 3 * INT32 for (min_val, max_val, curr_val))
-     */
-    if (IsMaster(pDev))
-        size = sizeof(INT32) * 3 * MAX_VALUATORS;
-    else {
-        ValuatorClassPtr v = pDev->valuator;
-        int numAxes;
-        /* XI1 doesn't understand mixed mode devices */
-        for (numAxes = 0; numAxes < v->numAxes; numAxes++)
-            if (valuator_get_mode(pDev, numAxes) != valuator_get_mode(pDev, 0))
-                break;
-        size = sizeof(INT32) * numAxes;
-    }
-
-    size += sizeof(Time);
-
-    pDev->valuator->motion = calloc(pDev->valuator->numMotionEvents, size);
-    pDev->valuator->first_motion = 0;
-    pDev->valuator->last_motion = 0;
-    if (!pDev->valuator->motion)
-        ErrorF("[dix] %s: Failed to alloc motion history (%d bytes).\n",
-                pDev->name, size * pDev->valuator->numMotionEvents);
-}
-
-/**
- * Dump the motion history between start and stop into the supplied buffer.
- * Only records the event for a given screen in theory, but in practice, we
- * sort of ignore this.
- *
- * If core is set, we only generate x/y, in INT16, scaled to screen coords.
- */
-int
-GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
-                 unsigned long stop, ScreenPtr pScreen, BOOL core)
-{
-    char *ibuff = NULL, *obuff;
-    int i = 0, ret = 0;
-    int j, coord;
-    Time current;
-    /* The size of a single motion event. */
-    int size;
-    int dflt;
-    AxisInfo from, *to; /* for scaling */
-    INT32 *ocbuf, *icbuf; /* pointer to coordinates for copying */
-    INT16 *corebuf;
-    AxisInfo core_axis = {0};
-
-    if (!pDev->valuator || !pDev->valuator->numMotionEvents)
-        return 0;
-
-    if (core && !pScreen)
-        return 0;
-
-    if (IsMaster(pDev))
-        size = (sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(Time);
-    else
-        size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
-
-    *buff = malloc(size * pDev->valuator->numMotionEvents);
-    if (!(*buff))
-        return 0;
-    obuff = (char *)*buff;
-
-    for (i = pDev->valuator->first_motion;
-         i != pDev->valuator->last_motion;
-         i = (i + 1) % pDev->valuator->numMotionEvents) {
-        /* We index the input buffer by which element we're accessing, which
-         * is not monotonic, and the output buffer by how many events we've
-         * written so far. */
-        ibuff = (char *) pDev->valuator->motion + (i * size);
-        memcpy(&current, ibuff, sizeof(Time));
-
-        if (current > stop) {
-            return ret;
-        }
-        else if (current >= start) {
-            if (core)
-            {
-                memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */
-
-                icbuf = (INT32*)(ibuff + sizeof(Time));
-                corebuf = (INT16*)(obuff + sizeof(Time));
-
-                /* fetch x coordinate + range */
-                memcpy(&from.min_value, icbuf++, sizeof(INT32));
-                memcpy(&from.max_value, icbuf++, sizeof(INT32));
-                memcpy(&coord, icbuf++, sizeof(INT32));
-
-                /* scale to screen coords */
-                to = &core_axis;
-                to->max_value = pScreen->width;
-                coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->width);
-
-                memcpy(corebuf, &coord, sizeof(INT16));
-                corebuf++;
-
-                /* fetch y coordinate + range */
-                memcpy(&from.min_value, icbuf++, sizeof(INT32));
-                memcpy(&from.max_value, icbuf++, sizeof(INT32));
-                memcpy(&coord, icbuf++, sizeof(INT32));
-
-                to->max_value = pScreen->height;
-                coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->height);
-                memcpy(corebuf, &coord, sizeof(INT16));
-
-            } else if (IsMaster(pDev))
-            {
-                memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */
-
-                ocbuf = (INT32*)(obuff + sizeof(Time));
-                icbuf = (INT32*)(ibuff + sizeof(Time));
-                for (j = 0; j < MAX_VALUATORS; j++)
-                {
-                    if (j >= pDev->valuator->numAxes)
-                        break;
-
-                    /* fetch min/max/coordinate */
-                    memcpy(&from.min_value, icbuf++, sizeof(INT32));
-                    memcpy(&from.max_value, icbuf++, sizeof(INT32));
-                    memcpy(&coord, icbuf++, sizeof(INT32));
-
-                    to = (j < pDev->valuator->numAxes) ? &pDev->valuator->axes[j] : NULL;
-
-                    /* x/y scaled to screen if no range is present */
-                    if (j == 0 && (from.max_value < from.min_value))
-                        from.max_value = pScreen->width;
-                    else if (j == 1 && (from.max_value < from.min_value))
-                        from.max_value = pScreen->height;
-
-                    if (j == 0 && (to->max_value < to->min_value))
-                        dflt = pScreen->width;
-                    else if (j == 1 && (to->max_value < to->min_value))
-                        dflt = pScreen->height;
-                    else
-                        dflt = 0;
-
-                    /* scale from stored range into current range */
-                    coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, 0);
-                    memcpy(ocbuf, &coord, sizeof(INT32));
-                    ocbuf++;
-                }
-            } else
-                memcpy(obuff, ibuff, size);
-
-            /* don't advance by size here. size may be different to the
-             * actually written size if the MD has less valuators than MAX */
-            if (core)
-                obuff += sizeof(INT32) + sizeof(Time);
-            else
-                obuff += (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
-            ret++;
-        }
-    }
-
-    return ret;
-}
-
-
-/**
- * Update the motion history for a specific device, with the list of
- * valuators.
- *
- * Layout of the history buffer:
- *   for SDs: [time] [val0] [val1] ... [valn]
- *   for MDs: [time] [min_val0] [max_val0] [val0] [min_val1] ... [valn]
- *
- * For events that have some valuators unset:
- *      min_val == max_val == val == 0.
- */
-static void
-updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, ValuatorMask *mask,
-                    int *valuators)
-{
-    char *buff = (char *) pDev->valuator->motion;
-    ValuatorClassPtr v;
-    int i;
-
-    if (!pDev->valuator->numMotionEvents)
-        return;
-
-    v = pDev->valuator;
-    if (IsMaster(pDev))
-    {
-        buff += ((sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(CARD32)) *
-                v->last_motion;
-
-        memcpy(buff, &ms, sizeof(Time));
-        buff += sizeof(Time);
-
-        memset(buff, 0, sizeof(INT32) * 3 * MAX_VALUATORS);
-
-        for (i = 0; i < v->numAxes; i++)
-        {
-            /* XI1 doesn't support mixed mode devices */
-            if (valuator_get_mode(pDev, i) != valuator_get_mode(pDev, 0))
-                break;
-            if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i))
-            {
-                buff += 3 * sizeof(INT32);
-                continue;
-            }
-            memcpy(buff, &v->axes[i].min_value, sizeof(INT32));
-            buff += sizeof(INT32);
-            memcpy(buff, &v->axes[i].max_value, sizeof(INT32));
-            buff += sizeof(INT32);
-            memcpy(buff, &valuators[i], sizeof(INT32));
-            buff += sizeof(INT32);
-        }
-    } else
-    {
-
-        buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) *
-            pDev->valuator->last_motion;
-
-        memcpy(buff, &ms, sizeof(Time));
-        buff += sizeof(Time);
-
-        memset(buff, 0, sizeof(INT32) * pDev->valuator->numAxes);
-
-        for (i = 0; i < MAX_VALUATORS; i++)
-        {
-            if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i))
-            {
-                buff += sizeof(INT32);
-                continue;
-            }
-            memcpy(buff, &valuators[i], sizeof(INT32));
-            buff += sizeof(INT32);
-        }
-    }
-
-    pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) %
-        pDev->valuator->numMotionEvents;
-    /* If we're wrapping around, just keep the circular buffer going. */
-    if (pDev->valuator->first_motion == pDev->valuator->last_motion)
-        pDev->valuator->first_motion = (pDev->valuator->first_motion + 1) %
-                                       pDev->valuator->numMotionEvents;
-
-    return;
-}
-
-
-/**
- * Returns the maximum number of events GetKeyboardEvents,
- * GetKeyboardValuatorEvents, and GetPointerEvents will ever return.
- *
- * This MUST be absolutely constant, from init until exit.
- */
-int
-GetMaximumEventsNum(void) {
-    /* One raw event
-     * One device event
-     * One possible device changed event
-     */
-    return 3;
-}
-
-
-/**
- * Clip an axis to its bounds, which are declared in the call to
- * InitValuatorAxisClassStruct.
- */
-static void
-clipAxis(DeviceIntPtr pDev, int axisNum, int *val)
-{
-    AxisInfoPtr axis;
-
-    if (axisNum >= pDev->valuator->numAxes)
-        return;
-
-    axis = pDev->valuator->axes + axisNum;
-
-    /* If a value range is defined, clip. If not, do nothing */
-    if (axis->max_value <= axis->min_value)
-        return;
-
-    if (*val < axis->min_value)
-        *val = axis->min_value;
-    if (*val > axis->max_value)
-        *val = axis->max_value;
-}
-
-/**
- * Clip every axis in the list of valuators to its bounds.
- */
-static void
-clipValuators(DeviceIntPtr pDev, ValuatorMask *mask)
-{
-    int i;
-
-    for (i = 0; i < valuator_mask_size(mask); i++)
-        if (valuator_mask_isset(mask, i))
-        {
-            int val = valuator_mask_get(mask, i);
-            clipAxis(pDev, i, &val);
-            valuator_mask_set(mask, i, val);
-        }
-}
-
-/**
- * Create the DCCE event (does not update the master's device state yet, this
- * is done in the event processing).
- * Pull in the coordinates from the MD if necessary.
- *
- * @param events Pointer to a pre-allocated event list.
- * @param dev The slave device that generated an event.
- * @param type Either DEVCHANGE_POINTER_EVENT and/or DEVCHANGE_KEYBOARD_EVENT
- * @param num_events The current number of events, returns the number of
- *        events if a DCCE was generated.
- * @return The updated @events pointer.
- */
-EventListPtr
-UpdateFromMaster(EventListPtr events, DeviceIntPtr dev, int type, int *num_events)
-{
-    DeviceIntPtr master;
-
-    master = GetMaster(dev, (type & DEVCHANGE_POINTER_EVENT) ?  MASTER_POINTER : MASTER_KEYBOARD);
-
-    if (master && master->last.slave != dev)
-    {
-        CreateClassesChangedEvent(events, master, dev, type);
-        if (IsPointerDevice(master))
-        {
-            updateSlaveDeviceCoords(master, dev);
-            master->last.numValuators = dev->last.numValuators;
-        }
-        master->last.slave = dev;
-        (*num_events)++;
-        events++;
-    }
-    return events;
-}
-
-/**
- * Move the device's pointer to the position given in the valuators.
- *
- * @param dev The device which's pointer is to be moved.
- * @param x Returns the x position of the pointer after the move.
- * @param y Returns the y position of the pointer after the move.
- * @param mask Bit mask of valid valuators.
- * @param valuators Valuator data for each axis between @first and
- *        @first+@num.
- */
-static void
-moveAbsolute(DeviceIntPtr dev, int *x, int *y, ValuatorMask *mask)
-{
-    int i;
-
-    if (valuator_mask_isset(mask, 0))
-        *x = valuator_mask_get(mask, 0);
-    else
-        *x = dev->last.valuators[0];
-
-    if (valuator_mask_isset(mask, 1))
-        *y = valuator_mask_get(mask, 1);
-    else
-        *y = dev->last.valuators[1];
-
-    clipAxis(dev, 0, x);
-    clipAxis(dev, 1, y);
-
-    for (i = 2; i < valuator_mask_size(mask); i++)
-    {
-        if (valuator_mask_isset(mask, i))
-        {
-            dev->last.valuators[i] = valuator_mask_get(mask, i);
-            clipAxis(dev, i, &dev->last.valuators[i]);
-        }
-    }
-}
-
-/**
- * Move the device's pointer by the values given in @valuators.
- *
- * @param dev The device which's pointer is to be moved.
- * @param x Returns the x position of the pointer after the move.
- * @param y Returns the y position of the pointer after the move.
- * @param mask Bit mask of valid valuators.
- * @param valuators Valuator data for each axis between @first and
- *        @first+@num.
- */
-static void
-moveRelative(DeviceIntPtr dev, int *x, int *y, ValuatorMask *mask)
-{
-    int i;
-
-    *x = dev->last.valuators[0];
-    *y = dev->last.valuators[1];
-
-    if (valuator_mask_isset(mask, 0))
-        *x += valuator_mask_get(mask, 0);
-
-    if (valuator_mask_isset(mask, 1))
-        *y += valuator_mask_get(mask, 1);
-
-    /* if attached, clip both x and y to the defined limits (usually
-     * co-ord space limit). If it is attached, we need x/y to go over the
-     * limits to be able to change screens. */
-    if(dev->u.master) {
-        if (valuator_get_mode(dev, 0) == Absolute)
-            clipAxis(dev, 0, x);
-        if (valuator_get_mode(dev, 1) == Absolute)
-            clipAxis(dev, 1, y);
-    }
-
-    /* calc other axes, clip, drop back into valuators */
-    for (i = 2; i < valuator_mask_size(mask); i++)
-    {
-        if (valuator_mask_isset(mask, i))
-        {
-            dev->last.valuators[i] += valuator_mask_get(mask, i);
-            if (valuator_get_mode(dev, i) == Absolute)
-                clipAxis(dev, i, &dev->last.valuators[i]);
-            valuator_mask_set(mask, i, dev->last.valuators[i]);
-        }
-    }
-}
-
-/**
- * Accelerate the data in valuators based on the device's acceleration scheme.
- *
- * @param dev The device which's pointer is to be moved.
- * @param first The first valuator in @valuators
- * @param num Total number of valuators in @valuators.
- * @param valuators Valuator data for each axis between @first and
- *        @first+@num.
- * @param ms Current time.
- */
-static void
-accelPointer(DeviceIntPtr dev, int first, int num, int *valuators, CARD32 ms)
-{
-    if (dev->valuator->accelScheme.AccelSchemeProc)
-        dev->valuator->accelScheme.AccelSchemeProc(dev, first, num, valuators, ms);
-}
-
-/**
- * If we have HW cursors, this actually moves the visible sprite. If not, we
- * just do all the screen crossing, etc.
- *
- * We scale from device to screen coordinates here, call
- * miPointerSetPosition() and then scale back into device coordinates (if
- * needed). miPSP will change x/y if the screen was crossed.
- *
- * @param dev The device to be moved.
- * @param x Pointer to current x-axis value, may be modified.
- * @param y Pointer to current y-axis value, may be modified.
- * @param x_frac Fractional part of current x-axis value, may be modified.
- * @param y_frac Fractional part of current y-axis value, may be modified.
- * @param scr Screen the device's sprite is currently on.
- * @param screenx Screen x coordinate the sprite is on after the update.
- * @param screeny Screen y coordinate the sprite is on after the update.
- * @param screenx_frac Fractional part of screen x coordinate, as above.
- * @param screeny_frac Fractional part of screen y coordinate, as above.
- */
-static void
-positionSprite(DeviceIntPtr dev, int *x, int *y, float x_frac, float y_frac,
-               ScreenPtr scr, int *screenx, int *screeny, float *screenx_frac, float *screeny_frac)
-{
-    int old_screenx, old_screeny;
-
-    /* scale x&y to screen */
-    if (dev->valuator->numAxes > 0) {
-        *screenx = rescaleValuatorAxis(*x, x_frac, screenx_frac,
-                dev->valuator->axes + 0, NULL, scr->width);
-    } else {
-        *screenx = dev->last.valuators[0];
-        *screenx_frac = dev->last.remainder[0];
-    }
-
-    if (dev->valuator->numAxes > 1) {
-        *screeny = rescaleValuatorAxis(*y, y_frac, screeny_frac,
-                dev->valuator->axes + 1, NULL, scr->height);
-    } else {
-        *screeny = dev->last.valuators[1];
-        *screeny_frac = dev->last.remainder[1];
-    }
-
-    /* Hit the left screen edge? */
-    if (*screenx <= 0 && *screenx_frac < 0.0f)
-    {
-        *screenx_frac = 0.0f;
-        x_frac = 0.0f;
-    }
-    if (*screeny <= 0 && *screeny_frac < 0.0f)
-    {
-        *screeny_frac = 0.0f;
-        y_frac = 0.0f;
-    }
-
-
-    old_screenx = *screenx;
-    old_screeny = *screeny;
-    /* This takes care of crossing screens for us, as well as clipping
-     * to the current screen. */
-    miPointerSetPosition(dev, screenx, screeny);
-
-    if (dev->u.master) {
-        dev->u.master->last.valuators[0] = *screenx;
-        dev->u.master->last.valuators[1] = *screeny;
-        dev->u.master->last.remainder[0] = *screenx_frac;
-        dev->u.master->last.remainder[1] = *screeny_frac;
-    }
-
-    /* Crossed screen? Scale back to device coordiantes */
-    if(*screenx != old_screenx)
-    {
-        scr = miPointerGetScreen(dev);
-        *x = rescaleValuatorAxis(*screenx, *screenx_frac, &x_frac, NULL,
-                                dev->valuator->axes + 0, scr->width);
-    }
-    if(*screeny != old_screeny)
-    {
-        scr = miPointerGetScreen(dev);
-        *y = rescaleValuatorAxis(*screeny, *screeny_frac, &y_frac, NULL,
-                                 dev->valuator->axes + 1, scr->height);
-    }
-
-    /* dropy x/y (device coordinates) back into valuators for next event */
-    dev->last.valuators[0] = *x;
-    dev->last.valuators[1] = *y;
-    dev->last.remainder[0] = x_frac;
-    dev->last.remainder[1] = y_frac;
-}
-
-/**
- * Update the motion history for the device and (if appropriate) for its
- * master device.
- * @param dev Slave device to update.
- * @param mask Bit mask of valid valuators to append to history.
- * @param num Total number of valuators to append to history.
- * @param ms Current time
- */
-static void
-updateHistory(DeviceIntPtr dev, ValuatorMask *mask, CARD32 ms)
-{
-    updateMotionHistory(dev, ms, mask, dev->last.valuators);
-    if (dev->u.master)
-    {
-        DeviceIntPtr master = GetMaster(dev, MASTER_POINTER);
-        updateMotionHistory(master, ms, mask, dev->last.valuators);
-    }
-}
-
-/**
- * Convenience wrapper around GetKeyboardValuatorEvents, that takes no
- * valuators.
- */
-int
-GetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code) {
-    ValuatorMask mask;
-
-    valuator_mask_zero(&mask);
-    return GetKeyboardValuatorEvents(events, pDev, type, key_code, &mask);
-}
-
-
-/**
- * Returns a set of InternalEvents for KeyPress/KeyRelease, optionally
- * also with valuator events.
- *
- * events is not NULL-terminated; the return value is the number of events.
- * The DDX is responsible for allocating the event structure in the first
- * place via GetMaximumEventsNum(), and for freeing it.
- */
-int
-GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
-                          int key_code, const ValuatorMask *mask_in) {
-    int num_events = 0;
-    CARD32 ms = 0;
-    DeviceEvent *event;
-    RawDeviceEvent *raw;
-    ValuatorMask mask;
-
-    /* refuse events from disabled devices */
-    if (!pDev->enabled)
-        return 0;
-
-    if (!events ||!pDev->key || !pDev->focus || !pDev->kbdfeed ||
-       (type != KeyPress && type != KeyRelease) ||
-       (key_code < 8 || key_code > 255))
-        return 0;
-
-    num_events = 1;
-
-    events = UpdateFromMaster(events, pDev, DEVCHANGE_KEYBOARD_EVENT, &num_events);
-
-    /* Handle core repeating, via press/release/press/release. */
-    if (type == KeyPress && key_is_down(pDev, key_code, KEY_POSTED)) {
-        /* If autorepeating is disabled either globally or just for that key,
-         * or we have a modifier, don't generate a repeat event. */
-        if (!pDev->kbdfeed->ctrl.autoRepeat ||
-            !key_autorepeats(pDev, key_code) ||
-            pDev->key->xkbInfo->desc->map->modmap[key_code])
-            return 0;
-    }
-
-    ms = GetTimeInMillis();
-
-    raw = (RawDeviceEvent*)events->event;
-    events++;
-    num_events++;
-
-    valuator_mask_copy(&mask, mask_in);
-
-    init_raw(pDev, raw, ms, type, key_code);
-    set_raw_valuators(raw, &mask, raw->valuators.data_raw);
-
-    clipValuators(pDev, &mask);
-
-    set_raw_valuators(raw, &mask, raw->valuators.data);
-
-    event = (DeviceEvent*) events->event;
-    init_event(pDev, event, ms);
-    event->detail.key = key_code;
-
-    if (type == KeyPress) {
-        event->type = ET_KeyPress;
-	set_key_down(pDev, key_code, KEY_POSTED);
-    }
-    else if (type == KeyRelease) {
-        event->type = ET_KeyRelease;
-	set_key_up(pDev, key_code, KEY_POSTED);
-    }
-
-    clipValuators(pDev, &mask);
-
-    set_valuators(pDev, event, &mask);
-
-    return num_events;
-}
-
-/**
- * Initialize an event list and fill with 32 byte sized events.
- * This event list is to be passed into GetPointerEvents() and
- * GetKeyboardEvents().
- *
- * @param num_events Number of elements in list.
- */
-EventListPtr
-InitEventList(int num_events)
-{
-    EventListPtr events;
-    int i;
-
-    events = (EventListPtr)calloc(num_events, sizeof(EventList));
-    if (!events)
-        return NULL;
-
-    for (i = 0; i < num_events; i++)
-    {
-        events[i].evlen = sizeof(InternalEvent);
-        events[i].event = calloc(1, sizeof(InternalEvent));
-        if (!events[i].event)
-        {
-            /* rollback */
-            while(i--)
-                free(events[i].event);
-            free(events);
-            events = NULL;
-            break;
-        }
-    }
-
-    return events;
-}
-
-/**
- * Free an event list.
- *
- * @param list The list to be freed.
- * @param num_events Number of elements in list.
- */
-void
-FreeEventList(EventListPtr list, int num_events)
-{
-    if (!list)
-        return;
-    while(num_events--)
-        free(list[num_events].event);
-    free(list);
-}
-
-static void
-transformAbsolute(DeviceIntPtr dev, ValuatorMask *mask)
-{
-    struct pixman_f_vector p;
-
-    /* p' = M * p in homogeneous coordinates */
-    p.v[0] = (valuator_mask_isset(mask, 0) ? valuator_mask_get(mask, 0) :
-              dev->last.valuators[0]);
-    p.v[1] = (valuator_mask_isset(mask, 1) ? valuator_mask_get(mask, 1) :
-              dev->last.valuators[1]);
-    p.v[2] = 1.0;
-
-    pixman_f_transform_point(&dev->transform, &p);
-
-    if (lround(p.v[0]) != dev->last.valuators[0])
-        valuator_mask_set(mask, 0, lround(p.v[0]));
-    if (lround(p.v[1]) != dev->last.valuators[1])
-        valuator_mask_set(mask, 1, lround(p.v[1]));
-}
-
-/**
- * Generate a series of InternalEvents (filled into the EventList)
- * representing pointer motion, or button presses.
- *
- * events is not NULL-terminated; the return value is the number of events.
- * The DDX is responsible for allocating the event structure in the first
- * place via InitEventList() and GetMaximumEventsNum(), and for freeing it.
- *
- * In the generated events rootX/Y will be in absolute screen coords and
- * the valuator information in the absolute or relative device coords.
- *
- * last.valuators[x] of the device is always in absolute device coords.
- * last.valuators[x] of the master device is in absolute screen coords.
- *
- * master->last.valuators[x] for x > 2 is undefined.
- */
-int
-GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
-                 int flags, const ValuatorMask *mask_in) {
-    int num_events = 1;
-    CARD32 ms;
-    DeviceEvent *event;
-    RawDeviceEvent    *raw;
-    int x = 0, y = 0, /* device coords */
-        cx, cy; /* only screen coordinates */
-    float x_frac = 0.0, y_frac = 0.0, cx_frac, cy_frac;
-    ScreenPtr scr = miPointerGetScreen(pDev);
-    ValuatorMask mask;
-
-    /* refuse events from disabled devices */
-    if (!pDev->enabled)
-        return 0;
-
-    ms = GetTimeInMillis(); /* before pointer update to help precision */
-
-    if (!scr || !pDev->valuator ||
-        (type != MotionNotify && type != ButtonPress && type != ButtonRelease) ||
-        (type != MotionNotify && !pDev->button) ||
-        ((type == ButtonPress || type == ButtonRelease) && !buttons))
-        return 0;
-
-    if (type == MotionNotify &&
-        (!mask_in || valuator_mask_num_valuators(mask_in) <= 0))
-        return 0;
-
-    events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
-
-    raw = (RawDeviceEvent*)events->event;
-    events++;
-    num_events++;
-
-    valuator_mask_copy(&mask, mask_in);
-
-    init_raw(pDev, raw, ms, type, buttons);
-    set_raw_valuators(raw, &mask, raw->valuators.data_raw);
-
-    if (flags & POINTER_ABSOLUTE)
-    {
-        if (flags & POINTER_SCREEN) /* valuators are in screen coords */
-        {
-            int scaled;
-
-            if (valuator_mask_isset(&mask, 0))
-            {
-                scaled = rescaleValuatorAxis(valuator_mask_get(&mask, 0),
-                                             0.0, &x_frac, NULL,
-                                             pDev->valuator->axes + 0,
-                                             scr->width);
-                valuator_mask_set(&mask, 0, scaled);
-            }
-            if (valuator_mask_isset(&mask, 1))
-            {
-                scaled = rescaleValuatorAxis(valuator_mask_get(&mask, 1),
-                                             0.0, &y_frac, NULL,
-                                             pDev->valuator->axes + 1,
-                                             scr->height);
-                valuator_mask_set(&mask, 1, scaled);
-            }
-        }
-
-        transformAbsolute(pDev, &mask);
-        moveAbsolute(pDev, &x, &y, &mask);
-    } else {
-        if (flags & POINTER_ACCELERATE) {
-            /* FIXME: Pointer acceleration only requires X and Y values. This
-             * should be converted to masked valuators. */
-            int vals[2];
-            vals[0] = valuator_mask_isset(&mask, 0) ?
-                      valuator_mask_get(&mask, 0) : 0;
-            vals[1] = valuator_mask_isset(&mask, 1) ?
-                      valuator_mask_get(&mask, 1) : 0;
-            accelPointer(pDev, 0, 2, vals, ms);
-
-            if (valuator_mask_isset(&mask, 0))
-                valuator_mask_set(&mask, 0, vals[0]);
-            if (valuator_mask_isset(&mask, 1))
-                valuator_mask_set(&mask, 1, vals[1]);
-
-            /* The pointer acceleration code modifies the fractional part
-             * in-place, so we need to extract this information first */
-            x_frac = pDev->last.remainder[0];
-            y_frac = pDev->last.remainder[1];
-        }
-        moveRelative(pDev, &x, &y, &mask);
-    }
-
-    set_raw_valuators(raw, &mask, raw->valuators.data);
-
-    positionSprite(pDev, &x, &y, x_frac, y_frac, scr, &cx, &cy, &cx_frac, &cy_frac);
-    updateHistory(pDev, &mask, ms);
-
-    /* Update the valuators with the true value sent to the client*/
-    if (valuator_mask_isset(&mask, 0))
-        valuator_mask_set(&mask, 0, x);
-    if (valuator_mask_isset(&mask, 1))
-        valuator_mask_set(&mask, 1, y);
-
-    clipValuators(pDev, &mask);
-
-    event = (DeviceEvent*) events->event;
-    init_event(pDev, event, ms);
-
-    if (type == MotionNotify) {
-        event->type = ET_Motion;
-        event->detail.button = 0;
-    }
-    else {
-        if (type == ButtonPress) {
-            event->type = ET_ButtonPress;
-            set_button_down(pDev, buttons, BUTTON_POSTED);
-        }
-        else if (type == ButtonRelease) {
-            event->type = ET_ButtonRelease;
-            set_button_up(pDev, buttons, BUTTON_POSTED);
-        }
-        event->detail.button = buttons;
-    }
-
-    event->root_x = cx; /* root_x/y always in screen coords */
-    event->root_y = cy;
-    event->root_x_frac = cx_frac;
-    event->root_y_frac = cy_frac;
-
-    set_valuators(pDev, event, &mask);
-
-    return num_events;
-}
-
-
-/**
- * Generate ProximityIn/ProximityOut InternalEvents, accompanied by
- * valuators.
- *
- * events is not NULL-terminated; the return value is the number of events.
- * The DDX is responsible for allocating the event structure in the first
- * place via GetMaximumEventsNum(), and for freeing it.
- */
-int
-GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type, const ValuatorMask *mask_in)
-{
-    int num_events = 1, i;
-    DeviceEvent *event;
-    ValuatorMask mask;
-
-    /* refuse events from disabled devices */
-    if (!pDev->enabled)
-        return 0;
-
-    /* Sanity checks. */
-    if ((type != ProximityIn && type != ProximityOut) || !mask_in)
-        return 0;
-    if (!pDev->valuator)
-        return 0;
-
-    valuator_mask_copy(&mask, mask_in);
-
-    /* ignore relative axes for proximity. */
-    for (i = 0; i < valuator_mask_size(&mask); i++)
-    {
-        if (valuator_mask_isset(&mask, i) &&
-            valuator_get_mode(pDev, i) == Relative)
-            valuator_mask_unset(&mask, i);
-    }
-
-    /* FIXME: posting proximity events with relative valuators only results
-     * in an empty event, EventToXI() will fail to convert → no event sent
-     * to client. */
-
-    events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
-
-    event = (DeviceEvent *) events->event;
-    init_event(pDev, event, GetTimeInMillis());
-    event->type = (type == ProximityIn) ? ET_ProximityIn : ET_ProximityOut;
-
-    clipValuators(pDev, &mask);
-
-    set_valuators(pDev, event, &mask);
-
-    return num_events;
-}
-
-/**
- * Synthesize a single motion event for the core pointer.
- *
- * Used in cursor functions, e.g. when cursor confinement changes, and we need
- * to shift the pointer to get it inside the new bounds.
- */
-void
-PostSyntheticMotion(DeviceIntPtr pDev,
-                    int x,
-                    int y,
-                    int screen,
-                    unsigned long time)
-{
-    DeviceEvent ev;
-
-#ifdef PANORAMIX
-    /* Translate back to the sprite screen since processInputProc
-       will translate from sprite screen to screen 0 upon reentry
-       to the DIX layer. */
-    if (!noPanoramiXExtension) {
-        x += screenInfo.screens[0]->x - screenInfo.screens[screen]->x;
-        y += screenInfo.screens[0]->y - screenInfo.screens[screen]->y;
-    }
-#endif
-
-    memset(&ev, 0, sizeof(DeviceEvent));
-    init_event(pDev, &ev, time);
-    ev.root_x = x;
-    ev.root_y = y;
-    ev.type = ET_Motion;
-    ev.time = time;
-
-    /* FIXME: MD/SD considerations? */
-    (*pDev->public.processInputProc)((InternalEvent*)&ev, pDev);
-}
+/*
+ * Copyright © 2006 Nokia Corporation
+ * Copyright © 2006-2007 Daniel Stone
+ * Copyright © 2008 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Daniel Stone <daniel@fooishbar.org>
+ *          Peter Hutterer <peter.hutterer@who-t.net>
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/keysym.h>
+#include <X11/Xproto.h>
+#include <math.h>
+
+#include "misc.h"
+#include "resource.h"
+#include "inputstr.h"
+#include "scrnintstr.h"
+#include "cursorstr.h"
+#include "dixstruct.h"
+#include "globals.h"
+#include "dixevents.h"
+#include "mipointer.h"
+#include "eventstr.h"
+#include "eventconvert.h"
+#include "inpututils.h"
+
+#include <X11/extensions/XKBproto.h>
+#include "xkbsrv.h"
+
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+#endif
+
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XIproto.h>
+#include <pixman.h>
+#include "exglobals.h"
+#include "exevents.h"
+#include "exglobals.h"
+#include "extnsionst.h"
+#include "listdev.h" /* for sizing up DeviceClassesChangedEvent */
+
+/* Number of motion history events to store. */
+#define MOTION_HISTORY_SIZE 256
+
+/* InputEventList is the container list for all input events generated by the
+ * DDX. The DDX is expected to call GetEventList() and then pass the list into
+ * Get{Pointer|Keyboard}Events.
+ */
+EventListPtr InputEventList = NULL;
+int InputEventListLen = 0;
+
+int
+GetEventList(EventListPtr* list)
+{
+    *list = InputEventList;
+    return InputEventListLen;
+}
+
+/**
+ * Pick some arbitrary size for Xi motion history.
+ */
+int
+GetMotionHistorySize(void)
+{
+    return MOTION_HISTORY_SIZE;
+}
+
+void
+set_button_down(DeviceIntPtr pDev, int button, int type)
+{
+    if (type == BUTTON_PROCESSED)
+        SetBit(pDev->button->down, button);
+    else
+        SetBit(pDev->button->postdown, button);
+}
+
+void
+set_button_up(DeviceIntPtr pDev, int button, int type)
+{
+    if (type == BUTTON_PROCESSED)
+        ClearBit(pDev->button->down, button);
+    else
+        ClearBit(pDev->button->postdown, button);
+}
+
+Bool
+button_is_down(DeviceIntPtr pDev, int button, int type)
+{
+    Bool ret = FALSE;
+
+    if (type & BUTTON_PROCESSED)
+        ret = ret || BitIsOn(pDev->button->down, button);
+    if (type & BUTTON_POSTED)
+        ret = ret || BitIsOn(pDev->button->postdown, button);
+
+    return ret;
+}
+
+void
+set_key_down(DeviceIntPtr pDev, int key_code, int type)
+{
+    if (type == KEY_PROCESSED)
+        SetBit(pDev->key->down, key_code);
+    else
+        SetBit(pDev->key->postdown, key_code);
+}
+
+void
+set_key_up(DeviceIntPtr pDev, int key_code, int type)
+{
+    if (type == KEY_PROCESSED)
+        ClearBit(pDev->key->down, key_code);
+    else
+        ClearBit(pDev->key->postdown, key_code);
+}
+
+Bool
+key_is_down(DeviceIntPtr pDev, int key_code, int type)
+{
+    Bool ret = FALSE;
+
+    if (type & KEY_PROCESSED)
+        ret = ret || BitIsOn(pDev->key->down, key_code);
+    if (type & KEY_POSTED)
+        ret = ret || BitIsOn(pDev->key->postdown, key_code);
+
+    return ret;
+}
+
+static Bool
+key_autorepeats(DeviceIntPtr pDev, int key_code)
+{
+    return !!(pDev->kbdfeed->ctrl.autoRepeats[key_code >> 3] &
+              (1 << (key_code & 7)));
+}
+
+static void
+init_event(DeviceIntPtr dev, DeviceEvent* event, Time ms)
+{
+    memset(event, 0, sizeof(DeviceEvent));
+    event->header = ET_Internal;
+    event->length = sizeof(DeviceEvent);
+    event->time = ms;
+    event->deviceid = dev->id;
+    event->sourceid = dev->id;
+}
+
+static void
+init_raw(DeviceIntPtr dev, RawDeviceEvent *event, Time ms, int type, int detail)
+{
+    memset(event, 0, sizeof(RawDeviceEvent));
+    event->header = ET_Internal;
+    event->length = sizeof(RawDeviceEvent);
+    event->type = ET_RawKeyPress - ET_KeyPress + type;
+    event->time = ms;
+    event->deviceid = dev->id;
+    event->sourceid = dev->id;
+    event->detail.button = detail;
+}
+
+static void
+set_raw_valuators(RawDeviceEvent *event, ValuatorMask *mask, int32_t* data)
+{
+    int i;
+
+    for (i = 0; i < valuator_mask_size(mask); i++)
+    {
+        if (valuator_mask_isset(mask, i))
+        {
+            SetBit(event->valuators.mask, i);
+            data[i] = valuator_mask_get(mask, i);
+        }
+    }
+}
+
+
+static void
+set_valuators(DeviceIntPtr dev, DeviceEvent* event, ValuatorMask *mask)
+{
+    int i;
+
+    for (i = 0; i < valuator_mask_size(mask); i++)
+    {
+        if (valuator_mask_isset(mask, i))
+        {
+            SetBit(event->valuators.mask, i);
+            if (valuator_get_mode(dev, i) == Absolute)
+                SetBit(event->valuators.mode, i);
+            event->valuators.data[i] = valuator_mask_get(mask, i);
+            event->valuators.data_frac[i] =
+                dev->last.remainder[i] * (1 << 16) * (1 << 16);
+        }
+    }
+}
+
+void
+CreateClassesChangedEvent(EventList* event,
+                          DeviceIntPtr master,
+                          DeviceIntPtr slave,
+                          int type)
+{
+    int i;
+    DeviceChangedEvent *dce;
+    CARD32 ms = GetTimeInMillis();
+
+    dce = (DeviceChangedEvent*)event->event;
+    memset(dce, 0, sizeof(DeviceChangedEvent));
+    dce->deviceid = slave->id;
+    dce->masterid = master->id;
+    dce->header = ET_Internal;
+    dce->length = sizeof(DeviceChangedEvent);
+    dce->type = ET_DeviceChanged;
+    dce->time = ms;
+    dce->flags = type;
+    dce->flags |= DEVCHANGE_SLAVE_SWITCH;
+    dce->sourceid = slave->id;
+
+    if (slave->button)
+    {
+        dce->buttons.num_buttons = slave->button->numButtons;
+        for (i = 0; i < dce->buttons.num_buttons; i++)
+            dce->buttons.names[i] = slave->button->labels[i];
+    }
+    if (slave->valuator)
+    {
+        dce->num_valuators = slave->valuator->numAxes;
+        for (i = 0; i < dce->num_valuators; i++)
+        {
+            dce->valuators[i].min = slave->valuator->axes[i].min_value;
+            dce->valuators[i].max = slave->valuator->axes[i].max_value;
+            dce->valuators[i].resolution = slave->valuator->axes[i].resolution;
+            dce->valuators[i].mode = slave->valuator->axes[i].mode;
+            dce->valuators[i].name = slave->valuator->axes[i].label;
+        }
+    }
+    if (slave->key)
+    {
+        dce->keys.min_keycode = slave->key->xkbInfo->desc->min_key_code;
+        dce->keys.max_keycode = slave->key->xkbInfo->desc->max_key_code;
+    }
+}
+
+/**
+ * Rescale the coord between the two axis ranges.
+ */
+static int
+rescaleValuatorAxis(int coord, float remainder, float *remainder_return, AxisInfoPtr from, AxisInfoPtr to,
+                    int defmax)
+{
+    int fmin = 0, tmin = 0, fmax = defmax, tmax = defmax, coord_return;
+    float value;
+
+    if(from && from->min_value < from->max_value) {
+        fmin = from->min_value;
+        fmax = from->max_value;
+    }
+    if(to && to->min_value < to->max_value) {
+        tmin = to->min_value;
+        tmax = to->max_value;
+    }
+
+    if(fmin == tmin && fmax == tmax) {
+        if (remainder_return)
+            *remainder_return = remainder;
+        return coord;
+    }
+
+    if(fmax == fmin) { /* avoid division by 0 */
+        if (remainder_return)
+            *remainder_return = 0.0;
+        return 0;
+    }
+
+    value = (coord + remainder - fmin) * (tmax - tmin) / (fmax - fmin) + tmin;
+    coord_return = lroundf(value);
+    if (remainder_return)
+        *remainder_return = value - coord_return;
+    return coord_return;
+}
+
+/**
+ * Update all coordinates when changing to a different SD
+ * to ensure that relative reporting will work as expected
+ * without loss of precision.
+ *
+ * pDev->last.valuators will be in absolute device coordinates after this
+ * function.
+ */
+static void
+updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
+{
+    ScreenPtr scr = miPointerGetScreen(pDev);
+    int i;
+    DeviceIntPtr lastSlave;
+
+    /* master->last.valuators[0]/[1] is in screen coords and the actual
+     * position of the pointer */
+    pDev->last.valuators[0] = master->last.valuators[0];
+    pDev->last.valuators[1] = master->last.valuators[1];
+
+    if (!pDev->valuator)
+        return;
+
+    /* scale back to device coordinates */
+    if(pDev->valuator->numAxes > 0)
+        pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0], pDev->last.remainder[0],
+                        &pDev->last.remainder[0], NULL, pDev->valuator->axes + 0, scr->width);
+    if(pDev->valuator->numAxes > 1)
+        pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1], pDev->last.remainder[1],
+                        &pDev->last.remainder[1], NULL, pDev->valuator->axes + 1, scr->height);
+
+    /* calculate the other axis as well based on info from the old
+     * slave-device. If the old slave had less axes than this one,
+     * last.valuators is reset to 0.
+     */
+    if ((lastSlave = master->last.slave) && lastSlave->valuator) {
+        for (i = 2; i < pDev->valuator->numAxes; i++) {
+            if (i >= lastSlave->valuator->numAxes)
+                pDev->last.valuators[i] = 0;
+            else
+                pDev->last.valuators[i] =
+                    rescaleValuatorAxis(pDev->last.valuators[i],
+                            pDev->last.remainder[i],
+                            &pDev->last.remainder[i],
+                            lastSlave->valuator->axes + i,
+                            pDev->valuator->axes + i, 0);
+        }
+    }
+
+}
+
+/**
+ * Allocate the motion history buffer.
+ */
+void
+AllocateMotionHistory(DeviceIntPtr pDev)
+{
+    int size;
+    free(pDev->valuator->motion);
+
+    if (pDev->valuator->numMotionEvents < 1)
+        return;
+
+    /* An MD must have a motion history size large enough to keep all
+     * potential valuators, plus the respective range of the valuators.
+     * 3 * INT32 for (min_val, max_val, curr_val))
+     */
+    if (IsMaster(pDev))
+        size = sizeof(INT32) * 3 * MAX_VALUATORS;
+    else {
+        ValuatorClassPtr v = pDev->valuator;
+        int numAxes;
+        /* XI1 doesn't understand mixed mode devices */
+        for (numAxes = 0; numAxes < v->numAxes; numAxes++)
+            if (valuator_get_mode(pDev, numAxes) != valuator_get_mode(pDev, 0))
+                break;
+        size = sizeof(INT32) * numAxes;
+    }
+
+    size += sizeof(Time);
+
+    pDev->valuator->motion = calloc(pDev->valuator->numMotionEvents, size);
+    pDev->valuator->first_motion = 0;
+    pDev->valuator->last_motion = 0;
+    if (!pDev->valuator->motion)
+        ErrorF("[dix] %s: Failed to alloc motion history (%d bytes).\n",
+                pDev->name, size * pDev->valuator->numMotionEvents);
+}
+
+/**
+ * Dump the motion history between start and stop into the supplied buffer.
+ * Only records the event for a given screen in theory, but in practice, we
+ * sort of ignore this.
+ *
+ * If core is set, we only generate x/y, in INT16, scaled to screen coords.
+ */
+int
+GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
+                 unsigned long stop, ScreenPtr pScreen, BOOL core)
+{
+    char *ibuff = NULL, *obuff;
+    int i = 0, ret = 0;
+    int j, coord;
+    Time current;
+    /* The size of a single motion event. */
+    int size;
+    int dflt;
+    AxisInfo from, *to; /* for scaling */
+    INT32 *ocbuf, *icbuf; /* pointer to coordinates for copying */
+    INT16 *corebuf;
+    AxisInfo core_axis = {0};
+
+    if (!pDev->valuator || !pDev->valuator->numMotionEvents)
+        return 0;
+
+    if (core && !pScreen)
+        return 0;
+
+    if (IsMaster(pDev))
+        size = (sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(Time);
+    else
+        size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
+
+    *buff = malloc(size * pDev->valuator->numMotionEvents);
+    if (!(*buff))
+        return 0;
+    obuff = (char *)*buff;
+
+    for (i = pDev->valuator->first_motion;
+         i != pDev->valuator->last_motion;
+         i = (i + 1) % pDev->valuator->numMotionEvents) {
+        /* We index the input buffer by which element we're accessing, which
+         * is not monotonic, and the output buffer by how many events we've
+         * written so far. */
+        ibuff = (char *) pDev->valuator->motion + (i * size);
+        memcpy(&current, ibuff, sizeof(Time));
+
+        if (current > stop) {
+            return ret;
+        }
+        else if (current >= start) {
+            if (core)
+            {
+                memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */
+
+                icbuf = (INT32*)(ibuff + sizeof(Time));
+                corebuf = (INT16*)(obuff + sizeof(Time));
+
+                /* fetch x coordinate + range */
+                memcpy(&from.min_value, icbuf++, sizeof(INT32));
+                memcpy(&from.max_value, icbuf++, sizeof(INT32));
+                memcpy(&coord, icbuf++, sizeof(INT32));
+
+                /* scale to screen coords */
+                to = &core_axis;
+                to->max_value = pScreen->width;
+                coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->width);
+
+                memcpy(corebuf, &coord, sizeof(INT16));
+                corebuf++;
+
+                /* fetch y coordinate + range */
+                memcpy(&from.min_value, icbuf++, sizeof(INT32));
+                memcpy(&from.max_value, icbuf++, sizeof(INT32));
+                memcpy(&coord, icbuf++, sizeof(INT32));
+
+                to->max_value = pScreen->height;
+                coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->height);
+                memcpy(corebuf, &coord, sizeof(INT16));
+
+            } else if (IsMaster(pDev))
+            {
+                memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */
+
+                ocbuf = (INT32*)(obuff + sizeof(Time));
+                icbuf = (INT32*)(ibuff + sizeof(Time));
+                for (j = 0; j < MAX_VALUATORS; j++)
+                {
+                    if (j >= pDev->valuator->numAxes)
+                        break;
+
+                    /* fetch min/max/coordinate */
+                    memcpy(&from.min_value, icbuf++, sizeof(INT32));
+                    memcpy(&from.max_value, icbuf++, sizeof(INT32));
+                    memcpy(&coord, icbuf++, sizeof(INT32));
+
+                    to = (j < pDev->valuator->numAxes) ? &pDev->valuator->axes[j] : NULL;
+
+                    /* x/y scaled to screen if no range is present */
+                    if (j == 0 && (from.max_value < from.min_value))
+                        from.max_value = pScreen->width;
+                    else if (j == 1 && (from.max_value < from.min_value))
+                        from.max_value = pScreen->height;
+
+                    if (j == 0 && (to->max_value < to->min_value))
+                        dflt = pScreen->width;
+                    else if (j == 1 && (to->max_value < to->min_value))
+                        dflt = pScreen->height;
+                    else
+                        dflt = 0;
+
+                    /* scale from stored range into current range */
+                    coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, 0);
+                    memcpy(ocbuf, &coord, sizeof(INT32));
+                    ocbuf++;
+                }
+            } else
+                memcpy(obuff, ibuff, size);
+
+            /* don't advance by size here. size may be different to the
+             * actually written size if the MD has less valuators than MAX */
+            if (core)
+                obuff += sizeof(INT32) + sizeof(Time);
+            else
+                obuff += (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
+            ret++;
+        }
+    }
+
+    return ret;
+}
+
+
+/**
+ * Update the motion history for a specific device, with the list of
+ * valuators.
+ *
+ * Layout of the history buffer:
+ *   for SDs: [time] [val0] [val1] ... [valn]
+ *   for MDs: [time] [min_val0] [max_val0] [val0] [min_val1] ... [valn]
+ *
+ * For events that have some valuators unset:
+ *      min_val == max_val == val == 0.
+ */
+static void
+updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, ValuatorMask *mask,
+                    int *valuators)
+{
+    char *buff = (char *) pDev->valuator->motion;
+    ValuatorClassPtr v;
+    int i;
+
+    if (!pDev->valuator->numMotionEvents)
+        return;
+
+    v = pDev->valuator;
+    if (IsMaster(pDev))
+    {
+        buff += ((sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(CARD32)) *
+                v->last_motion;
+
+        memcpy(buff, &ms, sizeof(Time));
+        buff += sizeof(Time);
+
+        memset(buff, 0, sizeof(INT32) * 3 * MAX_VALUATORS);
+
+        for (i = 0; i < v->numAxes; i++)
+        {
+            /* XI1 doesn't support mixed mode devices */
+            if (valuator_get_mode(pDev, i) != valuator_get_mode(pDev, 0))
+                break;
+            if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i))
+            {
+                buff += 3 * sizeof(INT32);
+                continue;
+            }
+            memcpy(buff, &v->axes[i].min_value, sizeof(INT32));
+            buff += sizeof(INT32);
+            memcpy(buff, &v->axes[i].max_value, sizeof(INT32));
+            buff += sizeof(INT32);
+            memcpy(buff, &valuators[i], sizeof(INT32));
+            buff += sizeof(INT32);
+        }
+    } else
+    {
+
+        buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) *
+            pDev->valuator->last_motion;
+
+        memcpy(buff, &ms, sizeof(Time));
+        buff += sizeof(Time);
+
+        memset(buff, 0, sizeof(INT32) * pDev->valuator->numAxes);
+
+        for (i = 0; i < MAX_VALUATORS; i++)
+        {
+            if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i))
+            {
+                buff += sizeof(INT32);
+                continue;
+            }
+            memcpy(buff, &valuators[i], sizeof(INT32));
+            buff += sizeof(INT32);
+        }
+    }
+
+    pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) %
+        pDev->valuator->numMotionEvents;
+    /* If we're wrapping around, just keep the circular buffer going. */
+    if (pDev->valuator->first_motion == pDev->valuator->last_motion)
+        pDev->valuator->first_motion = (pDev->valuator->first_motion + 1) %
+                                       pDev->valuator->numMotionEvents;
+
+    return;
+}
+
+
+/**
+ * Returns the maximum number of events GetKeyboardEvents,
+ * GetKeyboardValuatorEvents, and GetPointerEvents will ever return.
+ *
+ * This MUST be absolutely constant, from init until exit.
+ */
+int
+GetMaximumEventsNum(void) {
+    /* One raw event
+     * One device event
+     * One possible device changed event
+     */
+    return 3;
+}
+
+
+/**
+ * Clip an axis to its bounds, which are declared in the call to
+ * InitValuatorAxisClassStruct.
+ */
+static void
+clipAxis(DeviceIntPtr pDev, int axisNum, int *val)
+{
+    AxisInfoPtr axis;
+
+    if (axisNum >= pDev->valuator->numAxes)
+        return;
+
+    axis = pDev->valuator->axes + axisNum;
+
+    /* If a value range is defined, clip. If not, do nothing */
+    if (axis->max_value <= axis->min_value)
+        return;
+
+    if (*val < axis->min_value)
+        *val = axis->min_value;
+    if (*val > axis->max_value)
+        *val = axis->max_value;
+}
+
+/**
+ * Clip every axis in the list of valuators to its bounds.
+ */
+static void
+clipValuators(DeviceIntPtr pDev, ValuatorMask *mask)
+{
+    int i;
+
+    for (i = 0; i < valuator_mask_size(mask); i++)
+        if (valuator_mask_isset(mask, i))
+        {
+            int val = valuator_mask_get(mask, i);
+            clipAxis(pDev, i, &val);
+            valuator_mask_set(mask, i, val);
+        }
+}
+
+/**
+ * Create the DCCE event (does not update the master's device state yet, this
+ * is done in the event processing).
+ * Pull in the coordinates from the MD if necessary.
+ *
+ * @param events Pointer to a pre-allocated event list.
+ * @param dev The slave device that generated an event.
+ * @param type Either DEVCHANGE_POINTER_EVENT and/or DEVCHANGE_KEYBOARD_EVENT
+ * @param num_events The current number of events, returns the number of
+ *        events if a DCCE was generated.
+ * @return The updated @events pointer.
+ */
+EventListPtr
+UpdateFromMaster(EventListPtr events, DeviceIntPtr dev, int type, int *num_events)
+{
+    DeviceIntPtr master;
+
+    master = GetMaster(dev, (type & DEVCHANGE_POINTER_EVENT) ?  MASTER_POINTER : MASTER_KEYBOARD);
+
+    if (master && master->last.slave != dev)
+    {
+        CreateClassesChangedEvent(events, master, dev, type);
+        if (IsPointerDevice(master))
+        {
+            updateSlaveDeviceCoords(master, dev);
+            master->last.numValuators = dev->last.numValuators;
+        }
+        master->last.slave = dev;
+        (*num_events)++;
+        events++;
+    }
+    return events;
+}
+
+/**
+ * Move the device's pointer to the position given in the valuators.
+ *
+ * @param dev The device which's pointer is to be moved.
+ * @param x Returns the x position of the pointer after the move.
+ * @param y Returns the y position of the pointer after the move.
+ * @param mask Bit mask of valid valuators.
+ * @param valuators Valuator data for each axis between @first and
+ *        @first+@num.
+ */
+static void
+moveAbsolute(DeviceIntPtr dev, int *x, int *y, ValuatorMask *mask)
+{
+    int i;
+
+    if (valuator_mask_isset(mask, 0))
+        *x = valuator_mask_get(mask, 0);
+    else
+        *x = dev->last.valuators[0];
+
+    if (valuator_mask_isset(mask, 1))
+        *y = valuator_mask_get(mask, 1);
+    else
+        *y = dev->last.valuators[1];
+
+    clipAxis(dev, 0, x);
+    clipAxis(dev, 1, y);
+
+    for (i = 2; i < valuator_mask_size(mask); i++)
+    {
+        if (valuator_mask_isset(mask, i))
+        {
+            dev->last.valuators[i] = valuator_mask_get(mask, i);
+            clipAxis(dev, i, &dev->last.valuators[i]);
+        }
+    }
+}
+
+/**
+ * Move the device's pointer by the values given in @valuators.
+ *
+ * @param dev The device which's pointer is to be moved.
+ * @param x Returns the x position of the pointer after the move.
+ * @param y Returns the y position of the pointer after the move.
+ * @param mask Bit mask of valid valuators.
+ * @param valuators Valuator data for each axis between @first and
+ *        @first+@num.
+ */
+static void
+moveRelative(DeviceIntPtr dev, int *x, int *y, ValuatorMask *mask)
+{
+    int i;
+
+    *x = dev->last.valuators[0];
+    *y = dev->last.valuators[1];
+
+    if (valuator_mask_isset(mask, 0))
+        *x += valuator_mask_get(mask, 0);
+
+    if (valuator_mask_isset(mask, 1))
+        *y += valuator_mask_get(mask, 1);
+
+    /* if attached, clip both x and y to the defined limits (usually
+     * co-ord space limit). If it is attached, we need x/y to go over the
+     * limits to be able to change screens. */
+    if(dev->u.master && dev->valuator) {
+        if (valuator_get_mode(dev, 0) == Absolute)
+            clipAxis(dev, 0, x);
+        if (valuator_get_mode(dev, 1) == Absolute)
+            clipAxis(dev, 1, y);
+    }
+
+    /* calc other axes, clip, drop back into valuators */
+    for (i = 2; i < valuator_mask_size(mask); i++)
+    {
+        if (valuator_mask_isset(mask, i))
+        {
+            dev->last.valuators[i] += valuator_mask_get(mask, i);
+            if (valuator_get_mode(dev, i) == Absolute)
+                clipAxis(dev, i, &dev->last.valuators[i]);
+            valuator_mask_set(mask, i, dev->last.valuators[i]);
+        }
+    }
+}
+
+/**
+ * Accelerate the data in valuators based on the device's acceleration scheme.
+ *
+ * @param dev The device which's pointer is to be moved.
+ * @param first The first valuator in @valuators
+ * @param num Total number of valuators in @valuators.
+ * @param valuators Valuator data for each axis between @first and
+ *        @first+@num.
+ * @param ms Current time.
+ */
+static void
+accelPointer(DeviceIntPtr dev, int first, int num, int *valuators, CARD32 ms)
+{
+    if (dev->valuator->accelScheme.AccelSchemeProc)
+        dev->valuator->accelScheme.AccelSchemeProc(dev, first, num, valuators, ms);
+}
+
+/**
+ * If we have HW cursors, this actually moves the visible sprite. If not, we
+ * just do all the screen crossing, etc.
+ *
+ * We scale from device to screen coordinates here, call
+ * miPointerSetPosition() and then scale back into device coordinates (if
+ * needed). miPSP will change x/y if the screen was crossed.
+ *
+ * @param dev The device to be moved.
+ * @param x Pointer to current x-axis value, may be modified.
+ * @param y Pointer to current y-axis value, may be modified.
+ * @param x_frac Fractional part of current x-axis value, may be modified.
+ * @param y_frac Fractional part of current y-axis value, may be modified.
+ * @param scr Screen the device's sprite is currently on.
+ * @param screenx Screen x coordinate the sprite is on after the update.
+ * @param screeny Screen y coordinate the sprite is on after the update.
+ * @param screenx_frac Fractional part of screen x coordinate, as above.
+ * @param screeny_frac Fractional part of screen y coordinate, as above.
+ */
+static void
+positionSprite(DeviceIntPtr dev, int *x, int *y, float x_frac, float y_frac,
+               ScreenPtr scr, int *screenx, int *screeny, float *screenx_frac, float *screeny_frac)
+{
+    int old_screenx, old_screeny;
+
+    /* scale x&y to screen */
+    if (dev->valuator && dev->valuator->numAxes > 0) {
+        *screenx = rescaleValuatorAxis(*x, x_frac, screenx_frac,
+                dev->valuator->axes + 0, NULL, scr->width);
+    } else {
+        *screenx = dev->last.valuators[0];
+        *screenx_frac = dev->last.remainder[0];
+    }
+
+    if (dev->valuator && dev->valuator->numAxes > 1) {
+        *screeny = rescaleValuatorAxis(*y, y_frac, screeny_frac,
+                dev->valuator->axes + 1, NULL, scr->height);
+    } else {
+        *screeny = dev->last.valuators[1];
+        *screeny_frac = dev->last.remainder[1];
+    }
+
+    /* Hit the left screen edge? */
+    if (*screenx <= 0 && *screenx_frac < 0.0f)
+    {
+        *screenx_frac = 0.0f;
+        x_frac = 0.0f;
+    }
+    if (*screeny <= 0 && *screeny_frac < 0.0f)
+    {
+        *screeny_frac = 0.0f;
+        y_frac = 0.0f;
+    }
+
+
+    old_screenx = *screenx;
+    old_screeny = *screeny;
+    /* This takes care of crossing screens for us, as well as clipping
+     * to the current screen. */
+    miPointerSetPosition(dev, screenx, screeny);
+
+    if (dev->u.master) {
+        dev->u.master->last.valuators[0] = *screenx;
+        dev->u.master->last.valuators[1] = *screeny;
+        dev->u.master->last.remainder[0] = *screenx_frac;
+        dev->u.master->last.remainder[1] = *screeny_frac;
+    }
+
+    if (dev->valuator)
+    {
+        /* Crossed screen? Scale back to device coordiantes */
+        if(*screenx != old_screenx)
+        {
+            scr = miPointerGetScreen(dev);
+            *x = rescaleValuatorAxis(*screenx, *screenx_frac, &x_frac, NULL,
+                                    dev->valuator->axes + 0, scr->width);
+        }
+        if(*screeny != old_screeny)
+        {
+            scr = miPointerGetScreen(dev);
+            *y = rescaleValuatorAxis(*screeny, *screeny_frac, &y_frac, NULL,
+                                     dev->valuator->axes + 1, scr->height);
+        }
+    }
+
+    /* dropy x/y (device coordinates) back into valuators for next event */
+    dev->last.valuators[0] = *x;
+    dev->last.valuators[1] = *y;
+    dev->last.remainder[0] = x_frac;
+    dev->last.remainder[1] = y_frac;
+}
+
+/**
+ * Update the motion history for the device and (if appropriate) for its
+ * master device.
+ * @param dev Slave device to update.
+ * @param mask Bit mask of valid valuators to append to history.
+ * @param num Total number of valuators to append to history.
+ * @param ms Current time
+ */
+static void
+updateHistory(DeviceIntPtr dev, ValuatorMask *mask, CARD32 ms)
+{
+    if (!dev->valuator)
+        return;
+
+    updateMotionHistory(dev, ms, mask, dev->last.valuators);
+    if (dev->u.master)
+    {
+        DeviceIntPtr master = GetMaster(dev, MASTER_POINTER);
+        updateMotionHistory(master, ms, mask, dev->last.valuators);
+    }
+}
+
+/**
+ * Convenience wrapper around GetKeyboardValuatorEvents, that takes no
+ * valuators.
+ */
+int
+GetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code) {
+    ValuatorMask mask;
+
+    valuator_mask_zero(&mask);
+    return GetKeyboardValuatorEvents(events, pDev, type, key_code, &mask);
+}
+
+
+/**
+ * Returns a set of InternalEvents for KeyPress/KeyRelease, optionally
+ * also with valuator events.
+ *
+ * events is not NULL-terminated; the return value is the number of events.
+ * The DDX is responsible for allocating the event structure in the first
+ * place via GetMaximumEventsNum(), and for freeing it.
+ */
+int
+GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
+                          int key_code, const ValuatorMask *mask_in) {
+    int num_events = 0;
+    CARD32 ms = 0;
+    DeviceEvent *event;
+    RawDeviceEvent *raw;
+    ValuatorMask mask;
+
+    /* refuse events from disabled devices */
+    if (!pDev->enabled)
+        return 0;
+
+    if (!events ||!pDev->key || !pDev->focus || !pDev->kbdfeed ||
+       (type != KeyPress && type != KeyRelease) ||
+       (key_code < 8 || key_code > 255))
+        return 0;
+
+    num_events = 1;
+
+    events = UpdateFromMaster(events, pDev, DEVCHANGE_KEYBOARD_EVENT, &num_events);
+
+    /* Handle core repeating, via press/release/press/release. */
+    if (type == KeyPress && key_is_down(pDev, key_code, KEY_POSTED)) {
+        /* If autorepeating is disabled either globally or just for that key,
+         * or we have a modifier, don't generate a repeat event. */
+        if (!pDev->kbdfeed->ctrl.autoRepeat ||
+            !key_autorepeats(pDev, key_code) ||
+            pDev->key->xkbInfo->desc->map->modmap[key_code])
+            return 0;
+    }
+
+    ms = GetTimeInMillis();
+
+    raw = (RawDeviceEvent*)events->event;
+    events++;
+    num_events++;
+
+    valuator_mask_copy(&mask, mask_in);
+
+    init_raw(pDev, raw, ms, type, key_code);
+    set_raw_valuators(raw, &mask, raw->valuators.data_raw);
+
+    clipValuators(pDev, &mask);
+
+    set_raw_valuators(raw, &mask, raw->valuators.data);
+
+    event = (DeviceEvent*) events->event;
+    init_event(pDev, event, ms);
+    event->detail.key = key_code;
+
+    if (type == KeyPress) {
+        event->type = ET_KeyPress;
+	set_key_down(pDev, key_code, KEY_POSTED);
+    }
+    else if (type == KeyRelease) {
+        event->type = ET_KeyRelease;
+	set_key_up(pDev, key_code, KEY_POSTED);
+    }
+
+    clipValuators(pDev, &mask);
+
+    set_valuators(pDev, event, &mask);
+
+    return num_events;
+}
+
+/**
+ * Initialize an event list and fill with 32 byte sized events.
+ * This event list is to be passed into GetPointerEvents() and
+ * GetKeyboardEvents().
+ *
+ * @param num_events Number of elements in list.
+ */
+EventListPtr
+InitEventList(int num_events)
+{
+    EventListPtr events;
+    int i;
+
+    events = (EventListPtr)calloc(num_events, sizeof(EventList));
+    if (!events)
+        return NULL;
+
+    for (i = 0; i < num_events; i++)
+    {
+        events[i].evlen = sizeof(InternalEvent);
+        events[i].event = calloc(1, sizeof(InternalEvent));
+        if (!events[i].event)
+        {
+            /* rollback */
+            while(i--)
+                free(events[i].event);
+            free(events);
+            events = NULL;
+            break;
+        }
+    }
+
+    return events;
+}
+
+/**
+ * Free an event list.
+ *
+ * @param list The list to be freed.
+ * @param num_events Number of elements in list.
+ */
+void
+FreeEventList(EventListPtr list, int num_events)
+{
+    if (!list)
+        return;
+    while(num_events--)
+        free(list[num_events].event);
+    free(list);
+}
+
+static void
+transformAbsolute(DeviceIntPtr dev, ValuatorMask *mask)
+{
+    struct pixman_f_vector p;
+
+    /* p' = M * p in homogeneous coordinates */
+    p.v[0] = (valuator_mask_isset(mask, 0) ? valuator_mask_get(mask, 0) :
+              dev->last.valuators[0]);
+    p.v[1] = (valuator_mask_isset(mask, 1) ? valuator_mask_get(mask, 1) :
+              dev->last.valuators[1]);
+    p.v[2] = 1.0;
+
+    pixman_f_transform_point(&dev->transform, &p);
+
+    if (lround(p.v[0]) != dev->last.valuators[0])
+        valuator_mask_set(mask, 0, lround(p.v[0]));
+    if (lround(p.v[1]) != dev->last.valuators[1])
+        valuator_mask_set(mask, 1, lround(p.v[1]));
+}
+
+/**
+ * Generate a series of InternalEvents (filled into the EventList)
+ * representing pointer motion, or button presses.
+ *
+ * events is not NULL-terminated; the return value is the number of events.
+ * The DDX is responsible for allocating the event structure in the first
+ * place via InitEventList() and GetMaximumEventsNum(), and for freeing it.
+ *
+ * In the generated events rootX/Y will be in absolute screen coords and
+ * the valuator information in the absolute or relative device coords.
+ *
+ * last.valuators[x] of the device is always in absolute device coords.
+ * last.valuators[x] of the master device is in absolute screen coords.
+ *
+ * master->last.valuators[x] for x > 2 is undefined.
+ */
+int
+GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
+                 int flags, const ValuatorMask *mask_in) {
+    int num_events = 1;
+    CARD32 ms;
+    DeviceEvent *event;
+    RawDeviceEvent    *raw;
+    int x = 0, y = 0, /* device coords */
+        cx, cy; /* only screen coordinates */
+    float x_frac = 0.0, y_frac = 0.0, cx_frac, cy_frac;
+    ScreenPtr scr = miPointerGetScreen(pDev);
+    ValuatorMask mask;
+
+    /* refuse events from disabled devices */
+    if (!pDev->enabled)
+        return 0;
+
+    if (!scr)
+        return 0;
+
+    switch (type)
+    {
+        case MotionNotify:
+            if (!mask_in || valuator_mask_num_valuators(mask_in) <= 0)
+                return 0;
+            break;
+        case ButtonPress:
+        case ButtonRelease:
+            if (!pDev->button || !buttons)
+                return 0;
+            break;
+        default:
+            return 0;
+    }
+
+    ms = GetTimeInMillis(); /* before pointer update to help precision */
+
+    events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
+
+    raw = (RawDeviceEvent*)events->event;
+    events++;
+    num_events++;
+
+    valuator_mask_copy(&mask, mask_in);
+
+    init_raw(pDev, raw, ms, type, buttons);
+    set_raw_valuators(raw, &mask, raw->valuators.data_raw);
+
+    if (flags & POINTER_ABSOLUTE)
+    {
+        if (flags & POINTER_SCREEN) /* valuators are in screen coords */
+        {
+            int scaled;
+
+            if (valuator_mask_isset(&mask, 0))
+            {
+                scaled = rescaleValuatorAxis(valuator_mask_get(&mask, 0),
+                                             0.0, &x_frac, NULL,
+                                             pDev->valuator->axes + 0,
+                                             scr->width);
+                valuator_mask_set(&mask, 0, scaled);
+            }
+            if (valuator_mask_isset(&mask, 1))
+            {
+                scaled = rescaleValuatorAxis(valuator_mask_get(&mask, 1),
+                                             0.0, &y_frac, NULL,
+                                             pDev->valuator->axes + 1,
+                                             scr->height);
+                valuator_mask_set(&mask, 1, scaled);
+            }
+        }
+
+        transformAbsolute(pDev, &mask);
+        moveAbsolute(pDev, &x, &y, &mask);
+    } else {
+        if (flags & POINTER_ACCELERATE) {
+            /* FIXME: Pointer acceleration only requires X and Y values. This
+             * should be converted to masked valuators. */
+            int vals[2];
+            vals[0] = valuator_mask_isset(&mask, 0) ?
+                      valuator_mask_get(&mask, 0) : 0;
+            vals[1] = valuator_mask_isset(&mask, 1) ?
+                      valuator_mask_get(&mask, 1) : 0;
+            accelPointer(pDev, 0, 2, vals, ms);
+
+            if (valuator_mask_isset(&mask, 0))
+                valuator_mask_set(&mask, 0, vals[0]);
+            if (valuator_mask_isset(&mask, 1))
+                valuator_mask_set(&mask, 1, vals[1]);
+
+            /* The pointer acceleration code modifies the fractional part
+             * in-place, so we need to extract this information first */
+            x_frac = pDev->last.remainder[0];
+            y_frac = pDev->last.remainder[1];
+        }
+        moveRelative(pDev, &x, &y, &mask);
+    }
+
+    set_raw_valuators(raw, &mask, raw->valuators.data);
+
+    positionSprite(pDev, &x, &y, x_frac, y_frac, scr, &cx, &cy, &cx_frac, &cy_frac);
+    updateHistory(pDev, &mask, ms);
+
+    /* Update the valuators with the true value sent to the client*/
+    if (valuator_mask_isset(&mask, 0))
+        valuator_mask_set(&mask, 0, x);
+    if (valuator_mask_isset(&mask, 1))
+        valuator_mask_set(&mask, 1, y);
+
+    clipValuators(pDev, &mask);
+
+    event = (DeviceEvent*) events->event;
+    init_event(pDev, event, ms);
+
+    if (type == MotionNotify) {
+        event->type = ET_Motion;
+        event->detail.button = 0;
+    }
+    else {
+        if (type == ButtonPress) {
+            event->type = ET_ButtonPress;
+            set_button_down(pDev, buttons, BUTTON_POSTED);
+        }
+        else if (type == ButtonRelease) {
+            event->type = ET_ButtonRelease;
+            set_button_up(pDev, buttons, BUTTON_POSTED);
+        }
+        event->detail.button = buttons;
+    }
+
+    event->root_x = cx; /* root_x/y always in screen coords */
+    event->root_y = cy;
+    event->root_x_frac = cx_frac;
+    event->root_y_frac = cy_frac;
+
+    set_valuators(pDev, event, &mask);
+
+    return num_events;
+}
+
+
+/**
+ * Generate ProximityIn/ProximityOut InternalEvents, accompanied by
+ * valuators.
+ *
+ * events is not NULL-terminated; the return value is the number of events.
+ * The DDX is responsible for allocating the event structure in the first
+ * place via GetMaximumEventsNum(), and for freeing it.
+ */
+int
+GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type, const ValuatorMask *mask_in)
+{
+    int num_events = 1, i;
+    DeviceEvent *event;
+    ValuatorMask mask;
+
+    /* refuse events from disabled devices */
+    if (!pDev->enabled)
+        return 0;
+
+    /* Sanity checks. */
+    if ((type != ProximityIn && type != ProximityOut) || !mask_in)
+        return 0;
+    if (!pDev->valuator)
+        return 0;
+
+    valuator_mask_copy(&mask, mask_in);
+
+    /* ignore relative axes for proximity. */
+    for (i = 0; i < valuator_mask_size(&mask); i++)
+    {
+        if (valuator_mask_isset(&mask, i) &&
+            valuator_get_mode(pDev, i) == Relative)
+            valuator_mask_unset(&mask, i);
+    }
+
+    /* FIXME: posting proximity events with relative valuators only results
+     * in an empty event, EventToXI() will fail to convert → no event sent
+     * to client. */
+
+    events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
+
+    event = (DeviceEvent *) events->event;
+    init_event(pDev, event, GetTimeInMillis());
+    event->type = (type == ProximityIn) ? ET_ProximityIn : ET_ProximityOut;
+
+    clipValuators(pDev, &mask);
+
+    set_valuators(pDev, event, &mask);
+
+    return num_events;
+}
+
+/**
+ * Synthesize a single motion event for the core pointer.
+ *
+ * Used in cursor functions, e.g. when cursor confinement changes, and we need
+ * to shift the pointer to get it inside the new bounds.
+ */
+void
+PostSyntheticMotion(DeviceIntPtr pDev,
+                    int x,
+                    int y,
+                    int screen,
+                    unsigned long time)
+{
+    DeviceEvent ev;
+
+#ifdef PANORAMIX
+    /* Translate back to the sprite screen since processInputProc
+       will translate from sprite screen to screen 0 upon reentry
+       to the DIX layer. */
+    if (!noPanoramiXExtension) {
+        x += screenInfo.screens[0]->x - screenInfo.screens[screen]->x;
+        y += screenInfo.screens[0]->y - screenInfo.screens[screen]->y;
+    }
+#endif
+
+    memset(&ev, 0, sizeof(DeviceEvent));
+    init_event(pDev, &ev, time);
+    ev.root_x = x;
+    ev.root_y = y;
+    ev.type = ET_Motion;
+    ev.time = time;
+
+    /* FIXME: MD/SD considerations? */
+    (*pDev->public.processInputProc)((InternalEvent*)&ev, pDev);
+}
-- 
cgit v1.2.3