918 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			918 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 * Copyright © 2006 Nokia Corporation
 | 
						|
 * Copyright © 2006-2007 Daniel Stone
 | 
						|
 *
 | 
						|
 * 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.
 | 
						|
 *
 | 
						|
 * Author: Daniel Stone <daniel@fooishbar.org>
 | 
						|
 */
 | 
						|
 | 
						|
#ifdef HAVE_DIX_CONFIG_H
 | 
						|
#include <dix-config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <X11/X.h>
 | 
						|
#include <X11/keysym.h>
 | 
						|
#define NEED_EVENTS
 | 
						|
#define NEED_REPLIES
 | 
						|
#include <X11/Xproto.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"
 | 
						|
 | 
						|
#ifdef XKB
 | 
						|
#include <X11/extensions/XKBproto.h>
 | 
						|
#include <xkbsrv.h>
 | 
						|
extern Bool XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies);
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef PANORAMIX
 | 
						|
#include "panoramiX.h"
 | 
						|
#include "panoramiXsrv.h"
 | 
						|
#endif
 | 
						|
 | 
						|
#include <X11/extensions/XI.h>
 | 
						|
#include <X11/extensions/XIproto.h>
 | 
						|
#include "exglobals.h"
 | 
						|
#include "exevents.h"
 | 
						|
#include "exglobals.h"
 | 
						|
#include "extnsionst.h"
 | 
						|
#include "listdev.h" /* for sizing up DeviceClassesChangedEvent */
 | 
						|
 | 
						|
/* Maximum number of valuators, divided by six, rounded up, to get number
 | 
						|
 * of events. */
 | 
						|
#define MAX_VALUATOR_EVENTS 6
 | 
						|
 | 
						|
/* 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;
 | 
						|
 | 
						|
_X_EXPORT int
 | 
						|
GetEventList(EventListPtr* list)
 | 
						|
{
 | 
						|
    *list = InputEventList;
 | 
						|
    return InputEventListLen;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Pick some arbitrary size for Xi motion history.
 | 
						|
 */
 | 
						|
_X_EXPORT int
 | 
						|
