diff options
Diffstat (limited to 'nx-X11/programs/Xserver/hw/xfree86/common/xf86Xinput.c')
-rw-r--r-- | nx-X11/programs/Xserver/hw/xfree86/common/xf86Xinput.c | 1513 |
1 files changed, 1513 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/hw/xfree86/common/xf86Xinput.c b/nx-X11/programs/Xserver/hw/xfree86/common/xf86Xinput.c new file mode 100644 index 000000000..cc9e76361 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/xfree86/common/xf86Xinput.c @@ -0,0 +1,1513 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Xinput.c,v 3.70 2003/11/03 05:11:02 tsi Exp $ */ +/* + * Copyright 1995-1999 by Frederic Lepied, France. <Lepied@XFree86.org> + * + * 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. + * + */ +/* + * Copyright (c) 2000-2002 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ +/* $XConsortium: xf86Xinput.c /main/14 1996/10/27 11:05:25 kaleb $ */ +/* $XdotOrg: xc/programs/Xserver/hw/xfree86/common/xf86Xinput.c,v 1.7 2005/10/21 19:06:13 ajax Exp $ */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <X11/Xfuncproto.h> +#include <X11/Xmd.h> +#ifdef XINPUT +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#endif +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86Xinput.h" +#ifdef XINPUT +#include "XIstubs.h" +#endif +#include "mipointer.h" +#include "xf86InPriv.h" + +#ifdef DPMSExtension +#define DPMS_SERVER +#include <X11/extensions/dpms.h> +#include "dpmsproc.h" +#endif + +#ifdef XFreeXDGA +#include "dgaproc.h" +#endif + +#include "exevents.h" /* AddInputDevice */ +#include "exglobals.h" + +#define EXTENSION_PROC_ARGS void * +#include "extnsionst.h" +#include "extinit.h" /* LookupDeviceIntRec */ + +#include "windowstr.h" /* screenIsSaved */ + +#include <stdarg.h> + +#include "osdep.h" /* EnabledDevices */ +#include <X11/Xpoll.h> +#include "xf86_OSproc.h" /* sigio stuff */ + +/****************************************************************************** + * debugging macro + *****************************************************************************/ +#ifdef DBG +#undef DBG +#endif +#ifdef DEBUG +#undef DEBUG +#endif + +#define DEBUG 0 + +#if DEBUG +static int debug_level = 0; + +#define DBG(lvl, f) {if ((lvl) <= debug_level) f;} +#else +#define DBG(lvl, f) +#endif + +/****************************************************************************** + * macros + *****************************************************************************/ +#define ENQUEUE(e) xf86eqEnqueue((e)) + +/*********************************************************************** + * + * 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) +{ + return(device == inputInfo.pointer); +} + +static int +xf86ShareCorePointer(DeviceIntPtr device) +{ + LocalDevicePtr local = (LocalDevicePtr) device->public.devicePrivate; + + return((local->always_core_feedback && + local->always_core_feedback->ctrl.integer_displayed)); +} + +static Bool +xf86SendDragEvents(DeviceIntPtr device) +{ + LocalDevicePtr local = (LocalDevicePtr) device->public.devicePrivate; + + if (inputInfo.pointer->button->buttonsDown > 0) + return (local->flags & XI86_SEND_DRAG_EVENTS); + else + return (TRUE); +} + +int +xf86IsCoreKeyboard(DeviceIntPtr device) +{ + LocalDevicePtr local = (LocalDevicePtr) device->public.devicePrivate; + + return((local->flags & XI86_ALWAYS_CORE) || + (device == inputInfo.keyboard)); +} + +void +xf86XInputSetSendCoreEvents(LocalDevicePtr local, Bool always) +{ + if (always) { + local->flags |= XI86_ALWAYS_CORE; + } else { + local->flags &= ~XI86_ALWAYS_CORE; + } +} + +static int xf86CoreButtonState; + +/*********************************************************************** + * + * xf86CheckButton -- + * + * Test if the core pointer button state is coherent with + * the button event to send. + * + *********************************************************************** + */ +Bool +xf86CheckButton(int button, + int down) +{ + int check; + int bit = (1 << (button - 1)); + + check = xf86CoreButtonState & bit; + + DBG(5, ErrorF("xf86CheckButton " + "button=%d down=%d state=%d check=%d returns ", + button, down, xf86CoreButtonState, check)); + if ((check && down) || (!check && !down)) { + DBG(5, ErrorF("FALSE\n")); + return FALSE; + } + xf86CoreButtonState ^= bit; + + DBG(5, ErrorF("TRUE\n")); + return TRUE; +} + +/*********************************************************************** + * + * xf86ProcessCommonOptions -- + * + * Process global options. + * + *********************************************************************** + */ +void +xf86ProcessCommonOptions(LocalDevicePtr local, + pointer list) +{ + if (xf86SetBoolOption(list, "AlwaysCore", 0) || + xf86SetBoolOption(list, "SendCoreEvents", 0)) { + local->flags |= XI86_ALWAYS_CORE; + xf86Msg(X_CONFIG, "%s: always reports core events\n", local->name); + } + + if (xf86SetBoolOption(list, "CorePointer", 0)) { + local->flags |= XI86_CORE_POINTER; + xf86Msg(X_CONFIG, "%s: Core Pointer\n", local->name); + } + + if (xf86SetBoolOption(list, "CoreKeyboard", 0)) { + local->flags |= XI86_CORE_KEYBOARD; + xf86Msg(X_CONFIG, "%s: Core Keyboard\n", local->name); + } + + if (xf86SetBoolOption(list, "SendDragEvents", 1)) { + local->flags |= XI86_SEND_DRAG_EVENTS; + } else { + xf86Msg(X_CONFIG, "%s: doesn't report drag events\n", local->name); + } + + local->history_size = xf86SetIntOption(list, "HistorySize", 0); + + if (local->history_size > 0) { + xf86Msg(X_CONFIG, "%s: has a history of %d motions\n", local->name, + local->history_size); + } +} + +/*********************************************************************** + * + * xf86XinputFinalizeInit -- + * + * Create and initialize an integer feedback to control the always + * core feature. + * + *********************************************************************** + */ +void +xf86XinputFinalizeInit(DeviceIntPtr dev) +{ + LocalDevicePtr local = (LocalDevicePtr)dev->public.devicePrivate; + + local->dxremaind = 0.0; + local->dyremaind = 0.0; + + 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; + } +} + +/*********************************************************************** + * + * xf86ActivateDevice -- + * + * Initialize an input device. + * + *********************************************************************** + */ +void +xf86ActivateDevice(LocalDevicePtr local) +{ + DeviceIntPtr dev; + + if (local->flags & XI86_CONFIGURED) { + int open_on_init; + + open_on_init = local->flags & + (XI86_OPEN_ON_INIT | + XI86_ALWAYS_CORE | XI86_CORE_POINTER | XI86_CORE_KEYBOARD); + + dev = AddInputDevice(local->device_control, + open_on_init); + if (dev == NULL) + FatalError("Too many input devices"); + + local->atom = MakeAtom(local->type_name, + strlen(local->type_name), + TRUE); + AssignTypeAndName (dev, local->atom, local->name); + dev->public.devicePrivate = (pointer) local; + local->dev = dev; + + xf86XinputFinalizeInit(dev); + + /* + * XXX Can a single device instance be both core keyboard and + * core pointer? If so, this should be changed. + */ + if (local->flags & XI86_CORE_POINTER) + RegisterPointerDevice(dev); + else if (local->flags & XI86_CORE_KEYBOARD) + RegisterKeyboardDevice(dev); +#ifdef XINPUT + else + RegisterOtherDevice(dev); +#endif + + if (serverGeneration == 1) + xf86Msg(X_INFO, "XINPUT: Adding extended input device \"%s\" (type: %s)\n", + local->name, local->type_name); + } +} + + +#ifdef XINPUT +/*********************************************************************** + * + * 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(DeviceIntPtr dev, + ClientPtr client, + int *status) +{ + 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 (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 +ChangePointerDevice ( + DeviceIntPtr old_dev, + DeviceIntPtr new_dev, + unsigned char x, + unsigned char y) +{ + /************************************************************************ + 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 (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 (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 (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 (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); + } +} +#endif + +/* + * adapted from mieq.c to support extended events + * + */ +#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 (DevicePtr pKbd, DevicePtr 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 (xEvent *e) +{ + int oldtail, newtail; + Bool isMotion; +#ifdef XINPUT + int count; + + xf86AssertBlockedSIGIO ("xf86eqEnqueue"); + switch (e->u.u.type) { + case KeyPress: + case KeyRelease: +#ifdef XFreeXDGA + /* we do this here, because nobody seems to be calling + xf86PostKeyEvent(). We can't steal MotionNotify events here + because the motion-relative information has been lost already. */ + if(DGAStealKeyEvent(xf86EventQueue.pEnqueueScreen->myNum, e)) + return; +#endif + /* fall through */ + case ButtonPress: + case ButtonRelease: + case MotionNotify: + count = 1; + break; + default: +#ifdef XFreeXDGA + if (DGAIsDgaEvent (e)) + { + count = 1; + break; + } +#endif + 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; + struct { + xEvent event; +#ifdef XINPUT + deviceValuator val; +#endif + } 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.event = e->event; + xe.val = e->val; + if (xf86EventQueue.head == QUEUE_SIZE - 1) + xf86EventQueue.head = 0; + else + ++xf86EventQueue.head; + switch (xe.event.u.u.type) { + case KeyPress: + case KeyRelease: + (*xf86EventQueue.pKbd->processInputProc) + (&xe.event, (DeviceIntPtr)xf86EventQueue.pKbd, 1); + break; +#ifdef XINPUT + case ButtonPress: + case ButtonRelease: + case MotionNotify: + (*(inputInfo.pointer->public.processInputProc)) + (&xe.event, (DeviceIntPtr)inputInfo.pointer, 1); + break; + + default: +#ifdef XFreeXDGA + if (DGADeliverEvent (xf86EventQueue.pDequeueScreen, &xe.event)) + break; +#endif + dev_xe = (deviceKeyButtonPointer *) &xe.event; + 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)(&xe.event, dev, count); +#else + default: + (*xf86EventQueue.pPtr->processInputProc) + (&xe.event, (DeviceIntPtr)xf86EventQueue.pPtr, 1); +#endif + break; + } + } + } +} + +void +xf86eqSwitchScreen(ScreenPtr pScreen, + Bool fromDIX) +{ + xf86EventQueue.pEnqueueScreen = pScreen; + + if (fromDIX) + xf86EventQueue.pDequeueScreen = pScreen; +} + +/* + * 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 = 0; + Time current; + Bool is_core = xf86IsCorePointer(device); + Bool is_shared = xf86ShareCorePointer(device); + Bool drag = xf86SendDragEvents(device); + ValuatorClassPtr val = device->valuator; + int valuator[6]; + int oldaxis[6]; + int *axisvals; + int dx = 0, dy = 0; + float mult; + int x, y; + int loop_start; + int i; + int num; + + DBG(5, ErrorF("xf86PostMotionEvent BEGIN 0x%x(%s) is_core=%s is_shared=%s is_absolute=%s\n", + device, device->name, + is_core ? "True" : "False", + is_shared ? "True" : "False", + is_absolute ? "True" : "False")); + + xf86Info.lastEventTime = xev->time = current = GetTimeInMillis(); + + if (!is_core) { + if (HAS_MOTION_HISTORY(local)) { + buff = ((char *)local->motion_history + + (sizeof(INT32) * local->dev->valuator->numAxes + sizeof(Time)) * local->last); + } + } + + if (num_valuators && (!val || (first_valuator + num_valuators > val->numAxes))) { + ErrorF("Bad valuators reported for device \"%s\"\n", device->name); + return; + } + + axisvals = val->axisVal; + + va_start(var, num_valuators); + + loop_start = first_valuator; + for(loop=0; loop<num_valuators; loop++) { + + valuator[loop%6] = va_arg(var,int); + + if (loop % 6 == 5 || loop == num_valuators - 1) { + num = loop % 6 + 1; + /* + * Adjust first two relative valuators + */ + if (!is_absolute && num_valuators >= 2 && loop_start == 0) { + + dx = valuator[0]; + dy = valuator[1]; + + /* + * Accelerate + */ + if (device->ptrfeed && device->ptrfeed->ctrl.num) { + /* modeled from xf86Events.c */ + if (device->ptrfeed->ctrl.threshold) { + if ((abs(dx) + abs(dy)) >= device->ptrfeed->ctrl.threshold) { + local->dxremaind = ((float)dx * (float)(device->ptrfeed->ctrl.num)) / + (float)(device->ptrfeed->ctrl.den) + local->dxremaind; + valuator[0] = (int)local->dxremaind; + local->dxremaind = local->dxremaind - (float)valuator[0]; + + local->dyremaind = ((float)dy * (float)(device->ptrfeed->ctrl.num)) / + (float)(device->ptrfeed->ctrl.den) + local->dyremaind; + valuator[1] = (int)local->dyremaind; + local->dyremaind = local->dyremaind - (float)valuator[1]; + } + } + else if (dx || dy) { + mult = pow((float)(dx*dx+dy*dy), + ((float)(device->ptrfeed->ctrl.num) / + (float)(device->ptrfeed->ctrl.den) - 1.0) / + 2.0) / 2.0; + if (dx) { + local->dxremaind = mult * (float)dx + local->dxremaind; + valuator[0] = (int)local->dxremaind; + local->dxremaind = local->dxremaind - (float)valuator[0]; + } + if (dy) { + local->dyremaind = mult * (float)dy + local->dyremaind; + valuator[1] = (int)local->dyremaind; + local->dyremaind = local->dyremaind - (float)valuator[1]; + } + } + DBG(6, ErrorF("xf86PostMotionEvent acceleration v0=%d v1=%d\n", + valuator[0], valuator[1])); + } + + /* + * Map current position back to device space in case + * the cursor was warped + */ + if (is_core || is_shared) + { + miPointerPosition (&x, &y); + if (local->reverse_conversion_proc) + (*local->reverse_conversion_proc)(local, x, y, axisvals); + else + { + axisvals[0] = x; + axisvals[1] = y; + } + } + } + + /* + * Update axes + */ + for (i = 0; i < num; i++) + { + oldaxis[i] = axisvals[loop_start + i]; + if (is_absolute) + axisvals[loop_start + i] = valuator[i]; + else + axisvals[loop_start + i] += valuator[i]; + } + + /* + * Deliver extension event + */ + if (!is_core) { + xev->type = DeviceMotionNotify; + xev->detail = 0; + xev->deviceid = device->id | MORE_EVENTS; + + xv->type = DeviceValuator; + xv->deviceid = device->id; + + xv->device_state = 0; + xv->num_valuators = num; + xv->first_valuator = loop_start; + memcpy (&xv->valuator0, &axisvals[loop_start], + sizeof(INT32)*xv->num_valuators); + + if (HAS_MOTION_HISTORY(local)) { + *(Time*)buff = current; + memcpy(buff+sizeof(Time)+sizeof(INT32)*xv->first_valuator, + &axisvals[loop_start], + sizeof(INT32)*xv->num_valuators); + } + ENQUEUE(xE); + } + + /* + * Deliver core event + */ + if (is_core || + (is_shared && num_valuators >= 2 && loop_start == 0)) { +#ifdef XFreeXDGA + /* + * Let DGA peek at the event and steal it + */ + xev->type = MotionNotify; + xev->detail = 0; + if (is_absolute) + { + dx = axisvals[0] - oldaxis[0]; + dy = axisvals[1] - oldaxis[1]; + } + if (DGAStealMouseEvent(xf86EventQueue.pEnqueueScreen->myNum, + xE, dx, dy)) + continue; +#endif + if (!(*local->conversion_proc)(local, loop_start, num, + axisvals[0], axisvals[1], + axisvals[2], axisvals[3], + axisvals[4], axisvals[5], + &x, &y)) + continue; + + if (drag) + miPointerAbsoluteCursor (x, y, current); + /* + * Retrieve the position + */ + miPointerPosition (&x, &y); + if (local->reverse_conversion_proc) + (*local->reverse_conversion_proc)(local, x, y, axisvals); + else + { + axisvals[0] = x; + axisvals[1] = y; + } + } + loop_start += 6; + } + } + 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; + } + DBG(5, ErrorF("xf86PostMotionEvent END 0x%x(%s) is_core=%s is_shared=%s\n", + device, device->name, + is_core ? "True" : "False", + is_shared ? "True" : "False")); +} + +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; + ValuatorClassPtr val = device->valuator; + Bool is_core = xf86IsCorePointer(device); + Bool is_absolute = val && ((val->mode & 1) == Relative); + + DBG(5, ErrorF("xf86PostProximityEvent BEGIN 0x%x(%s) prox=%s is_core=%s is_absolute=%s\n", + device, device->name, is_in ? "true" : "false", + is_core ? "True" : "False", + is_absolute ? "True" : "False")); + + if (is_core) { + return; + } + + if (num_valuators && (!val || (first_valuator + num_valuators > val->numAxes))) { + ErrorF("Bad valuators reported for device \"%s\"\n", device->name); + return; + } + + xev->type = is_in ? ProximityIn : ProximityOut; + xev->detail = 0; + xev->deviceid = device->id | MORE_EVENTS; + + xv->type = DeviceValuator; + xv->deviceid = device->id; + xv->device_state = 0; + + if ((device->valuator->mode & 1) == Relative) { + num_valuators = 0; + } + + if (num_valuators != 0) { + int *axisvals = val->axisVal; + + va_start(var, num_valuators); + + for(loop=0; loop<num_valuators; loop++) { + switch (loop % 6) { + case 0: + xv->valuator0 = is_absolute ? va_arg(var, int) : axisvals[loop]; + break; + case 1: + xv->valuator1 = is_absolute ? va_arg(var, int) : axisvals[loop]; + break; + case 2: + xv->valuator2 = is_absolute ? va_arg(var, int) : axisvals[loop]; + break; + case 3: + xv->valuator3 = is_absolute ? va_arg(var, int) : axisvals[loop]; + break; + case 4: + xv->valuator4 = is_absolute ? va_arg(var, int) : axisvals[loop]; + break; + case 5: + xv->valuator5 = is_absolute ? va_arg(var, int) : axisvals[loop]; + break; + } + if ((loop % 6 == 5) || (loop == num_valuators - 1)) { + xf86Info.lastEventTime = xev->time = GetTimeInMillis(); + + xv->num_valuators = (loop % 6) + 1; + xv->first_valuator = first_valuator + (loop / 6) * 6; + ENQUEUE(xE); + } + } + va_end(var); + } + else { + /* no valuator */ + xf86Info.lastEventTime = xev->time = GetTimeInMillis(); + + xv->num_valuators = 0; + xv->first_valuator = 0; + ENQUEUE(xE); + } + DBG(5, ErrorF("xf86PostProximityEvent END 0x%x(%s) prox=%s is_core=%s is_absolute=%s\n", + device, device->name, is_in ? "true" : "false", + is_core ? "True" : "False", + is_absolute ? "True" : "False")); + +} + +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; + ValuatorClassPtr val = device->valuator; + Bool is_core = xf86IsCorePointer(device); + Bool is_shared = xf86ShareCorePointer(device); + + DBG(5, ErrorF("xf86PostButtonEvent BEGIN 0x%x(%s) button=%d down=%s is_core=%s is_shared=%s is_absolute=%s\n", + device, device->name, button, + is_down ? "True" : "False", + is_core ? "True" : "False", + is_shared ? "True" : "False", + is_absolute ? "True" : "False")); + + /* Check the core pointer button state not to send an inconsistent + * event. This can happen with the AlwaysCore feature. + */ + if ((is_core || is_shared) && + !xf86CheckButton(device->button->map[button], is_down)) + { + return; + } + + if (num_valuators && (!val || (first_valuator + num_valuators > val->numAxes))) { + ErrorF("Bad valuators reported for device \"%s\"\n", device->name); + return; + } + + if (!is_core) { + xev->type = is_down ? DeviceButtonPress : DeviceButtonRelease; + xev->detail = button; + xev->deviceid = device->id | MORE_EVENTS; + + xv->type = DeviceValuator; + xv->deviceid = device->id; + xv->device_state = 0; + + if (num_valuators != 0) { + int *axisvals = val->axisVal; + + va_start(var, num_valuators); + + for(loop=0; loop<num_valuators; loop++) { + switch (loop % 6) { + case 0: + xv->valuator0 = is_absolute ? va_arg(var, int) : axisvals[loop]; + break; + case 1: + xv->valuator1 = is_absolute ? va_arg(var, int) : axisvals[loop]; + break; + case 2: + xv->valuator2 = is_absolute ? va_arg(var, int) : axisvals[loop]; + break; + case 3: + xv->valuator3 = is_absolute ? va_arg(var, int) : axisvals[loop]; + break; + case 4: + xv->valuator4 = is_absolute ? va_arg(var, int) : axisvals[loop]; + break; + case 5: + xv->valuator5 = is_absolute ? va_arg(var, int) : axisvals[loop]; + break; + } + if ((loop % 6 == 5) || (loop == num_valuators - 1)) { + xf86Info.lastEventTime = xev->time = GetTimeInMillis(); + xv->num_valuators = (loop % 6) + 1; + xv->first_valuator = first_valuator + (loop / 6) * 6; + ENQUEUE(xE); + + } + } + va_end(var); + } + else { + /* no valuator */ + xf86Info.lastEventTime = xev->time = GetTimeInMillis(); + xv->num_valuators = 0; + xv->first_valuator = 0; + ENQUEUE(xE); + } + } + + /* removed rootX/rootY as DIX sets these fields */ + if (is_core || is_shared) { + xE->u.u.type = is_down ? ButtonPress : ButtonRelease; + xE->u.u.detail = device->button->map[button]; + xf86Info.lastEventTime = xE->u.keyButtonPointer.time = GetTimeInMillis(); + +#ifdef XFreeXDGA + if (!DGAStealMouseEvent(xf86EventQueue.pEnqueueScreen->myNum, xE, 0, 0)) +#endif + ENQUEUE(xE); + } + DBG(5, ErrorF("xf86PostButtonEvent END\n")); +} + +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; + + ENQUEUE(xE); + /* if the device is in the relative mode only one event is needed */ + if (!is_absolute) break; + } + } + va_end(var); +} + +void +xf86PostKeyboardEvent(DeviceIntPtr device, + unsigned int key_code, + int is_down) +{ + xEvent xE[2]; + deviceKeyButtonPointer *xev = (deviceKeyButtonPointer*) xE; + + if (xf86IsCoreKeyboard(device)) { + xev->type = is_down ? KeyPress : KeyRelease; + } else { + xev->type = is_down ? DeviceKeyPress : DeviceKeyRelease; + } + xev->detail = key_code; + xf86Info.lastEventTime = xev->time = GetTimeInMillis(); + +#ifdef XFreeXDGA + /* if(!DGAStealKeyEvent(xf86EventQueue.pEnqueueScreen->myNum, xE)) */ +#endif + ENQUEUE(xE); +} + +/* + * Motion history management. + */ + +void +xf86MotionHistoryAllocate(LocalDevicePtr local) +{ + ValuatorClassPtr valuator = local->dev->valuator; + + if (!HAS_MOTION_HISTORY(local)) + return; + if (local->motion_history) xfree(local->motion_history); + 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; +} + +LocalDevicePtr +xf86FirstLocalDevice() +{ + return xf86InputDevs; +} + +/* + * Cx - raw data from touch screen + * Sxhigh - scaled highest dimension + * (remember, this is of rows - 1 because of 0 origin) + * Sxlow - scaled lowest dimension + * Rxhigh - highest raw value from touch screen calibration + * Rxlow - lowest raw value from touch screen calibration + * + * This function is the same for X or Y coordinates. + * You may have to reverse the high and low values to compensate for + * different orgins on the touch screen vs X. + */ + +int +xf86ScaleAxis(int Cx, + int Sxhigh, + int Sxlow, + int Rxhigh, + int Rxlow ) +{ + int X; + int dSx = Sxhigh - Sxlow; + int dRx = Rxhigh - Rxlow; + + dSx = Sxhigh - Sxlow; + if (dRx) { + X = ((dSx * (Cx - Rxlow)) / dRx) + Sxlow; + } + else { + X = 0; + ErrorF ("Divide by Zero in xf86ScaleAxis"); + } + + if (X > Sxlow) + X = Sxlow; + if (X < Sxhigh) + X = Sxhigh; + + return (X); +} + +/* + * This function checks the given screen against the current screen and + * makes changes if appropriate. It should be called from an XInput driver's + * ReadInput function before any events are posted, if the device is screen + * specific like a touch screen. + */ +void +xf86XInputSetScreen(LocalDevicePtr local, + int screen_number, + int x, + int y) +{ + if ((xf86IsCorePointer(local->dev) || xf86ShareCorePointer(local->dev)) && + (miPointerCurrentScreen() != screenInfo.screens[screen_number])) { + miPointerSetNewScreen (screen_number, x, y); + } +} + + +void +xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, int minval, int maxval, + int resolution, int min_res, int max_res) +{ +#ifdef XINPUT + if (maxval == -1) { + if (axnum == 0) + maxval = screenInfo.screens[0]->width - 1; + else if (axnum == 1) + maxval = screenInfo.screens[0]->height - 1; + /* else? */ + } + InitValuatorAxisStruct(dev, axnum, minval, maxval, resolution, min_res, + max_res); +#endif +} + +/* + * Set the valuator values to be in synch with dix/event.c + * DefineInitialRootWindow(). + */ +void +xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum) +{ +#ifdef XINPUT + if (axnum == 0) + dev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; + else if (axnum == 1) + dev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; +#endif +} + +/* end of xf86Xinput.c */ |