xserver-multidpi/hw/dmx/input/dmxevents.c
Keith Packard 9838b7032e Introduce a consistent coding style
This is strictly the application of the script 'x-indent-all.sh'
from util/modular. Compared to the patch that Daniel posted in
January, I've added a few indent flags:

	-bap
	-psl
	-T PrivatePtr
	-T pmWait
	-T _XFUNCPROTOBEGIN
	-T _XFUNCPROTOEND
	-T _X_EXPORT

The typedefs were needed to make the output of sdksyms.sh match the
previous output, otherwise, the code is formatted badly enough that
sdksyms.sh generates incorrect output.

The generated code was compared with the previous version and found to
be essentially identical -- "assert" line numbers and BUILD_TIME were
the only differences found.

The comparison was done with this script:

dir1=$1
dir2=$2

for dir in $dir1 $dir2; do
	(cd $dir && find . -name '*.o' | while read file; do
		dir=`dirname $file`
		base=`basename $file .o`
		dump=$dir/$base.dump
		objdump -d $file > $dump
	done)
done

find $dir1 -name '*.dump' | while read dump; do
	otherdump=`echo $dump | sed "s;$dir1;$dir2;"`
	diff -u $dump $otherdump
done

Signed-off-by: Keith Packard <keithp@keithp.com>
Acked-by: Daniel Stone <daniel@fooishbar.org>
Acked-by: Alan Coopersmith <alan.coopersmith@oracle.com>
2012-03-21 13:54:42 -07:00

833 lines
25 KiB
C

