xserver-multidpi/hw/xfree86/common/xf86Xinput.c
2003-11-14 15:54:54 +00:00

1265 lines
35 KiB
C

/* $Xorg: xf86Xinput.c,v 1.3 2000/08/17 19:50:31 cpqbld Exp $ */
/*
* Copyright 1995,1996 by Frederic Lepied, France. <fred@sugix.frmug.fr.net>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Frederic Lepied not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Frederic Lepied makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* FREDERIC LEPIED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL FREDERIC LEPIED BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
*/
/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Xinput.c,v 3.22.2.7 1998/02/07 10:05:22 hohndel Exp $ */
#include "Xmd.h"
#include "XI.h"
#include "XIproto.h"
#include "xf86.h"
#include "Xpoll.h"
#include "xf86Priv.h"
#include "xf86_Config.h"
#include "xf86Xinput.h"
#include "xf86Procs.h"
#include "mipointer.h"
#ifdef DPMSExtension
#include "extensions/dpms.h"
#endif
#include "exevents.h" /* AddInputDevice */
#include "extnsionst.h"
#include "extinit.h" /* LookupDeviceIntRec */
#include "windowstr.h" /* screenIsSaved */
#include <stdarg.h>
extern InputInfo inputInfo;
#ifndef DYNAMIC_MODULE
#ifdef JOYSTICK_SUPPORT
extern DeviceAssocRec joystick_assoc;
#endif
#ifdef WACOM_SUPPORT
extern DeviceAssocRec wacom_stylus_assoc;
extern DeviceAssocRec wacom_cursor_assoc;
extern DeviceAssocRec wacom_eraser_assoc;
#endif
#ifdef ELOGRAPHICS_SUPPORT
extern DeviceAssocRec elographics_assoc;
#endif
#ifdef SUMMASKETCH_SUPPORT
extern DeviceAssocRec summasketch_assoc;
#endif
#endif
extern DeviceAssocRec mouse_assoc;
static int num_devices;
static LocalDevicePtr *localDevices;
static int max_devices;
static DeviceAssocPtr *deviceAssoc = NULL;
static int numAssoc = 0;
static int maxAssoc = 0;
static SymTabRec XinputTab[] = {
{ ENDSECTION, "endsection"},
{ SUBSECTION, "subsection" },
{ -1, "" },
};
/***********************************************************************
*
* xf86AlwaysCoreControl --
*
* Control proc for the integer feedback that controls the always
* core feature.
*
***********************************************************************
*/
static void
xf86AlwaysCoreControl(DeviceIntPtr device,
IntegerCtrl *control)
{
}
/***********************************************************************
*
* Core devices functions --
*
* Test if device is the core device by checking the
* value of always core feedback and the inputInfo struct.
*
***********************************************************************
*/
int
xf86IsCorePointer(DeviceIntPtr device)
{
LocalDevicePtr local = (LocalDevicePtr) device->public.devicePrivate;
return((local->always_core_feedback &&
local->always_core_feedback->ctrl.integer_displayed) ||
(device == inputInfo.pointer));
}
static int
xf86IsAlwaysCore(DeviceIntPtr device)
{
LocalDevicePtr local = (LocalDevicePtr) device->public.devicePrivate;
return(local->always_core_feedback &&
local->always_core_feedback->ctrl.integer_displayed);
}
int
xf86IsCoreKeyboard(DeviceIntPtr device)
{
LocalDevicePtr local = (LocalDevicePtr) device->public.devicePrivate;
return((local->flags & XI86_ALWAYS_CORE) ||
(device == inputInfo.keyboard));
}
void
xf86AlwaysCore(LocalDevicePtr local,
Bool always)
{
if (always) {
local->flags |= XI86_ALWAYS_CORE;
} else {
local->flags &= ~XI86_ALWAYS_CORE;
}
}
/***********************************************************************
*
* xf86CheckButton --
*
* Test if the core pointer button state is coherent with
* the button event to send.
*
***********************************************************************
*/
Bool
xf86CheckButton(int button,
int down)
{
/* The device may have up to MSE_MAXBUTTONS (12) buttons. */
int state = (inputInfo.pointer->button->state & 0x0fff00) >> 8;
int check = (state & (1 << (button - 1)));
if ((check && down) && (!check && !down)) {
return FALSE;
}
return TRUE;
}
/***********************************************************************
*
* ReadInput --
* Wakeup handler to catch input and dispatch it to our
* input routines if necessary.
*
***********************************************************************
*/
static void
ReadInput(pointer block_data,
int select_status,
pointer read_mask)
{
int i;
LocalDevicePtr local_dev;
fd_set* LastSelectMask = (fd_set*) read_mask;
fd_set devices_with_input;
extern fd_set EnabledDevices;
if (select_status < 1)
return;
XFD_ANDSET(&devices_with_input, LastSelectMask, &EnabledDevices);
if (!XFD_ANYSET(&devices_with_input))
return;
for (i = 0; i < num_devices; i++) {
local_dev = localDevices[i];
if (local_dev->read_input &&
(local_dev->fd >= 0) &&
(FD_ISSET(local_dev->fd, ((fd_set *) read_mask)) != 0)) {
(*local_dev->read_input)(local_dev);
break;
}
}
}
/***********************************************************************
*
* configExtendedInputSection --
*
***********************************************************************
*/
void
xf86ConfigExtendedInputSection(LexPtr val)
{
int i;
int token;
#ifndef DYNAMIC_MODULE
# ifdef JOYSTICK_SUPPORT
xf86AddDeviceAssoc(&joystick_assoc);
# endif
# ifdef WACOM_SUPPORT
xf86AddDeviceAssoc(&wacom_stylus_assoc);
xf86AddDeviceAssoc(&wacom_cursor_assoc);
xf86AddDeviceAssoc(&wacom_eraser_assoc);
# endif
# ifdef ELOGRAPHICS_SUPPORT
xf86AddDeviceAssoc(&elographics_assoc);
# endif
# ifdef SUMMASKETCH_SUPPORT
xf86AddDeviceAssoc(&summasketch_assoc);
# endif
#endif
xf86AddDeviceAssoc(&mouse_assoc);
num_devices = 0;
max_devices = 3;
localDevices = (LocalDevicePtr*) xalloc(sizeof(LocalDevicePtr)*max_devices);
while ((token = xf86GetToken(XinputTab)) != ENDSECTION)
{
if (token == SUBSECTION)
{
int found = 0;
if (xf86GetToken(NULL) != STRING)
xf86ConfigError("SubSection name expected");
for(i=0; !found && i<numAssoc; i++)
{
if (StrCaseCmp(val->str, deviceAssoc[i]->config_section_name) == 0)
{
if (num_devices == max_devices) {
max_devices *= 2;
localDevices = (LocalDevicePtr*) xrealloc(localDevices,
sizeof(LocalDevicePtr)*max_devices);
}
localDevices[num_devices] = deviceAssoc[i]->device_allocate();
if (localDevices[num_devices] && localDevices[num_devices]->device_config)
{
(*localDevices[num_devices]->device_config)(localDevices,
num_devices,
num_devices+1,
val);
localDevices[num_devices]->flags |= XI86_CONFIGURED;
num_devices++;
}
found = 1;
}
}
if (!found)
xf86ConfigError("Invalid SubSection name");
}
else
xf86ConfigError("XInput keyword section expected");
}
}
/***********************************************************************
*
* xf86AddDeviceAssoc --
*
* Add an association to the array deviceAssoc. This is needed to
* allow dynamic loading of devices to register themself.
*
***********************************************************************
*/
void
xf86AddDeviceAssoc(DeviceAssocPtr assoc)
{
if (!deviceAssoc) {
maxAssoc = 10;
deviceAssoc = (DeviceAssocPtr*) xalloc(sizeof(DeviceAssocPtr)*maxAssoc);
} else {
if (maxAssoc == numAssoc) {
maxAssoc *= 2;
deviceAssoc = (DeviceAssocPtr*) xrealloc(deviceAssoc, sizeof(DeviceAssocPtr)*maxAssoc);
}
}
deviceAssoc[numAssoc] = assoc;
numAssoc++;
}
/***********************************************************************
*
* xf86XinputFinalizeInit --
*
* Create and initialize an integer feedback to control the always
* core feature.
*
***********************************************************************
*/
void
xf86XinputFinalizeInit(DeviceIntPtr dev)
{
LocalDevicePtr local = (LocalDevicePtr)dev->public.devicePrivate;
if (InitIntegerFeedbackClassDeviceStruct(dev, xf86AlwaysCoreControl) == FALSE) {
ErrorF("Unable to init integer feedback for always core feature\n");
} else {
local->always_core_feedback = dev->intfeed;
dev->intfeed->ctrl.integer_displayed = (local->flags & XI86_ALWAYS_CORE) ? 1 : 0;
}
}
/***********************************************************************
*
* InitExtInput --
*
* Initialize any extended devices we might have. It is called from
* ddx InitInput.
*
***********************************************************************
*/
void
InitExtInput()
{
DeviceIntPtr dev;
int i;
/* Register a Wakeup handler to handle input when generated */
RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr) NoopDDA, ReadInput,
NULL);
/* Add each device */
for (i = 0; i < num_devices; i++) {
if (localDevices[i]->flags & XI86_CONFIGURED) {
int open_on_init;
open_on_init = !(localDevices[i]->flags & XI86_NO_OPEN_ON_INIT) ||
(localDevices[i]->flags & XI86_ALWAYS_CORE);
dev = AddInputDevice(localDevices[i]->device_control,
open_on_init);
if (dev == NULL)
FatalError("Too many input devices");
localDevices[i]->atom = MakeAtom(localDevices[i]->name,
strlen(localDevices[i]->name),
TRUE);
dev->public.devicePrivate = (pointer) localDevices[i];
localDevices[i]->dev = dev;
xf86XinputFinalizeInit(dev);
RegisterOtherDevice(dev);
if (serverGeneration == 1)
ErrorF("%s Adding extended device \"%s\" (type: %s)\n", XCONFIG_GIVEN,
localDevices[i]->name, localDevices[i]->type_name);
}
}
}
/***********************************************************************
*
* Caller: ProcXOpenDevice
*
* This is the implementation-dependent routine to open an input device.
* Some implementations open all input devices when the server is first
* initialized, and never close them. Other implementations open only
* the X pointer and keyboard devices during server initialization,
* and only open other input devices when some client makes an
* XOpenDevice request. This entry point is for the latter type of
* implementation.
*
* If the physical device is not already open, do it here. In this case,
* you need to keep track of the fact that one or more clients has the
* device open, and physically close it when the last client that has
* it open does an XCloseDevice.
*
* The default implementation is to do nothing (assume all input devices
* are opened during X server initialization and kept open).
*
***********************************************************************
*/
void
OpenInputDevice (dev, client, status)
DeviceIntPtr dev;
ClientPtr client;
int *status;
{
extern int BadDevice;
if (!dev->inited) {
*status = BadDevice;
} else {
if (!dev->public.on) {
if (!EnableDevice(dev)) {
*status = BadDevice;
} else {
/* to prevent ProcXOpenDevice to call EnableDevice again */
dev->startup = FALSE;
}
}
}
}
/***********************************************************************
*
* Caller: ProcXChangeKeyboardDevice
*
* This procedure does the implementation-dependent portion of the work
* needed to change the keyboard device.
*
* The X keyboard device has a FocusRec. If the device that has been
* made into the new X keyboard did not have a FocusRec,
* ProcXChangeKeyboardDevice will allocate one for it.
*
* If you do not want clients to be able to focus the old X keyboard
* device, call DeleteFocusClassDeviceStruct to free the FocusRec.
*
* If you support input devices with keys that you do not want to be
* used as the X keyboard, you need to check for them here and return
* a BadDevice error.
*
* The default implementation is to do nothing (assume you do want
* clients to be able to focus the old X keyboard). The commented-out
* sample code shows what you might do if you don't want the default.
*
***********************************************************************
*/
int
ChangeKeyboardDevice (old_dev, new_dev)
DeviceIntPtr old_dev;
DeviceIntPtr new_dev;
{
/**********************************************************************
* DeleteFocusClassDeviceStruct(old_dev); * defined in xchgptr.c *
**********************************************************************/
return !Success;
}
/***********************************************************************
*
* Caller: ProcXChangePointerDevice
*
* This procedure does the implementation-dependent portion of the work
* needed to change the pointer device.
*
* The X pointer device does not have a FocusRec. If the device that
* has been made into the new X pointer had a FocusRec,
* ProcXChangePointerDevice will free it.
*
* If you want clients to be able to focus the old pointer device that
* has now become accessible through the input extension, you need to
* add a FocusRec to it here.
*
* The XChangePointerDevice protocol request also allows the client
* to choose which axes of the new pointer device are used to move
* the X cursor in the X- and Y- directions. If the axes are different
* than the default ones, you need to keep track of that here.
*
* If you support input devices with valuators that you do not want to be
* used as the X pointer, you need to check for them here and return a
* BadDevice error.
*
* The default implementation is to do nothing (assume you don't want
* clients to be able to focus the old X pointer). The commented-out
* sample code shows what you might do if you don't want the default.
*
***********************************************************************
*/
int
#ifdef NeedFunctionPrototypes
ChangePointerDevice (
DeviceIntPtr old_dev,
DeviceIntPtr new_dev,
unsigned char x,
unsigned char y)
#else
ChangePointerDevice (old_dev, new_dev, x, y)
DeviceIntPtr old_dev, new_dev;
unsigned char x, y;
#endif /* NeedFunctionPrototypes */
{
/************************************************************************
InitFocusClassDeviceStruct(old_dev); * allow focusing old ptr*
x_axis = x; * keep track of new x-axis*
y_axis = y; * keep track of new y-axis*
if (x_axis != 0 || y_axis != 1)
axes_changed = TRUE; * remember axes have changed*
else
axes_changed = FALSE;
*************************************************************************/
/*
* We don't allow axis swap or other exotic features.
*/
if (x == 0 && y == 1) {
LocalDevicePtr old_local = (LocalDevicePtr)old_dev->public.devicePrivate;
LocalDevicePtr new_local = (LocalDevicePtr)new_dev->public.devicePrivate;
InitFocusClassDeviceStruct(old_dev);
/* Restore Extended motion history information */
old_dev->valuator->GetMotionProc = old_local->motion_history_proc;
old_dev->valuator->numMotionEvents = old_local->history_size;
/* Save Extended motion history information */
new_local->motion_history_proc = new_dev->valuator->GetMotionProc;
new_local->history_size = new_dev->valuator->numMotionEvents;
/* Set Core motion history information */
new_dev->valuator->GetMotionProc = miPointerGetMotionEvents;
new_dev->valuator->numMotionEvents = miPointerGetMotionBufferSize();
return Success;
}
else
return !Success;
}
/***********************************************************************
*
* Caller: ProcXCloseDevice
*
* Take care of implementation-dependent details of closing a device.
* Some implementations may actually close the device, others may just
* remove this clients interest in that device.
*
* The default implementation is to do nothing (assume all input devices
* are initialized during X server initialization and kept open).
*
***********************************************************************
*/
void
CloseInputDevice (d, client)
DeviceIntPtr d;
ClientPtr client;
{
ErrorF("ProcXCloseDevice to close or not ?\n");
}
/***********************************************************************
*
* Caller: ProcXListInputDevices
*
* This is the implementation-dependent routine to initialize an input
* device to the point that information about it can be listed.
* Some implementations open all input devices when the server is first
* initialized, and never close them. Other implementations open only
* the X pointer and keyboard devices during server initialization,
* and only open other input devices when some client makes an
* XOpenDevice request. If some other process has the device open, the
* server may not be able to get information about the device to list it.
*
* This procedure should be used by implementations that do not initialize
* all input devices at server startup. It should do device-dependent
* initialization for any devices not previously initialized, and call
* AddInputDevice for each of those devices so that a DeviceIntRec will be
* created for them.
*
* The default implementation is to do nothing (assume all input devices
* are initialized during X server initialization and kept open).
* The commented-out sample code shows what you might do if you don't want
* the default.
*
***********************************************************************
*/
void
AddOtherInputDevices ()
{
}
/****************************************************************************
*
* Caller: ProcXSetDeviceMode
*
* Change the mode of an extension device.
* This function is used to change the mode of a device from reporting
* relative motion to reporting absolute positional information, and
* vice versa.
* The default implementation below is that no such devices are supported.
*
***********************************************************************
*/
int
SetDeviceMode (client, dev, mode)
register ClientPtr client;
DeviceIntPtr dev;
int mode;
{
LocalDevicePtr local = (LocalDevicePtr)dev->public.devicePrivate;
if (local->switch_mode) {
return (*local->switch_mode)(client, dev, mode);
}
else
return BadMatch;
}
/***********************************************************************
*
* Caller: ProcXSetDeviceValuators
*
* Set the value of valuators on an extension input device.
* This function is used to set the initial value of valuators on
* those input devices that are capable of reporting either relative
* motion or an absolute position, and allow an initial position to be set.
* The default implementation below is that no such devices are supported.
*
***********************************************************************
*/
int
SetDeviceValuators (client, dev, valuators, first_valuator, num_valuators)
register ClientPtr client;
DeviceIntPtr dev;
int *valuators;
int first_valuator;
int num_valuators;
{
return BadMatch;
}
/***********************************************************************
*
* Caller: ProcXChangeDeviceControl
*
* Change the specified device controls on an extension input device.
*
***********************************************************************
*/
int
ChangeDeviceControl (client, dev, control)
register ClientPtr client;
DeviceIntPtr dev;
xDeviceCtl *control;
{
LocalDevicePtr local = (LocalDevicePtr)dev->public.devicePrivate;
if (!local->control_proc) {
return (BadMatch);
}
else {
return (*local->control_proc)(local, control);
}
}
/*
* adapted from mieq.c to support extended events
*
*/
extern InputInfo inputInfo;
#define QUEUE_SIZE 256
typedef struct _Event {
xEvent event;
#ifdef XINPUT
deviceValuator val;
#endif
ScreenPtr pScreen;
} EventRec, *EventPtr;
typedef struct _EventQueue {
HWEventQueueType head, tail;
CARD32 lastEventTime; /* to avoid time running backwards */
Bool lastMotion;
EventRec events[QUEUE_SIZE]; /* static allocation for signals */
DevicePtr pKbd, pPtr; /* device pointer, to get funcs */
ScreenPtr pEnqueueScreen; /* screen events are being delivered to */
ScreenPtr pDequeueScreen; /* screen events are being dispatched to */
} EventQueueRec, *EventQueuePtr;
static EventQueueRec xf86EventQueue;
Bool
xf86eqInit (pKbd, pPtr)
DevicePtr pKbd, pPtr;
{
xf86EventQueue.head = xf86EventQueue.tail = 0;
xf86EventQueue.lastEventTime = GetTimeInMillis ();
xf86EventQueue.pKbd = pKbd;
xf86EventQueue.pPtr = pPtr;
xf86EventQueue.lastMotion = FALSE;
xf86EventQueue.pEnqueueScreen = screenInfo.screens[0];
xf86EventQueue.pDequeueScreen = xf86EventQueue.pEnqueueScreen;
SetInputCheck (&xf86EventQueue.head, &xf86EventQueue.tail);
return TRUE;
}
/*
* Must be reentrant with ProcessInputEvents. Assumption: xf86eqEnqueue
* will never be interrupted. If this is called from both signal
* handlers and regular code, make sure the signal is suspended when
* called from regular code.
*/
void
xf86eqEnqueue (e)
xEvent *e;
{
int oldtail, newtail;
Bool isMotion;
#ifdef XINPUT
int count;
switch (e->u.u.type)
{
case KeyPress:
case KeyRelease:
case ButtonPress:
case ButtonRelease:
case MotionNotify:
count = 1;
break;
default:
if (!((deviceKeyButtonPointer *) e)->deviceid & MORE_EVENTS)
{
count = 1;
}
else
{
count = 2;
}
break;
}
#endif
oldtail = xf86EventQueue.tail;
isMotion = e->u.u.type == MotionNotify;
if (isMotion && xf86EventQueue.lastMotion && oldtail != xf86EventQueue.head)
{
if (oldtail == 0)
oldtail = QUEUE_SIZE;
oldtail = oldtail - 1;
}
else
{
newtail = oldtail + 1;
if (newtail == QUEUE_SIZE)
newtail = 0;
/* Toss events which come in late */
if (newtail == xf86EventQueue.head)
return;
xf86EventQueue.tail = newtail;
}
xf86EventQueue.lastMotion = isMotion;
xf86EventQueue.events[oldtail].event = *e;
#ifdef XINPUT
if (count == 2)
{
xf86EventQueue.events[oldtail].val = *((deviceValuator *) (((deviceKeyButtonPointer *) e)+1));
}
#endif
/*
* Make sure that event times don't go backwards - this
* is "unnecessary", but very useful
*/
if (e->u.keyButtonPointer.time < xf86EventQueue.lastEventTime &&
xf86EventQueue.lastEventTime - e->u.keyButtonPointer.time < 10000)
{
xf86EventQueue.events[oldtail].event.u.keyButtonPointer.time =
xf86EventQueue.lastEventTime;
}
xf86EventQueue.events[oldtail].pScreen = xf86EventQueue.pEnqueueScreen;
}
/*
* Call this from ProcessInputEvents()
*/
void
xf86eqProcessInputEvents ()
{
EventRec *e;
int x, y;
xEvent xe;
#ifdef XINPUT
DeviceIntPtr dev;
int id, count;
deviceKeyButtonPointer *dev_xe;
#endif
while (xf86EventQueue.head != xf86EventQueue.tail)
{
if (screenIsSaved == SCREEN_SAVER_ON)
SaveScreens (SCREEN_SAVER_OFF, ScreenSaverReset);
#ifdef DPMSExtension
if (DPMSPowerLevel != DPMSModeOn)
DPMSSet(DPMSModeOn);
#endif
e = &xf86EventQueue.events[xf86EventQueue.head];
/*
* Assumption - screen switching can only occur on motion events
*/
if (e->pScreen != xf86EventQueue.pDequeueScreen)
{
xf86EventQueue.pDequeueScreen = e->pScreen;
x = e->event.u.keyButtonPointer.rootX;
y = e->event.u.keyButtonPointer.rootY;
if (xf86EventQueue.head == QUEUE_SIZE - 1)
xf86EventQueue.head = 0;
else
++xf86EventQueue.head;
NewCurrentScreen (xf86EventQueue.pDequeueScreen, x, y);
}
else
{
xe = e->event;
if (xf86EventQueue.head == QUEUE_SIZE - 1)
xf86EventQueue.head = 0;
else
++xf86EventQueue.head;
switch (xe.u.u.type)
{
case KeyPress:
case KeyRelease:
(*xf86EventQueue.pKbd->processInputProc)
(&xe, (DeviceIntPtr)xf86EventQueue.pKbd, 1);
break;
#ifdef XINPUT
case ButtonPress:
case ButtonRelease:
case MotionNotify:
(*(inputInfo.pointer->public.processInputProc))
(&xe, (DeviceIntPtr)inputInfo.pointer, 1);
break;
default:
dev_xe = (deviceKeyButtonPointer *) e;
id = dev_xe->deviceid & DEVICE_BITS;
if (!(dev_xe->deviceid & MORE_EVENTS)) {
count = 1;
} else {
count = 2;
}
dev = LookupDeviceIntRec(id);
if (dev == NULL)
{
ErrorF("LookupDeviceIntRec id=0x%x not found\n", id);
/* FatalError("xf86eqProcessInputEvents : device not found.\n");
*/
break;
}
if (!dev->public.processInputProc)
{
FatalError("xf86eqProcessInputEvents : device has no input proc.\n");
break;
}
(*dev->public.processInputProc)(&e->event, dev, count);
#else
default:
(*xf86EventQueue.pPtr->processInputProc)
(&xe, (DeviceIntPtr)xf86EventQueue.pPtr, 1);
#endif
break;
}
}
}
}
/*
* convenient functions to post events
*/
void
xf86PostMotionEvent(DeviceIntPtr device,
int is_absolute,
int first_valuator,
int num_valuators,
...)
{
va_list var;
int loop;
xEvent xE[2];
deviceKeyButtonPointer *xev = (deviceKeyButtonPointer*) xE;
deviceValuator *xv = (deviceValuator*) xev+1;
LocalDevicePtr local = (LocalDevicePtr)device->public.devicePrivate;
char *buff;
Time current = GetTimeInMillis();
if (HAS_MOTION_HISTORY(local)) {
buff = ((char *)local->motion_history +
(sizeof(INT32) * local->dev->valuator->numAxes + sizeof(Time)) * local->last);
} else
buff = 0;
va_start(var, num_valuators);
for(loop=0; loop<num_valuators; loop++) {
switch (loop % 6) {
case 0:
xv->valuator0 = va_arg(var, int);
break;
case 1:
xv->valuator1 = va_arg(var, int);
break;
case 2:
xv->valuator2 = va_arg(var, int);
break;
case 3:
xv->valuator3 = va_arg(var, int);
break;
case 4:
xv->valuator4 = va_arg(var, int);
break;
case 5:
xv->valuator5 = va_arg(var, int);
break;
}
if ((loop % 6 == 5) || (loop == num_valuators - 1)) {
if (!xf86IsCorePointer(device)) {
xev->type = DeviceMotionNotify;
xev->detail = 0;
xf86Info.lastEventTime = xev->time = current;
xev->deviceid = device->id | MORE_EVENTS;
xv->type = DeviceValuator;
xv->deviceid = device->id;
xv->num_valuators = (loop % 6) + 1;
xv->first_valuator = first_valuator + (loop / 6) * 6;
xv->device_state = 0;
if (HAS_MOTION_HISTORY(local)) {
*(Time*)buff = current;
memcpy(buff+sizeof(Time)+sizeof(INT32)*xv->first_valuator, &xv->valuator0,
sizeof(INT32)*xv->num_valuators);
}
xf86eqEnqueue(xE);
} else {
xf86Info.lastEventTime = current;
if (num_valuators >= 2) {
if (is_absolute) {
miPointerAbsoluteCursor(xv->valuator0, xv->valuator1, xf86Info.lastEventTime);
} else {
if (device->ptrfeed) {
/* modeled from xf86Events.c */
if ((abs(xv->valuator0) + abs(xv->valuator1)) >= device->ptrfeed->ctrl.threshold) {
xv->valuator0 = (xv->valuator0 * device->ptrfeed->ctrl.num) / device->ptrfeed->ctrl.den;
xv->valuator1 = (xv->valuator1 * device->ptrfeed->ctrl.num) / device->ptrfeed->ctrl.den;
}
}
miPointerDeltaCursor(xv->valuator0, xv->valuator1, xf86Info.lastEventTime);
}
}
break;
}
}
va_end(var);
}
if (HAS_MOTION_HISTORY(local)) {
local->last = (local->last + 1) % device->valuator->numMotionEvents;
if (local->last == local->first)
local->first = (local->first + 1) % device->valuator->numMotionEvents;
}
}
void
xf86PostProximityEvent(DeviceIntPtr device,
int is_in,
int first_valuator,
int num_valuators,
...)
{
va_list var;
int loop;
xEvent xE[2];
deviceKeyButtonPointer *xev = (deviceKeyButtonPointer*) xE;
deviceValuator *xv = (deviceValuator*) xev+1;
va_start(var, num_valuators);
for(loop=0; loop<num_valuators; loop++) {
switch (loop % 6) {
case 0:
xv->valuator0 = va_arg(var, int);
break;
case 1:
xv->valuator1 = va_arg(var, int);
break;
case 2:
xv->valuator2 = va_arg(var, int);
break;
case 3:
xv->valuator3 = va_arg(var, int);
break;
case 4:
xv->valuator4 = va_arg(var, int);
break;
case 5:
xv->valuator5 = va_arg(var, int);
break;
}
if ((loop % 6 == 5) || (loop == num_valuators - 1)) {
xev->type = is_in ? ProximityIn : ProximityOut;
xev->detail = 0;
xf86Info.lastEventTime = xev->time = GetTimeInMillis();
xev->deviceid = device->id | MORE_EVENTS;
xv->type = DeviceValuator;
xv->deviceid = device->id;
xv->num_valuators = (loop % 6) + 1;
xv->first_valuator = first_valuator + (loop / 6) * 6;
xv->device_state = 0;
xf86eqEnqueue(xE);
}
}
va_end(var);
}
void
xf86PostButtonEvent(DeviceIntPtr device,
int is_absolute,
int button,
int is_down,
int first_valuator,
int num_valuators,
...)
{
va_list var;
int loop;
xEvent xE[2];
deviceKeyButtonPointer *xev = (deviceKeyButtonPointer*) xE;
deviceValuator *xv = (deviceValuator*) xev+1;
int is_core_pointer = xf86IsCorePointer(device);
/* Check the core pointer button state not to send an inconsistent
* event. This can happen with the AlwaysCore feature.
*/
if (is_core_pointer && !xf86CheckButton(button, is_down)) {
return;
}
va_start(var, num_valuators);
for(loop=0; loop<num_valuators; loop++) {
switch (loop % 6) {
case 0:
xv->valuator0 = va_arg(var, int);
break;
case 1:
xv->valuator1 = va_arg(var, int);
break;
case 2:
xv->valuator2 = va_arg(var, int);
break;
case 3:
xv->valuator3 = va_arg(var, int);
break;
case 4:
xv->valuator4 = va_arg(var, int);
break;
case 5:
xv->valuator5 = va_arg(var, int);
break;
}
if (((loop % 6 == 5) || (loop == num_valuators - 1)) &&
!is_core_pointer) {
xev->type = is_down ? DeviceButtonPress : DeviceButtonRelease;
xev->detail = button;
xf86Info.lastEventTime = xev->time = GetTimeInMillis();
xev->deviceid = device->id | MORE_EVENTS;
xv->type = DeviceValuator;
xv->deviceid = device->id;
xv->device_state = 0;
/* if the device is in the relative mode we don't have to send valuators */
xv->num_valuators = is_absolute ? (loop % 6) + 1 : 0;
xv->first_valuator = first_valuator + (loop / 6) * 6;
xf86eqEnqueue(xE);
/* if the device is in the relative mode only one event is needed */
if (!is_absolute) break;
}
if (is_core_pointer && loop == 1) {
int cx, cy;
GetSpritePosition(&cx, &cy);
/* Try to find the index in the core buttons map
* which corresponds to the extended button for
* an AlwaysCore device.
*/
if (xf86IsAlwaysCore(device)) {
int loop;
button = device->button->map[button];
for(loop=1; loop<=inputInfo.pointer->button->numButtons; loop++) {
if (inputInfo.pointer->button->map[loop] == button) {
button = loop;
break;
}
}
}
xE->u.u.type = is_down ? ButtonPress : ButtonRelease;
xE->u.u.detail = button;
xE->u.keyButtonPointer.rootY = cx;
xE->u.keyButtonPointer.rootX = cy;
xf86Info.lastEventTime = xE->u.keyButtonPointer.time = GetTimeInMillis();
xf86eqEnqueue(xE);
break;
}
}
va_end(var);
}
void
xf86PostKeyEvent(DeviceIntPtr device,
unsigned int key_code,
int is_down,
int is_absolute,
int first_valuator,
int num_valuators,
...)
{
va_list var;
int loop;
xEvent xE[2];
deviceKeyButtonPointer *xev = (deviceKeyButtonPointer*) xE;
deviceValuator *xv = (deviceValuator*) xev+1;
va_start(var, num_valuators);
for(loop=0; loop<num_valuators; loop++) {
switch (loop % 6) {
case 0:
xv->valuator0 = va_arg(var, int);
break;
case 1:
xv->valuator1 = va_arg(var, int);
break;
case 2:
xv->valuator2 = va_arg(var, int);
break;
case 3:
xv->valuator3 = va_arg(var, int);
break;
case 4:
xv->valuator4 = va_arg(var, int);
break;
case 5:
xv->valuator5 = va_arg(var, int);
break;
}
if (((loop % 6 == 5) || (loop == num_valuators - 1))) {
xev->type = is_down ? DeviceKeyPress : DeviceKeyRelease;
xev->detail = key_code;
xf86Info.lastEventTime = xev->time = GetTimeInMillis();
xev->deviceid = device->id | MORE_EVENTS;
xv->type = DeviceValuator;
xv->deviceid = device->id;
xv->device_state = 0;
/* if the device is in the relative mode we don't have to send valuators */
xv->num_valuators = is_absolute ? (loop % 6) + 1 : 0;
xv->first_valuator = first_valuator + (loop / 6) * 6;
xf86eqEnqueue(xE);
/* if the device is in the relative mode only one event is needed */
if (!is_absolute) break;
}
}
va_end(var);
}
/*
* Motion history management.
*/
void
xf86MotionHistoryAllocate(LocalDevicePtr local)
{
ValuatorClassPtr valuator = local->dev->valuator;
if (!HAS_MOTION_HISTORY(local))
return;
local->motion_history = xalloc((sizeof(INT32) * valuator->numAxes + sizeof(Time))
* valuator->numMotionEvents);
local->first = 0;
local->last = 0;
}
int
xf86GetMotionEvents(DeviceIntPtr dev,
xTimecoord *buff,
unsigned long start,
unsigned long stop,
ScreenPtr pScreen)
{
LocalDevicePtr local = (LocalDevicePtr)dev->public.devicePrivate;
ValuatorClassPtr valuator = dev->valuator;
int num = 0;
int loop = local->first;
int size;
Time current;
if (!HAS_MOTION_HISTORY(local))
return 0;
size = (sizeof(INT32) * valuator->numAxes + sizeof(Time));
while (loop != local->last) {
current = *(Time*)(((char *)local->motion_history)+loop*size);
if (current > stop)
return num;
if (current >= start) {
memcpy(((char *)buff)+size*num,
((char *)local->motion_history)+loop*size, size);
num++;
}
loop = (loop + 1) % valuator->numMotionEvents;
}
return num;
}
/* end of xf86Xinput.c */