GetMotionHistorySize(void)
 | 
						|
{
 | 
						|
    return MOTION_HISTORY_SIZE;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
set_key_down(DeviceIntPtr pDev, int key_code)
 | 
						|
{
 | 
						|
    pDev->key->postdown[key_code >> 3] |= (1 << (key_code & 7));
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
set_key_up(DeviceIntPtr pDev, int key_code)
 | 
						|
{
 | 
						|
    pDev->key->postdown[key_code >> 3] &= ~(1 << (key_code & 7));
 | 
						|
}
 | 
						|
 | 
						|
static Bool
 | 
						|
key_is_down(DeviceIntPtr pDev, int key_code)
 | 
						|
{
 | 
						|
    return !!(pDev->key->postdown[key_code >> 3] & (1 << (key_code & 7)));
 | 
						|
}
 | 
						|
 | 
						|
static Bool
 | 
						|
key_autorepeats(DeviceIntPtr pDev, int key_code)
 | 
						|
{
 | 
						|
    return !!(pDev->kbdfeed->ctrl.autoRepeats[key_code >> 3] &
 | 
						|
              (1 << (key_code & 7)));
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
CreateClassesChangedEvent(EventList* event,
 | 
						|
                          DeviceIntPtr master,
 | 
						|
                          DeviceIntPtr slave)
 | 
						|
{
 | 
						|
    deviceClassesChangedEvent *dcce;
 | 
						|
    int len = sizeof(xEvent);
 | 
						|
    CARD32 ms = GetTimeInMillis();
 | 
						|
    int namelen = 0; /* dummy */
 | 
						|
 | 
						|
    /* XXX: ok, this is a bit weird. We need to alloc enough size for the
 | 
						|
     * event so it can be filled in in POE lateron. Reason being that if
 | 
						|
     * we realloc the event in POE we can get SIGABRT when we try to free
 | 
						|
     * or realloc the original pointer.
 | 
						|
     * We can only do it here as we don't have the EventList in the event
 | 
						|
     * processing any more.
 | 
						|
     */
 | 
						|
    SizeDeviceInfo(slave, &namelen, &len);
 | 
						|
 | 
						|
    if (event->evlen < len)
 | 
						|
    {
 | 
						|
        event->event = realloc(event->event, len);
 | 
						|
        if (!event->event)
 | 
						|
            FatalError("[dix] Cannot allocate memory for "
 | 
						|
                    "DeviceClassesChangedEvent.\n");
 | 
						|
        event->evlen = len;
 | 
						|
    }
 | 
						|
 | 
						|
    dcce = (deviceClassesChangedEvent*)event->event;
 | 
						|
    dcce->type = GenericEvent;
 | 
						|
    dcce->extension = IReqCode;
 | 
						|
    dcce->evtype = XI_DeviceClassesChangedNotify;
 | 
						|
    dcce->time = ms;
 | 
						|
    dcce->new_slave = slave->id;
 | 
						|
    dcce->length = (len - sizeof(xEvent))/4;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Allocate the motion history buffer.
 | 
						|
 */
 | 
						|
_X_EXPORT void
 | 
						|
AllocateMotionHistory(DeviceIntPtr pDev)
 | 
						|
{
 | 
						|
    if (pDev->valuator->motion)
 | 
						|
        xfree(pDev->valuator->motion);
 | 
						|
 | 
						|
    if (pDev->valuator->numMotionEvents < 1)
 | 
						|
        return;
 | 
						|
 | 
						|
    pDev->valuator->motion = xalloc(((sizeof(INT32) * pDev->valuator->numAxes) +
 | 
						|
                                     sizeof(Time)) *
 | 
						|
                                    pDev->valuator->numMotionEvents);
 | 
						|
    pDev->valuator->first_motion = 0;
 | 
						|
    pDev->valuator->last_motion = 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * 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.
 | 
						|
 */
 | 
						|
_X_EXPORT int
 | 
						|
GetMotionHistory(DeviceIntPtr pDev, xTimecoord *buff, unsigned long start,
 | 
						|
                 unsigned long stop, ScreenPtr pScreen)
 | 
						|
{
 | 
						|
    char *ibuff = NULL, *obuff = (char *) buff;
 | 
						|
    int i = 0, ret = 0;
 | 
						|
    Time current;
 | 
						|
    /* The size of a single motion event. */
 | 
						|
    int size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
 | 
						|
 | 
						|
    if (!pDev->valuator || !pDev->valuator->numMotionEvents)
 | 
						|
        return 0;
 | 
						|
 | 
						|
    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(¤t, ibuff, sizeof(Time));
 | 
						|
 | 
						|
        if (current > stop) {
 | 
						|
            return ret;
 | 
						|
        }
 | 
						|
        else if (current >= start) {
 | 
						|
            memcpy(obuff, ibuff, size);
 | 
						|
            obuff += size;
 | 
						|
            ret++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Update the motion history for a specific device, with the list of
 | 
						|
 * valuators.
 | 
						|
 */
 | 
						|
static void
 | 
						|
updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, int first_valuator,
 | 
						|
                    int num_valuators, int *valuators)
 | 
						|
{
 | 
						|
    char *buff = (char *) pDev->valuator->motion;
 | 
						|
 | 
						|
    if (!pDev->valuator->numMotionEvents)
 | 
						|
        return;
 | 
						|
 | 
						|
    buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) *
 | 
						|
            pDev->valuator->last_motion;
 | 
						|
    memcpy(buff, &ms, sizeof(Time));
 | 
						|
 | 
						|
    buff += sizeof(Time);
 | 
						|
    bzero(buff, sizeof(INT32) * pDev->valuator->numAxes);
 | 
						|
 | 
						|
    buff += sizeof(INT32) * first_valuator;
 | 
						|
    memcpy(buff, valuators, sizeof(INT32) * num_valuators);
 | 
						|
 | 
						|
    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.
 | 
						|
 *
 | 
						|
 * Should be used in DIX as:
 | 
						|
 * xEvent *events = xcalloc(sizeof(xEvent), GetMaximumEventsNum());
 | 
						|
 *
 | 
						|
 * This MUST be absolutely constant, from init until exit.
 | 
						|
 */
 | 
						|
_X_EXPORT int
 | 
						|
GetMaximumEventsNum(void) {
 | 
						|
    /* One base event -- device, plus valuator events.
 | 
						|
     *  Multiply by two if we're doing non-XKB key repeats. */
 | 
						|
    int ret = 1 + MAX_VALUATOR_EVENTS;
 | 
						|
 | 
						|
#ifdef XKB
 | 
						|
    if (noXkbExtension)
 | 
						|
#endif
 | 
						|
        ret *= 2;
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* Originally a part of xf86PostMotionEvent; modifies valuators
 | 
						|
 * in-place. */
 | 
						|
static void
 | 
						|
acceleratePointer(DeviceIntPtr pDev, int first_valuator, int num_valuators,
 | 
						|
                  int *valuators)
 | 
						|
{
 | 
						|
    float mult = 0.0;
 | 
						|
    int dx = 0, dy = 0;
 | 
						|
    int *px = NULL, *py = NULL;
 | 
						|
 | 
						|
    if (!num_valuators || !valuators)
 | 
						|
        return;
 | 
						|
 | 
						|
    if (first_valuator == 0) {
 | 
						|
        dx = valuators[0];
 | 
						|
        px = &valuators[0];
 | 
						|
    }
 | 
						|
    if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) {
 | 
						|
        dy = valuators[1 - first_valuator];
 | 
						|
        py = &valuators[1 - first_valuator];
 | 
						|
    }
 | 
						|
 | 
						|
    if (!dx && !dy)
 | 
						|
        return;
 | 
						|
 | 
						|
    if (pDev->ptrfeed && pDev->ptrfeed->ctrl.num) {
 | 
						|
        /* modeled from xf86Events.c */
 | 
						|
        if (pDev->ptrfeed->ctrl.threshold) {
 | 
						|
            if ((abs(dx) + abs(dy)) >= pDev->ptrfeed->ctrl.threshold) {
 | 
						|
                pDev->valuator->dxremaind = ((float)dx *
 | 
						|
                                             (float)(pDev->ptrfeed->ctrl.num)) /
 | 
						|
                                             (float)(pDev->ptrfeed->ctrl.den) +
 | 
						|
                                            pDev->valuator->dxremaind;
 | 
						|
                if (px) {
 | 
						|
                    *px = (int)pDev->valuator->dxremaind;
 | 
						|
                    pDev->valuator->dxremaind = pDev->valuator->dxremaind -
 | 
						|
                                                (float)(*px);
 | 
						|
                }
 | 
						|
 | 
						|
                pDev->valuator->dyremaind = ((float)dy *
 | 
						|
                                             (float)(pDev->ptrfeed->ctrl.num)) /
 | 
						|
                                             (float)(pDev->ptrfeed->ctrl.den) +
 | 
						|
                                            pDev->valuator->dyremaind;
 | 
						|
                if (py) {
 | 
						|
                    *py = (int)pDev->valuator->dyremaind;
 | 
						|
                    pDev->valuator->dyremaind = pDev->valuator->dyremaind -
 | 
						|
                                                (float)(*py);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        else {
 | 
						|
	    mult = pow((float)dx * (float)dx + (float)dy * (float)dy,
 | 
						|
                       ((float)(pDev->ptrfeed->ctrl.num) /
 | 
						|
                        (float)(pDev->ptrfeed->ctrl.den) - 1.0) /
 | 
						|
                       2.0) / 2.0;
 | 
						|
            if (dx) {
 | 
						|
                pDev->valuator->dxremaind = mult * (float)dx +
 | 
						|
                                            pDev->valuator->dxremaind;
 | 
						|
                *px = (int)pDev->valuator->dxremaind;
 | 
						|
                pDev->valuator->dxremaind = pDev->valuator->dxremaind -
 | 
						|
                                            (float)(*px);
 | 
						|
            }
 | 
						|
            if (dy) {
 | 
						|
                pDev->valuator->dyremaind = mult * (float)dy +
 | 
						|
                                            pDev->valuator->dyremaind;
 | 
						|
                *py = (int)pDev->valuator->dyremaind;
 | 
						|
                pDev->valuator->dyremaind = pDev->valuator->dyremaind -
 | 
						|
                                            (float)(*py);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Clip an axis to its bounds, which are declared in the call to
 | 
						|
 * InitValuatorAxisClassStruct.
 | 
						|
 */
 | 
						|
static void
 | 
						|
clipAxis(DeviceIntPtr pDev, int axisNum, int *val)
 | 
						|
{
 | 
						|
    AxisInfoPtr axes = pDev->valuator->axes + axisNum;
 | 
						|
 | 
						|
    /* No clipping if the value-range <= 0 */
 | 
						|
    if(axes->min_value < axes->min_value) {
 | 
						|
        if (*val < axes->min_value)
 | 
						|
            *val = axes->min_value;
 | 
						|
        if (*val > axes->max_value)
 | 
						|
            *val = axes->max_value;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Clip every axis in the list of valuators to its bounds.
 | 
						|
 */
 | 
						|
static void
 | 
						|
clipValuators(DeviceIntPtr pDev, int first_valuator, int num_valuators,
 | 
						|
              int *valuators)
 | 
						|
{
 | 
						|
    AxisInfoPtr axes = pDev->valuator->axes + first_valuator;
 | 
						|
    int i;
 | 
						|
 | 
						|
    for (i = 0; i < num_valuators; i++, axes++)
 | 
						|
        clipAxis(pDev, i + first_valuator, &(valuators[i]));
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Fills events with valuator events for pDev, as given by the other
 | 
						|
 * parameters.
 | 
						|
 *
 | 
						|
 * FIXME: Need to fix ValuatorClassRec to store all the valuators as
 | 
						|
 *        last posted, not just x and y; otherwise relative non-x/y
 | 
						|
 *        valuators, though a very narrow use case, will be broken.
 | 
						|
 */
 | 
						|
static EventList *
 | 
						|
getValuatorEvents(EventList *events, DeviceIntPtr pDev, int first_valuator,
 | 
						|
                  int num_valuators, int *valuators) {
 | 
						|
    deviceValuator *xv;
 | 
						|
    int i = 0, final_valuator = first_valuator + num_valuators;
 | 
						|
 | 
						|
    for (i = first_valuator; i < final_valuator; i += 6, events++) {
 | 
						|
        xv = (deviceValuator*)events->event;
 | 
						|
        xv->type = DeviceValuator;
 | 
						|
        xv->first_valuator = i;
 | 
						|
        xv->num_valuators = ((final_valuator - i) > 6) ? 6 : (final_valuator - i);
 | 
						|
        xv->deviceid = pDev->id;
 | 
						|
        switch (final_valuator - i) {
 | 
						|
        case 6:
 | 
						|
            xv->valuator5 = valuators[i + 5];
 | 
						|
        case 5:
 | 
						|
            xv->valuator4 = valuators[i + 4];
 | 
						|
        case 4:
 | 
						|
            xv->valuator3 = valuators[i + 3];
 | 
						|
        case 3:
 | 
						|
            xv->valuator2 = valuators[i + 2];
 | 
						|
        case 2:
 | 
						|
            xv->valuator1 = valuators[i + 1];
 | 
						|
        case 1:
 | 
						|
            xv->valuator0 = valuators[i];
 | 
						|
        }
 | 
						|
 | 
						|
        if (i + 6 < final_valuator)
 | 
						|
            xv->deviceid |= MORE_EVENTS;
 | 
						|
    }
 | 
						|
 | 
						|
    return events;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Convenience wrapper around GetKeyboardValuatorEvents, that takes no
 | 
						|
 * valuators.
 | 
						|
 */
 | 
						|
_X_EXPORT int
 | 
						|
GetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code) {
 | 
						|
    return GetKeyboardValuatorEvents(events, pDev, type, key_code, 0, 0, NULL);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Returns a set of keyboard events for KeyPress/KeyRelease, optionally
 | 
						|
 * also with valuator events.  Handles Xi and XKB.
 | 
						|
 *
 | 
						|
 * DOES NOT GENERATE CORE EVENTS! Core events are created when processing the
 | 
						|
 * event (ProcessOtherEvent).
 | 
						|
 *
 | 
						|
 * 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.
 | 
						|
 *
 | 
						|
 * This function does not change the core keymap to that of the device;
 | 
						|
 * that is done by SwitchCoreKeyboard, which is called from
 | 
						|
 * mieqProcessInputEvents.  If replacing that function, take care to call
 | 
						|
 * SetCoreKeyboard before processInputProc, so keymaps are altered to suit.
 | 
						|
 *
 | 
						|
 * Note that this function recurses!  If called for non-XKB, a repeating
 | 
						|
 * key press will trigger a matching KeyRelease, as well as the
 | 
						|
 * KeyPresses.
 | 
						|
 */
 | 
						|
_X_EXPORT int
 | 
						|
GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
 | 
						|
                          int key_code, int first_valuator,
 | 
						|
                          int num_valuators, int *valuators) {
 | 
						|
    int numEvents = 0;
 | 
						|
    CARD32 ms = 0;
 | 
						|
    KeySym *map = pDev->key->curKeySyms.map;
 | 
						|
    KeySym sym = map[key_code * pDev->key->curKeySyms.mapWidth];
 | 
						|
    deviceKeyButtonPointer *kbp = NULL;
 | 
						|
    DeviceIntPtr master;
 | 
						|
 | 
						|
    if (!events)
 | 
						|
        return 0;
 | 
						|
 | 
						|
    /* DO NOT WANT */
 | 
						|
    if (type != KeyPress && type != KeyRelease)
 | 
						|
        return 0;
 | 
						|
 | 
						|
    if (!pDev->key || !pDev->focus || !pDev->kbdfeed ||
 | 
						|
        (pDev->coreEvents && !inputInfo.keyboard->key))
 | 
						|
        return 0;
 | 
						|
 | 
						|
    numEvents = 1;
 | 
						|
 | 
						|
    if (key_code < 8 || key_code > 255)
 | 
						|
        return 0;
 | 
						|
 | 
						|
    master = pDev->u.master;
 | 
						|
    if (master && master->u.lastSlave != pDev)
 | 
						|
    {
 | 
						|
        CreateClassesChangedEvent(events, master, pDev);
 | 
						|
 | 
						|
        if (master->valuator && pDev->valuator)
 | 
						|
        {
 | 
						|
            pDev->lastx = master->lastx;
 | 
						|
            pDev->lasty = master->lasty;
 | 
						|
        }
 | 
						|
        master->u.lastSlave = pDev;
 | 
						|
        numEvents++;
 | 
						|
        events++;
 | 
						|
    }
 | 
						|
 | 
						|
    if (num_valuators) {
 | 
						|
        if ((num_valuators / 6) + 1 > MAX_VALUATOR_EVENTS)
 | 
						|
            num_valuators = MAX_VALUATOR_EVENTS;
 | 
						|
        numEvents += (num_valuators / 6) + 1;
 | 
						|
    }
 | 
						|
 | 
						|
#ifdef XKB
 | 
						|
    if (noXkbExtension)
 | 
						|
#endif
 | 
						|
    {
 | 
						|
        switch (sym) {
 | 
						|
            case XK_Num_Lock:
 | 
						|
            case XK_Caps_Lock:
 | 
						|
            case XK_Scroll_Lock:
 | 
						|
            case XK_Shift_Lock:
 | 
						|
                if (type == KeyRelease)
 | 
						|
                    return 0;
 | 
						|
                else if (type == KeyPress && key_is_down(pDev, key_code))
 | 
						|
                    type = KeyRelease;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* Handle core repeating, via press/release/press/release.
 | 
						|
     * FIXME: In theory, if you're repeating with two keyboards in non-XKB,
 | 
						|
     *        you could get unbalanced events here. */
 | 
						|
    if (type == KeyPress && key_is_down(pDev, key_code)) {
 | 
						|
        /* 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->modifierMap[key_code])
 | 
						|
            return 0;
 | 
						|
 | 
						|
#ifdef XKB
 | 
						|
        if (noXkbExtension)
 | 
						|
#endif
 | 
						|
        {
 | 
						|
            numEvents += GetKeyboardValuatorEvents(events, pDev,
 | 
						|
                                                   KeyRelease, key_code,
 | 
						|
                                                   first_valuator, num_valuators,
 | 
						|
                                                   valuators);
 | 
						|
            events += numEvents;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    ms = GetTimeInMillis();
 | 
						|
 | 
						|
    kbp = (deviceKeyButtonPointer *) events->event;
 | 
						|
    kbp->time = ms;
 | 
						|
    kbp->deviceid = pDev->id;
 | 
						|
    kbp->detail = key_code;
 | 
						|
    if (type == KeyPress) {
 | 
						|
        kbp->type = DeviceKeyPress;
 | 
						|
	set_key_down(pDev, key_code);
 | 
						|
    }
 | 
						|
    else if (type == KeyRelease) {
 | 
						|
        kbp->type = DeviceKeyRelease;
 | 
						|
	set_key_up(pDev, key_code);
 | 
						|
    }
 | 
						|
 | 
						|
    events++;
 | 
						|
    if (num_valuators) {
 | 
						|
        kbp->deviceid |= MORE_EVENTS;
 | 
						|
        clipValuators(pDev, first_valuator, num_valuators, valuators);
 | 
						|
        events = getValuatorEvents(events, pDev, first_valuator,
 | 
						|
                                   num_valuators, valuators);
 | 
						|
    }
 | 
						|
 | 
						|
    return numEvents;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * 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.
 | 
						|
 */
 | 
						|
_X_EXPORT EventListPtr
 | 
						|
InitEventList(int num_events)
 | 
						|
{
 | 
						|
    EventListPtr events;
 | 
						|
    int i;
 | 
						|
 | 
						|
    events = (EventListPtr)xcalloc(num_events, sizeof(EventList));
 | 
						|
    if (!events)
 | 
						|
        return NULL;
 | 
						|
 | 
						|
    for (i = 0; i < num_events; i++)
 | 
						|
    {
 | 
						|
        events[i].evlen = sizeof(xEvent);
 | 
						|
        events[i].event = xcalloc(1, sizeof(xEvent));
 | 
						|
        if (!events[i].event)
 | 
						|
        {
 | 
						|
            /* rollback */
 | 
						|
            while(i--)
 | 
						|
                xfree(events[i].event);
 | 
						|
            xfree(events);
 | 
						|
            events = NULL;
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return events;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Allocs min_size memory for each event in the list.
 | 
						|
 */
 | 
						|
_X_EXPORT void
 | 
						|
SetMinimumEventSize(EventListPtr list, int num_events, int min_size)
 | 
						|
{
 | 
						|
    if (!list)
 | 
						|
        return;
 | 
						|
 | 
						|
    while(num_events--)
 | 
						|
    {
 | 
						|
        if (list[num_events].evlen < min_size)
 | 
						|
        {
 | 
						|
            list[num_events].evlen = min_size;
 | 
						|
            list[num_events].event = realloc(list[num_events].event, min_size);
 | 
						|
            if (!list[num_events].event)
 | 
						|
            {
 | 
						|
                FatalError("[dix] Failed to set event list's "
 | 
						|
                        "min_size to %d.\n", min_size);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Free an event list.
 | 
						|
 *
 | 
						|
 * @param list The list to be freed.
 | 
						|
 * @param num_events Number of elements in list.
 | 
						|
 */
 | 
						|
_X_EXPORT void
 | 
						|
FreeEventList(EventListPtr list, int num_events)
 | 
						|
{
 | 
						|
    if (!list)
 | 
						|
        return;
 | 
						|
    while(num_events--)
 | 
						|
        xfree(list[num_events].event);
 | 
						|
    xfree(list);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Generate a series of xEvents (filled into the EventList) representing
 | 
						|
 * pointer motion, or button presses.  Xi and XKB-aware.
 | 
						|
 *
 | 
						|
 * DOES NOT GENERATE CORE EVENTS! Core events are created when processing the
 | 
						|
 * event (ProcessOtherEvent).
 | 
						|
 *
 | 
						|
 * 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.
 | 
						|
 *
 | 
						|
 */
 | 
						|
_X_EXPORT int
 | 
						|
GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
 | 
						|
                 int flags, int first_valuator, int num_valuators,
 | 
						|
                 int *valuators) {
 | 
						|
    int num_events = 0, final_valuator = 0;
 | 
						|
    CARD32 ms = 0;
 | 
						|
    deviceKeyButtonPointer *kbp = NULL;
 | 
						|
    DeviceIntPtr master;
 | 
						|
    int x = 0, y = 0;
 | 
						|
 | 
						|
    /* Sanity checks. */
 | 
						|
    if (type != MotionNotify && type != ButtonPress && type != ButtonRelease)
 | 
						|
        return 0;
 | 
						|
 | 
						|
    if ((type == ButtonPress || type == ButtonRelease) && !pDev->button)
 | 
						|
        return 0;
 | 
						|
 | 
						|
    /* FIXME: I guess it should, in theory, be possible to post button events
 | 
						|
     *        from devices without valuators. */
 | 
						|
    if (!pDev->valuator)
 | 
						|
        return 0;
 | 
						|
 | 
						|
    if (type == MotionNotify && num_valuators <= 0)
 | 
						|
        return 0;
 | 
						|
 | 
						|
    ms = GetTimeInMillis();
 | 
						|
 | 
						|
    num_events = 1;
 | 
						|
 | 
						|
    master = pDev->u.master;
 | 
						|
    if (master && master->u.lastSlave != pDev)
 | 
						|
    {
 | 
						|
        CreateClassesChangedEvent(events, master, pDev);
 | 
						|
 | 
						|
        pDev->lastx = master->lastx;
 | 
						|
        pDev->lasty = master->lasty;
 | 
						|
        master->u.lastSlave = pDev;
 | 
						|
 | 
						|
        num_events++;
 | 
						|
        events++;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Do we need to send a DeviceValuator event? */
 | 
						|
    if (num_valuators) {
 | 
						|
        if ((((num_valuators - 1) / 6) + 1) > MAX_VALUATOR_EVENTS)
 | 
						|
            num_valuators = MAX_VALUATOR_EVENTS * 6;
 | 
						|
        num_events += ((num_valuators - 1) / 6) + 1;
 | 
						|
    }
 | 
						|
 | 
						|
    final_valuator = num_valuators + first_valuator;
 | 
						|
 | 
						|
    /* You fail. */
 | 
						|
    if (first_valuator < 0 || final_valuator > pDev->valuator->numAxes)
 | 
						|
        return 0;
 | 
						|
 | 
						|
    /* Set x and y based on whether this is absolute or relative, and
 | 
						|
     * accelerate if we need to. */
 | 
						|
    if (flags & POINTER_ABSOLUTE) {
 | 
						|
        if (num_valuators >= 1 && first_valuator == 0) {
 | 
						|
            x = valuators[0];
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            x = pDev->lastx;
 | 
						|
        }
 | 
						|
 | 
						|
        if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) {
 | 
						|
            y = valuators[1 - first_valuator];
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            y = pDev->lasty;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        if (flags & POINTER_ACCELERATE)
 | 
						|
            acceleratePointer(pDev, first_valuator, num_valuators,
 | 
						|
                              valuators);
 | 
						|
 | 
						|
        if (first_valuator == 0 && num_valuators >= 1)
 | 
						|
            x = pDev->lastx + valuators[0];
 | 
						|
        else
 | 
						|
            x = pDev->lastx;
 | 
						|
 | 
						|
        if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
 | 
						|
            y = pDev->lasty + valuators[1 - first_valuator];
 | 
						|
        else
 | 
						|
            y = pDev->lasty;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Clip both x and y to the defined limits (usually co-ord space limit). */
 | 
						|
    clipAxis(pDev, 0, &x);
 | 
						|
    clipAxis(pDev, 1, &y);
 | 
						|
 | 
						|
    /* This takes care of crossing screens for us, as well as clipping
 | 
						|
     * to the current screen.  Right now, we only have one history buffer,
 | 
						|
     * so we don't set this for both the device and core.*/
 | 
						|
    miPointerSetPosition(pDev, &x, &y, ms);
 | 
						|
 | 
						|
    /* Drop x and y back into the valuators list, if they were originally
 | 
						|
     * present. */
 | 
						|
    if (first_valuator == 0 && num_valuators >= 1)
 | 
						|
        valuators[0] = x;
 | 
						|
    if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
 | 
						|
        valuators[1 - first_valuator] = y;
 | 
						|
 | 
						|
    updateMotionHistory(pDev, ms, first_valuator, num_valuators, valuators);
 | 
						|
 | 
						|
    pDev->lastx = x;
 | 
						|
    pDev->lasty = y;
 | 
						|
    if (master)
 | 
						|
    {
 | 
						|
        master->lastx = x;
 | 
						|
        master->lasty = y;
 | 
						|
    }
 | 
						|
 | 
						|
    kbp = (deviceKeyButtonPointer *) events->event;
 | 
						|
    kbp->time = ms;
 | 
						|
    kbp->deviceid = pDev->id;
 | 
						|
 | 
						|
    if (type == MotionNotify) {
 | 
						|
        kbp->type = DeviceMotionNotify;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        if (type == ButtonPress)
 | 
						|
            kbp->type = DeviceButtonPress;
 | 
						|
        else if (type == ButtonRelease)
 | 
						|
            kbp->type = DeviceButtonRelease;
 | 
						|
        kbp->detail = pDev->button->map[buttons];
 | 
						|
    }
 | 
						|
 | 
						|
    kbp->root_x = x;
 | 
						|
    kbp->root_y = y;
 | 
						|
 | 
						|
    events++;
 | 
						|
    if (num_valuators) {
 | 
						|
        kbp->deviceid |= MORE_EVENTS;
 | 
						|
        clipValuators(pDev, first_valuator, num_valuators, valuators);
 | 
						|
        events = getValuatorEvents(events, pDev, first_valuator,
 | 
						|
                num_valuators, valuators);
 | 
						|
    }
 | 
						|
 | 
						|
    return num_events;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Post ProximityIn/ProximityOut events, 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.
 | 
						|
 */
 | 
						|
_X_EXPORT int
 | 
						|
GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
 | 
						|
                   int first_valuator, int num_valuators, int *valuators)
 | 
						|
{
 | 
						|
    int num_events = 1;
 | 
						|
    deviceKeyButtonPointer *kbp;
 | 
						|
    DeviceIntPtr master;
 | 
						|
 | 
						|
    /* Sanity checks. */
 | 
						|
    if (type != ProximityIn && type != ProximityOut)
 | 
						|
        return 0;
 | 
						|
 | 
						|
    if (!pDev->valuator)
 | 
						|
        return 0;
 | 
						|
 | 
						|
    /* Do we need to send a DeviceValuator event? */
 | 
						|
    if ((pDev->valuator->mode & 1) == Relative)
 | 
						|
        num_valuators = 0;
 | 
						|
 | 
						|
    if (num_valuators) {
 | 
						|
        if ((((num_valuators - 1) / 6) + 1) > MAX_VALUATOR_EVENTS)
 | 
						|
            num_valuators = MAX_VALUATOR_EVENTS * 6;
 | 
						|
        num_events += ((num_valuators - 1) / 6) + 1;
 | 
						|
    }
 | 
						|
 | 
						|
    /* You fail. */
 | 
						|
    if (first_valuator < 0 ||
 | 
						|
        (num_valuators + first_valuator) > pDev->valuator->numAxes)
 | 
						|
        return 0;
 | 
						|
 | 
						|
    master = pDev->u.master;
 | 
						|
    if (master && master->u.lastSlave != pDev)
 | 
						|
    {
 | 
						|
        CreateClassesChangedEvent(events, master, pDev);
 | 
						|
 | 
						|
        pDev->lastx = master->lastx;
 | 
						|
        pDev->lasty = master->lasty;
 | 
						|
        master->u.lastSlave = pDev;
 | 
						|
 | 
						|
        num_events++;
 | 
						|
        events++;
 | 
						|
    }
 | 
						|
 | 
						|
    kbp = (deviceKeyButtonPointer *) events->event;
 | 
						|
    kbp->type = type;
 | 
						|
    kbp->deviceid = pDev->id;
 | 
						|
    kbp->detail = 0;
 | 
						|
    kbp->time = GetTimeInMillis();
 | 
						|
 | 
						|
    if (num_valuators) {
 | 
						|
        kbp->deviceid |= MORE_EVENTS;
 | 
						|
        events++;
 | 
						|
        clipValuators(pDev, first_valuator, num_valuators, valuators);
 | 
						|
        events = getValuatorEvents(events, pDev, first_valuator,
 | 
						|
                                   num_valuators, valuators);
 | 
						|
    }
 | 
						|
 | 
						|
    return num_events;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Note that pDev was the last function to send a core pointer event.
 | 
						|
 * Currently a no-op.
 | 
						|
 *
 | 
						|
 * Call this just before processInputProc.
 | 
						|
 */
 | 
						|
_X_EXPORT void
 | 
						|
SwitchCorePointer(DeviceIntPtr pDev)
 | 
						|
{
 | 
						|
    if (pDev != dixLookupPrivate(&inputInfo.pointer->devPrivates,
 | 
						|
				 CoreDevicePrivateKey))
 | 
						|
	dixSetPrivate(&inputInfo.pointer->devPrivates,
 | 
						|
		      CoreDevicePrivateKey, pDev);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * 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)
 | 
						|
{
 | 
						|
    xEvent xE;
 | 
						|
 | 
						|
#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 += panoramiXdataPtr[0].x - panoramiXdataPtr[screen].x;
 | 
						|
        y += panoramiXdataPtr[0].y - panoramiXdataPtr[screen].y;
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
    memset(&xE, 0, sizeof(xEvent));
 | 
						|
    xE.u.u.type = MotionNotify;
 | 
						|
    xE.u.keyButtonPointer.rootX = x;
 | 
						|
    xE.u.keyButtonPointer.rootY = y;
 | 
						|
    xE.u.keyButtonPointer.time = time;
 | 
						|
 | 
						|
    (*pDev->public.processInputProc)(&xE, pDev, 1);
 | 
						|
}
 |