/*
* Copyright 2002-2003 Red Hat Inc., Durham, North Carolina.
*
* All Rights Reserved.
*
* 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 on the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* Authors:
* Rickard E. (Rik) Faith <faith@redhat.com>
*
*/
/** \file
* Provide support and helper functions for enqueing events received by
* the low-level input drivers. */
#ifdef HAVE_DMX_CONFIG_H
#include <dmx-config.h>
#endif
#define DMX_EVENTS_DEBUG 0
#include "dmxinputinit.h"
#include "dmxevents.h"
#include "dmxcb.h"
#include "dmxcommon.h"
#include "dmxcursor.h"
#include "dmxmotion.h"
#include "dmxsigio.h"
#include "dmxmap.h"
#include <X11/keysym.h>
#include "opaque.h"
#include "inputstr.h"
#include "inpututils.h"
#include "mipointer.h"
#include "mi.h"
#include "exglobals.h"
#include "xkbsrv.h"
#include "XIstubs.h"
static int dmxGlobalX, dmxGlobalY; /* Global cursor position */
static int dmxGlobalInvalid; /* Flag indicating dmxCoreMotion
* should move the mouse anyway. */
#if DMX_EVENTS_DEBUG
#define DMXDBG0(f) dmxLog(dmxDebug,f)
#define DMXDBG1(f,a) dmxLog(dmxDebug,f,a)
#define DMXDBG2(f,a,b) dmxLog(dmxDebug,f,a,b)
#define DMXDBG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c)
#define DMXDBG4(f,a,b,c,d) dmxLog(dmxDebug,f,a,b,c,d)
#define DMXDBG5(f,a,b,c,d,e) dmxLog(dmxDebug,f,a,b,c,d,e)
#define DMXDBG6(f,a,b,c,d,e,g) dmxLog(dmxDebug,f,a,b,c,d,e,g)
#define DMXDBG7(f,a,b,c,d,e,g,h) dmxLog(dmxDebug,f,a,b,c,d,e,g,h)
#else
#define DMXDBG0(f)
#define DMXDBG1(f,a)
#define DMXDBG2(f,a,b)
#define DMXDBG3(f,a,b,c)
#define DMXDBG4(f,a,b,c,d)
#define DMXDBG5(f,a,b,c,d,e)
#define DMXDBG6(f,a,b,c,d,e,g)
#define DMXDBG7(f,a,b,c,d,e,g,h)
#endif
static int
dmxApplyFunctions(DMXInputInfo * dmxInput, DMXFunctionType f)
{
int i;
int rc = 0;
for (i = 0; i < dmxInput->numDevs; i += dmxInput->devs[i]->binding)
if (dmxInput->devs[i]->functions)
rc += dmxInput->devs[i]->functions(dmxInput->devs[i]->private, f);
return rc;
}
static int
dmxCheckFunctionKeys(DMXLocalInputInfoPtr dmxLocal, int type, KeySym keySym)
{
DMXInputInfo *dmxInput = &dmxInputs[dmxLocal->inputIdx];
#if 1 /* hack to detect ctrl-alt-q, etc */
static int ctrl = 0, alt = 0;
/* keep track of ctrl/alt key status */
if (type == KeyPress && keySym == 0xffe3) {
ctrl = 1;
}
else if (type == KeyRelease && keySym == 0xffe3) {
ctrl = 0;
}
else if (type == KeyPress && keySym == 0xffe9) {
alt = 1;
}
else if (type == KeyRelease && keySym == 0xffe9) {
alt = 0;
}
if (!ctrl || !alt)
return 0;
#else
unsigned short state = 0;
if (dmxLocal->sendsCore)
state = dmxLocalCoreKeyboard->pDevice->key->state;
else if (dmxLocal->pDevice->key)
state = dmxLocal->pDevice->key->state;
DMXDBG3("dmxCheckFunctionKeys: keySym=0x%04x %s state=0x%04x\n",
keySym, type == KeyPress ? "press" : "release", state);
if ((state & (ControlMask | Mod1Mask)) != (ControlMask | Mod1Mask))
return 0;
#endif
switch (keySym) {
case XK_g:
if (type == KeyPress)
dmxApplyFunctions(dmxInput, DMX_FUNCTION_GRAB);
return 1;
case XK_f:
if (type == KeyPress)
dmxApplyFunctions(dmxInput, DMX_FUNCTION_FINE);
return 1;
case XK_q:
if (type == KeyPress && dmxLocal->sendsCore)
if (dmxApplyFunctions(dmxInput, DMX_FUNCTION_TERMINATE)) {
dmxLog(dmxInfo, "User request for termination\n");
dispatchException |= DE_TERMINATE;
}
return 1;
}
return 0;
}
DMXScreenInfo *
dmxFindFirstScreen(int x, int y)
{
int i;
for (i = 0; i < dmxNumScreens; i++) {
DMXScreenInfo *dmxScreen = &dmxScreens[i];
if (dmxOnScreen(x, y, dmxScreen))
return dmxScreen;
}
return NULL;
}
/**
* Enqueue a motion event.
*/
static void
enqueueMotion(DevicePtr pDev, int x, int y)
{
GETDMXLOCALFROMPDEV;
DeviceIntPtr p = dmxLocal->pDevice;
int valuators[3];
int detail = 0; /* XXX should this be mask of pressed buttons? */
ValuatorMask mask;
valuators[0] = x;
valuators[1] = y;
valuator_mask_set_range(&mask, 0, 2, valuators);
QueuePointerEvents(p, MotionNotify, detail,
POINTER_ABSOLUTE | POINTER_SCREEN, &mask);
return;
}
void
dmxCoreMotion(DevicePtr pDev, int x, int y, int delta, DMXBlockType block)
{
DMXScreenInfo *dmxScreen;
DMXInputInfo *dmxInput;
ScreenPtr pScreen;
int localX;
int localY;
int i;
if (!dmxGlobalInvalid && dmxGlobalX == x && dmxGlobalY == y)
return;
DMXDBG5("dmxCoreMotion(%d,%d,%d) dmxGlobalX=%d dmxGlobalY=%d\n",
x, y, delta, dmxGlobalX, dmxGlobalY);
dmxGlobalInvalid = 0;
dmxGlobalX = x;
dmxGlobalY = y;
if (dmxGlobalX < 0)
dmxGlobalX = 0;
if (dmxGlobalY < 0)
dmxGlobalY = 0;
if (dmxGlobalX >= dmxGlobalWidth)
dmxGlobalX = dmxGlobalWidth + delta - 1;
if (dmxGlobalY >= dmxGlobalHeight)
dmxGlobalY = dmxGlobalHeight + delta - 1;
if ((dmxScreen = dmxFindFirstScreen(dmxGlobalX, dmxGlobalY))) {
localX = dmxGlobalX - dmxScreen->rootXOrigin;
localY = dmxGlobalY - dmxScreen->rootYOrigin;
if ((pScreen = miPointerGetScreen(inputInfo.pointer))
&& pScreen->myNum == dmxScreen->index) {
/* Screen is old screen */
if (block)
dmxSigioBlock();
if (pDev)
enqueueMotion(pDev, localX, localY);
if (block)
dmxSigioUnblock();
}
else {
/* Screen is new */
DMXDBG4(" New screen: old=%d new=%d localX=%d localY=%d\n",
pScreen->myNum, dmxScreen->index, localX, localY);
if (block)
dmxSigioBlock();
mieqProcessInputEvents();
miPointerSetScreen(inputInfo.pointer, dmxScreen->index,
localX, localY);
if (pDev)
enqueueMotion(pDev, localX, localY);
if (block)
dmxSigioUnblock();
}
#if 00
miPointerGetPosition(inputInfo.pointer, &localX, &localY);
if ((pScreen = miPointerGetScreen(inputInfo.pointer))) {
dmxGlobalX = localX + dmxScreens[pScreen->myNum].rootXOrigin;
dmxGlobalY = localY + dmxScreens[pScreen->myNum].rootYOrigin;
ErrorF("Global is now %d, %d %d, %d\n", dmxGlobalX, dmxGlobalY,
localX, localY);
DMXDBG6(" Moved to dmxGlobalX=%d dmxGlobalY=%d"
" on screen index=%d/%d localX=%d localY=%d\n",
dmxGlobalX, dmxGlobalY,
dmxScreen ? dmxScreen->index : -1, pScreen->myNum,
localX, localY);
}
#endif
}
/* Send updates down to all core input
* drivers */
for (i = 0, dmxInput = &dmxInputs[0]; i < dmxNumInputs; i++, dmxInput++) {
int j;
for (j = 0; j < dmxInput->numDevs; j += dmxInput->devs[j]->binding)
if (!dmxInput->detached
&& dmxInput->devs[j]->sendsCore
&& dmxInput->devs[j]->update_position)
dmxInput->devs[j]->update_position(dmxInput->devs[j]->private,
dmxGlobalX, dmxGlobalY);
}
if (!dmxScreen)
ProcessInputEvents();
}
#define DMX_MAX_AXES 32 /* Max axes reported by this routine */
static void
dmxExtMotion(DMXLocalInputInfoPtr dmxLocal,
int *v, int firstAxis, int axesCount,
DMXMotionType type, DMXBlockType block)
{
DeviceIntPtr pDevice = dmxLocal->pDevice;
xEvent xE[2 * DMX_MAX_AXES / 6];
deviceKeyButtonPointer *xev = (deviceKeyButtonPointer *) xE;
deviceValuator *xv = (deviceValuator *) xev + 1;
int thisX = 0;
int thisY = 0;
int count;
ValuatorMask mask;
memset(xE, 0, sizeof(xE));
if (axesCount > DMX_MAX_AXES)
axesCount = DMX_MAX_AXES;
if ((valuator_get_mode(pDevice, 0) == Relative) && axesCount == 2) {
/* The dmx console is a relative mode
* device that sometimes reports
* absolute motion. It only has two
* axes. */
if (type == DMX_RELATIVE) {
thisX = -v[0];
thisY = -v[1];
dmxLocal->lastX += thisX;
dmxLocal->lastY += thisY;
if (dmxLocal->update_position)
dmxLocal->update_position(dmxLocal->private,
dmxLocal->lastX, dmxLocal->lastY);
}
else { /* Convert to relative */
if (dmxLocal->lastX || dmxLocal->lastY) {
thisX = v[0] - dmxLocal->lastX;
thisY = v[1] - dmxLocal->lastY;
}
dmxLocal->lastX = v[0];
dmxLocal->lastY = v[1];
}
v[0] = thisX;
v[1] = thisY;
}
if (axesCount <= 6) {
/* Optimize for the common case when
* only 1 or 2 axes change. */
xev->time = GetTimeInMillis();
xev->type = DeviceMotionNotify;
xev->detail = 0;
xev->deviceid = pDevice->id | MORE_EVENTS;
xv->type = DeviceValuator;
xv->deviceid = pDevice->id;
xv->num_valuators = axesCount;
xv->first_valuator = firstAxis;
switch (xv->num_valuators) {
case 6:
xv->valuator5 = v[5];
case 5:
xv->valuator4 = v[4];
case 4:
xv->valuator3 = v[3];
case 3:
xv->valuator2 = v[2];
case 2:
xv->valuator1 = v[1];
case 1:
xv->valuator0 = v[0];
}
count = 2;
}
else {
int i;
for (i = 0, count = 0; i < axesCount; i += 6) {
xev->time = GetTimeInMillis();
xev->type = DeviceMotionNotify;
xev->detail = 0;
xev->deviceid = pDevice->id | MORE_EVENTS;
xev += 2;
xv->type = DeviceValuator;
xv->deviceid = pDevice->id;
xv->num_valuators = (i + 6 >= axesCount ? axesCount - i : 6);
xv->first_valuator = firstAxis + i;
switch (xv->num_valuators) {
case 6:
xv->valuator5 = v[i + 5];
case 5:
xv->valuator4 = v[i + 4];
case 4:
xv->valuator3 = v[i + 3];
case 3:
xv->valuator2 = v[i + 2];
case 2:
xv->valuator1 = v[i + 1];
case 1:
xv->valuator0 = v[i + 0];
}
xv += 2;
count += 2;
}
}
if (block)
dmxSigioBlock();
valuator_mask_set_range(&mask, firstAxis, axesCount, v);
QueuePointerEvents(pDevice, MotionNotify, 0, POINTER_ABSOLUTE, &mask);
if (block)
dmxSigioUnblock();
}
static int
dmxTranslateAndEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal,
XEvent * e, DMXBlockType block)
{
int type;
int event = -1;
XDeviceKeyEvent *ke = (XDeviceKeyEvent *) e;
XDeviceMotionEvent *me = (XDeviceMotionEvent *) e;
DeviceIntPtr pDevice = dmxLocal->pDevice;
int valuators[MAX_VALUATORS];
ValuatorMask mask;
if (!e)
return -1; /* No extended event passed, cannot handle */
if ((XID) dmxLocal->deviceId != ke->deviceid) {
/* Search for the correct dmxLocal,
* since backend and console events are
* picked up for the first device on
* that X server. */
int i;
DMXInputInfo *dmxInput = &dmxInputs[dmxLocal->inputIdx];
for (i = 0; i < dmxInput->numDevs; i++) {
dmxLocal = dmxInput->devs[i];
if ((XID) dmxLocal->deviceId == ke->deviceid)
break;
}
}
if ((XID) dmxLocal->deviceId != ke->deviceid
|| (type = dmxMapLookup(dmxLocal, e->type)) < 0)
return -1; /* No mapping, so this event is unhandled */
switch (type) {
case XI_DeviceValuator:
event = DeviceValuator;
break;
case XI_DeviceKeyPress:
event = KeyPress;
break;
case XI_DeviceKeyRelease:
event = KeyRelease;
break;
case XI_DeviceButtonPress:
event = ButtonPress;
break;
case XI_DeviceButtonRelease:
event = ButtonRelease;
break;
case XI_DeviceMotionNotify:
event = MotionNotify;
break;
case XI_DeviceFocusIn:
event = DeviceFocusIn;
break;
case XI_DeviceFocusOut:
event = DeviceFocusOut;
break;
case XI_ProximityIn:
event = ProximityIn;
break;
case XI_ProximityOut:
event = ProximityOut;
break;
case XI_DeviceStateNotify:
event = DeviceStateNotify;
break;
case XI_DeviceMappingNotify:
event = DeviceMappingNotify;
break;
case XI_ChangeDeviceNotify:
event = ChangeDeviceNotify;
break;
case XI_DeviceKeystateNotify:
event = DeviceStateNotify;
break;
case XI_DeviceButtonstateNotify:
event = DeviceStateNotify;
break;
}
#define EXTRACT_VALUATORS(ke, valuators) \
valuators[0] = ke->axis_data[0]; \
valuators[1] = ke->axis_data[1]; \
valuators[2] = ke->axis_data[2]; \
valuators[3] = ke->axis_data[3]; \
valuators[4] = ke->axis_data[4]; \
valuators[5] = ke->axis_data[5]; \
switch (type) {
case XI_DeviceKeyPress:
case XI_DeviceKeyRelease:
EXTRACT_VALUATORS(ke, valuators);
valuator_mask_set_range(&mask, ke->first_axis, ke->axes_count,
valuators);
if (block)
dmxSigioBlock();
QueueKeyboardEvents(pDevice, event, ke->keycode, &mask);
if (block)
dmxSigioUnblock();
break;
case XI_DeviceButtonPress:
case XI_DeviceButtonRelease:
EXTRACT_VALUATORS(ke, valuators);
valuator_mask_set_range(&mask, ke->first_axis, ke->axes_count,
valuators);
if (block)
dmxSigioBlock();
QueuePointerEvents(pDevice, event, ke->keycode,
POINTER_ABSOLUTE, &mask);
if (block)
dmxSigioUnblock();
break;
case XI_ProximityIn:
case XI_ProximityOut:
EXTRACT_VALUATORS(ke, valuators);
valuator_mask_set_range(&mask, ke->first_axis, ke->axes_count,
valuators);
if (block)
dmxSigioBlock();
QueueProximityEvents(pDevice, event, &mask);
if (block)
dmxSigioUnblock();
break;
break;
case XI_DeviceMotionNotify:
dmxExtMotion(dmxLocal, me->axis_data, me->first_axis, me->axes_count,
DMX_ABSOLUTE, block);
break;
case XI_DeviceFocusIn:
case XI_DeviceFocusOut:
case XI_DeviceStateNotify:
case XI_DeviceMappingNotify:
case XI_ChangeDeviceNotify:
case XI_DeviceKeystateNotify:
case XI_DeviceButtonstateNotify:
/* These are ignored, since DMX will
* generate its own events of these
* types, as necessary.
* Perhaps ChangeDeviceNotify should
* generate an error, because it is
* unexpected? */
break;
case XI_DeviceValuator:
default:
dmxLog(dmxWarning,
"XInput extension event (remote=%d -> zero-based=%d)"
" not supported yet\n", e->type, type);
return -1;
}
return 0;
}
static int
dmxGetButtonMapping(DMXLocalInputInfoPtr dmxLocal, int button)
{
ButtonClassPtr b = dmxLocal->pDevice->button;
if (button > b->numButtons) { /* This shouldn't happen. */
dmxLog(dmxWarning, "Button %d pressed, but only %d buttons?!?\n",
button, b->numButtons);
return button;
}
return b->map[button];
}
/** Return DMX's notion of the pointer position in the global coordinate
* space. */
void
dmxGetGlobalPosition(int *x, int *y)
{
*x = dmxGlobalX;
*y = dmxGlobalY;
}
/** Invalidate the global position for #dmxCoreMotion. */
void
dmxInvalidateGlobalPosition(void)
{
dmxGlobalInvalid = 1;
}
/** Enqueue a motion event for \a pDev. The \a v vector has length \a
* axesCount, and contains values for each of the axes, starting at \a
* firstAxes.
*
* The \a type of the motion may be \a DMX_RELATIVE, \a DMX_ABSOLUTE, or
* \a DMX_ABSOLUTE_CONFINED (in the latter case, the pointer will not be
* allowed to move outside the global boundaires).
*
* If \a block is set to \a DMX_BLOCK, then the SIGIO handler will be
* blocked around calls to \a enqueueMotion(). */
void
dmxMotion(DevicePtr pDev, int *v, int firstAxes, int axesCount,
DMXMotionType type, DMXBlockType block)
{
GETDMXLOCALFROMPDEV;
if (!dmxLocal->sendsCore) {
dmxExtMotion(dmxLocal, v, firstAxes, axesCount, type, block);
return;
}
if (axesCount == 2) {
switch (type) {
case DMX_RELATIVE:
dmxCoreMotion(pDev, dmxGlobalX - v[0], dmxGlobalY - v[1], 0, block);
break;
case DMX_ABSOLUTE:
dmxCoreMotion(pDev, v[0], v[1], 0, block);
break;
case DMX_ABSOLUTE_CONFINED:
dmxCoreMotion(pDev, v[0], v[1], -1, block);
break;
}
}
}
static KeySym
dmxKeyCodeToKeySym(DMXLocalInputInfoPtr dmxLocal, KeyCode keyCode)
{
KeySym keysym = NoSymbol;
int effectiveGroup;
XkbSrvInfoPtr xkbi;
if (!dmxLocal || !dmxLocal->pDevice || !dmxLocal->pDevice->key)
goto out;
xkbi = dmxLocal->pDevice->key->xkbInfo;
effectiveGroup = XkbGetEffectiveGroup(xkbi, &xkbi->state, keyCode);
if (effectiveGroup == -1)
goto out;
keysym = XkbKeySym(xkbi->desc, keyCode, effectiveGroup);
DMXDBG2("dmxKeyCodeToKeySym: Translated keyCode=%d to keySym=0x%04x\n",
keyCode, keysym);
out:
return keysym;
}
static KeyCode
dmxKeySymToKeyCode(DMXLocalInputInfoPtr dmxLocal, KeySym keySym, int tryFirst)
{
/* FIXME: this is quite ineffective, converting to a core map first and
* then extracting the info from there. It'd be better to run the actual
* xkb map */
XkbSrvInfoPtr xkbi = dmxLocal->pDevice->key->xkbInfo;
KeySymsPtr pKeySyms = XkbGetCoreMap(dmxLocal->pDevice);
int i;
/* Optimize for similar maps */
if (XkbKeycodeInRange(xkbi->desc, tryFirst)
&& pKeySyms->map[(tryFirst - xkbi->desc->min_key_code)
* pKeySyms->mapWidth] == keySym)
return tryFirst;
for (i = pKeySyms->minKeyCode; i <= pKeySyms->maxKeyCode; i++) {
if (pKeySyms->map[(i - pKeySyms->minKeyCode)
* pKeySyms->mapWidth] == keySym) {
DMXDBG3("dmxKeySymToKeyCode: Translated keySym=0x%04x to"
" keyCode=%d (reverses to core keySym=0x%04x)\n",
keySym, i, dmxKeyCodeToKeySym(dmxLocalCoreKeyboard, i));
return i;
}
}
return 0;
}
static int
dmxFixup(DevicePtr pDev, int detail, KeySym keySym)
{
GETDMXLOCALFROMPDEV;
int keyCode;
if (!dmxLocal->pDevice->key) {
dmxLog(dmxWarning, "dmxFixup: not a keyboard device (%s)\n",
dmxLocal->pDevice->name);
return NoSymbol;
}
if (!keySym)
keySym = dmxKeyCodeToKeySym(dmxLocal, detail);
if (keySym == NoSymbol)
return detail;
keyCode = dmxKeySymToKeyCode(dmxLocalCoreKeyboard, keySym, detail);
return keyCode ? keyCode : detail;
}
/** Enqueue an event from the \a pDev device with the
* specified \a type and \a detail. If the event is a KeyPress or
* KeyRelease event, then the \a keySym is also specified.
*
* FIXME: make the code do what the comment says, or remove this comment.
* If \a block is set to \a DMX_BLOCK, then the SIGIO handler will be
* blocked around calls to dmxeqEnqueue(). */
void
dmxEnqueue(DevicePtr pDev, int type, int detail, KeySym keySym,
XEvent * e, DMXBlockType block)
{
GETDMXINPUTFROMPDEV;
xEvent xE;
DeviceIntPtr p = dmxLocal->pDevice;
int valuators[3];
ValuatorMask mask;
DMXDBG2("dmxEnqueue: Enqueuing type=%d detail=0x%0x\n", type, detail);
switch (type) {
case KeyPress:
case KeyRelease:
if (!keySym)
keySym = dmxKeyCodeToKeySym(dmxLocal, detail);
if (dmxCheckFunctionKeys(dmxLocal, type, keySym))
return;
if (dmxLocal->sendsCore && dmxLocal != dmxLocalCoreKeyboard)
xE.u.u.detail = dmxFixup(pDev, detail, keySym);
/*ErrorF("KEY %d sym %d\n", detail, (int) keySym); */
QueueKeyboardEvents(p, type, detail, NULL);
return;
case ButtonPress:
case ButtonRelease:
detail = dmxGetButtonMapping(dmxLocal, detail);
valuator_mask_zero(&mask);
QueuePointerEvents(p, type, detail,
POINTER_ABSOLUTE | POINTER_SCREEN, &mask);
return;
case MotionNotify:
valuators[0] = e->xmotion.x;
valuators[1] = e->xmotion.y;
valuators[2] = e->xmotion.state; /* FIXME: WTF?? */
valuator_mask_set_range(&mask, 0, 3, valuators);
QueuePointerEvents(p, type, detail,
POINTER_ABSOLUTE | POINTER_SCREEN, &mask);
return;
case EnterNotify:
case LeaveNotify:
case KeymapNotify:
case MappingNotify: /* This is sent because we change the
* modifier map on the backend/console
* input device so that we have complete
* control of the input device LEDs. */
return;
default:
if (type == ProximityIn || type == ProximityOut) {
if (dmxLocal->sendsCore)
return; /* Not a core event */
break;
}
if (type >= LASTEvent) {
if (dmxTranslateAndEnqueueExtEvent(dmxLocal, e, block))
dmxLogInput(dmxInput, "Unhandled extension event: %d\n", type);
}
else {
dmxLogInput(dmxInput, "Unhandled event: %d (%s)\n",
type, dmxEventName(type));
}
return;
}
}
/** A pointer to this routine is passed to low-level input drivers so
* that all special keychecking is unified to this file. This function
* returns 0 if no special keys have been pressed. If the user has
* requested termination of the DMX server, -1 is returned. If the user
* has requested a switch to a VT, then the (1-based) number of that VT
* is returned. */
int
dmxCheckSpecialKeys(DevicePtr pDev, KeySym keySym)
{
GETDMXINPUTFROMPDEV;
int vt = 0;
unsigned short state = 0;
if (dmxLocal->sendsCore)
state =
XkbStateFieldFromRec(&dmxLocalCoreKeyboard->pDevice->key->xkbInfo->
state);
else if (dmxLocal->pDevice->key)
state = XkbStateFieldFromRec(&dmxLocal->pDevice->key->xkbInfo->state);
if (!dmxLocal->sendsCore)
return 0; /* Only for core devices */
DMXDBG2("dmxCheckSpecialKeys: keySym=0x%04x state=0x%04x\n", keySym, state);
if ((state & (ControlMask | Mod1Mask)) != (ControlMask | Mod1Mask))
return 0;
switch (keySym) {
case XK_F1:
case XK_F2:
case XK_F3:
case XK_F4:
case XK_F5:
case XK_F6:
case XK_F7:
case XK_F8:
case XK_F9:
case XK_F10:
vt = keySym - XK_F1 + 1;
break;
case XK_F11:
case XK_F12:
vt = keySym - XK_F11 + 11;
break;
case XK_q: /* To avoid confusion */
case XK_BackSpace:
case XK_Delete:
case XK_KP_Delete:
dmxLog(dmxInfo, "User request for termination\n");
dispatchException |= DE_TERMINATE;
return -1; /* Terminate */
}
if (vt) {
dmxLog(dmxInfo, "Request to switch to VT %d\n", vt);
dmxInput->vt_switch_pending = vt;
return vt;
}
return 0; /* Do nothing */
}