summaryrefslogtreecommitdiff
path: root/hw/xfree86/common/xf86Xinput.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/xfree86/common/xf86Xinput.c')
-rw-r--r--hw/xfree86/common/xf86Xinput.c1264
1 files changed, 1264 insertions, 0 deletions
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
new file mode 100644
index 000000000..7659deb3f
--- /dev/null
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -0,0 +1,1264 @@
+/* $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 */