add GetPointerEvents/GetKeyboardEvents framework

Add GetPointerEvents (with XFree86 pointer acceleration) and GetKeyboardEvents
to the DIX.  Extend the ValuatorClass structure to account for same.
This commit is contained in:
Daniel Stone 2006-07-19 13:56:23 -04:00 committed by Daniel Stone
parent b308dbf273
commit a274e7296b
4 changed files with 438 additions and 0 deletions

View File

@ -611,6 +611,10 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes,
valc->axisVal = (int *)(valc->axes + numAxes);
for (i=0; i<numAxes; i++)
valc->axisVal[i]=0;
valc->lastx = 0;
valc->lasty = 0;
valc->dxremaind = 0;
valc->dyremaind = 0;
dev->valuator = valc;
return TRUE;
}

View File

@ -157,6 +157,7 @@ xEvent *xeviexE;
#endif
#include <X11/extensions/XIproto.h>
#include "exglobals.h"
#include "exevents.h"
#include "extnsionst.h"
@ -164,6 +165,8 @@ xEvent *xeviexE;
#include "dixgrabs.h"
#include "dispatch.h"
int CoreDevicePrivatesIndex = 0, CoreDevicePrivatesGeneration = -1;
#define EXTENSION_EVENT_BASE 64
#define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */
@ -4660,3 +4663,401 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
(void)WriteToClient(pClient, count * sizeof(xEvent), (char *) events);
}
}
int
GetKeyboardEvents(xEvent **xE, DeviceIntPtr pDev, int type, int key_code) {
return GetKeyboardValuatorEvents(xE, pDev, type, key_code, 0, NULL);
}
int GetKeyboardValuatorEvents(xEvent **xE, DeviceIntPtr pDev, int type,
int key_code, int num_valuators,
int *valuators) {
int numEvents = 0, ms = 0, first_valuator = 0;
deviceKeyButtonPointer *kbp = NULL;
deviceValuator *xv = NULL;
xEvent *ev = NULL;
KeyClassPtr ckeyc;
#ifdef XKB
xkbNewKeyboardNotify nkn;
#endif
if (type != KeyPress && type != KeyRelease)
return 0;
if (!pDev->key || !pDev->focus ||
(pDev->coreEvents && !inputInfo.keyboard->key))
return 0;
if (pDev->coreEvents)
numEvents = 2;
else
numEvents = 1;
if (num_valuators)
numEvents += (num_valuators % 6) + 1;
ev = (xEvent *)xcalloc(sizeof(xEvent), numEvents);
if (!ev)
return 0;
*xE = ev;
ms = GetTimeInMillis();
kbp = (deviceKeyButtonPointer *) ev;
kbp->time = ms;
kbp->deviceid = pDev->id;
if (type == KeyPress)
kbp->type = DeviceKeyPress;
else if (type == KeyRelease)
kbp->type = DeviceKeyRelease;
if (num_valuators) {
kbp->deviceid |= MORE_EVENTS;
while (first_valuator < num_valuators) {
xv = (deviceValuator *) ++ev;
xv->type = DeviceValuator;
xv->first_valuator = first_valuator;
xv->num_valuators = num_valuators;
xv->deviceid = kbp->deviceid;
switch (num_valuators - first_valuator) {
case 6:
xv->valuator5 = valuators[first_valuator+5];
case 5:
xv->valuator4 = valuators[first_valuator+4];
case 4:
xv->valuator3 = valuators[first_valuator+3];
case 3:
xv->valuator2 = valuators[first_valuator+2];
case 2:
xv->valuator1 = valuators[first_valuator+1];
case 1:
xv->valuator0 = valuators[first_valuator];
}
first_valuator += 6;
}
#ifdef DEBUG
ErrorF("GKVE: DV event with %d valuators\n", xv->num_valuators);
#endif
}
if (pDev->coreEvents) {
ev++;
ev->u.keyButtonPointer.time = ms;
ev->u.u.type = type;
ev->u.u.detail = key_code;
if (inputInfo.keyboard->devPrivates[CoreDevicePrivatesIndex].ptr !=
pDev) {
ckeyc = inputInfo.keyboard->key;
memcpy(ckeyc->modifierMap, pDev->key->modifierMap, MAP_LENGTH);
if (ckeyc->modifierKeyMap)
xfree(ckeyc->modifierKeyMap);
ckeyc->modifierKeyMap = xalloc(8 * pDev->key->maxKeysPerModifier);
memcpy(ckeyc->modifierKeyMap, pDev->key->modifierKeyMap,
(8 * pDev->key->maxKeysPerModifier));
ckeyc->maxKeysPerModifier = pDev->key->maxKeysPerModifier;
ckeyc->curKeySyms.map = NULL;
ckeyc->curKeySyms.mapWidth = 0;
ckeyc->curKeySyms.minKeyCode = pDev->key->curKeySyms.minKeyCode;
ckeyc->curKeySyms.maxKeyCode = pDev->key->curKeySyms.maxKeyCode;
SetKeySymsMap(&ckeyc->curKeySyms, &pDev->key->curKeySyms);
#ifdef XKB
if (!noXkbExtension) {
nkn.oldMinKeyCode = ckeyc->xkbInfo->desc->min_key_code;
nkn.oldMaxKeyCode = ckeyc->xkbInfo->desc->max_key_code;
nkn.deviceID = nkn.oldDeviceID = inputInfo.keyboard->id;
nkn.minKeyCode = pDev->key->xkbInfo->desc->min_key_code;
nkn.maxKeyCode = pDev->key->xkbInfo->desc->max_key_code;
nkn.requestMajor = XkbReqCode;
nkn.requestMinor = X_kbSetMap; /* XXX bare-faced lie */
nkn.changed = XkbAllNewKeyboardEventsMask;
/* Free the map we set up at DEVICE_INIT time, since it's
* going to just quietly disappear. Shameful hack. */
if (!inputInfo.keyboard->devPrivates[CoreDevicePrivatesIndex].ptr
&& ckeyc->xkbInfo)
XkbFreeInfo(ckeyc->xkbInfo);
ckeyc->xkbInfo = pDev->key->xkbInfo;
/* FIXME OH MY GOD SO AWFUL let's hope nobody notices */
if (nkn.oldMinKeyCode == nkn.minKeyCode)
nkn.oldMinKeyCode--;
if (nkn.oldMaxKeyCode == nkn.maxKeyCode)
nkn.oldMaxKeyCode++;
XkbSendNewKeyboardNotify(inputInfo.keyboard, &nkn);
}
#endif
SendMappingNotify(MappingKeyboard, ckeyc->curKeySyms.minKeyCode,
(ckeyc->curKeySyms.maxKeyCode -
ckeyc->curKeySyms.minKeyCode),
serverClient);
inputInfo.keyboard->devPrivates[CoreDevicePrivatesIndex].ptr = pDev;
}
}
#ifdef DEBUG
ErrorF("GKE: putting out %d events with detail %d\n", numEvents, key_code);
#endif
return numEvents;
}
/* Originally a part of xf86PostMotionEvent. */
static void
acceleratePointer(DeviceIntPtr pDev, int num_valuators, int *valuators)
{
float mult = 0.0;
int dx = num_valuators >= 1 ? valuators[0] : 0;
int dy = num_valuators >= 2 ? valuators[1] : 0;
if (!num_valuators || !valuators)
return;
/*
* Accelerate
*/
if (pDev->ptrfeed && pDev->ptrfeed->ctrl.num) {
/* modeled from xf86Events.c */
if (pDev->ptrfeed->ctrl.threshold) {
if ((abs(dx) + abs(dy)) >= pDev->ptrfeed->ctrl.threshold) {
pDev->valuator->dxremaind = ((float)dx *
(float)(pDev->ptrfeed->ctrl.num)) /
(float)(pDev->ptrfeed->ctrl.den) +
pDev->valuator->dxremaind;
valuators[0] = (int)pDev->valuator->dxremaind;
pDev->valuator->dxremaind = pDev->valuator->dxremaind -
(float)valuators[0];
pDev->valuator->dyremaind = ((float)dy *
(float)(pDev->ptrfeed->ctrl.num)) /
(float)(pDev->ptrfeed->ctrl.den) +
pDev->valuator->dyremaind;
valuators[1] = (int)pDev->valuator->dyremaind;
pDev->valuator->dyremaind = pDev->valuator->dyremaind -
(float)valuators[1];
}
}
else if (dx || dy) {
mult = pow((float)(dx * dx + dy * dy),
((float)(pDev->ptrfeed->ctrl.num) /
(float)(pDev->ptrfeed->ctrl.den) - 1.0) /
2.0) / 2.0;
if (dx) {
pDev->valuator->dxremaind = mult * (float)dx +
pDev->valuator->dxremaind;
valuators[0] = (int)pDev->valuator->dxremaind;
pDev->valuator->dxremaind = pDev->valuator->dxremaind -
(float)valuators[0];
}
if (dy) {
pDev->valuator->dyremaind = mult * (float)dy +
pDev->valuator->dyremaind;
valuators[1] = (int)pDev->valuator->dyremaind;
pDev->valuator->dyremaind = pDev->valuator->dyremaind -
(float)valuators[1];
}
}
}
}
int
GetPointerEvents(xEvent **xE, DeviceIntPtr pDev, int type, int buttons,
int flags, int num_valuators, int *valuators) {
int numEvents, ms, first_valuator = 0;
deviceKeyButtonPointer *kbp = NULL;
deviceValuator *xv = NULL;
AxisInfoPtr axes = NULL;
xEvent *ev = NULL;
DeviceIntPtr cp = inputInfo.pointer;
if (type != MotionNotify && type != ButtonPress && type != ButtonRelease)
return 0;
if (!pDev->button || (pDev->coreEvents && !(cp->button || !cp->valuator)))
return 0;
#ifdef DEBUG
ErrorF("GPE: called with device %d, type %d\n", pDev->id, type);
ErrorF("GPE: relative %s, accelerate %s\n", flags & POINTER_RELATIVE ? "yes" : "no",
flags & POINTER_ACCELERATE ? "yes" : "no");
#endif
if (pDev->coreEvents)
numEvents = 2;
else
numEvents = 1;
if (type == MotionNotify) {
if (num_valuators > 2)
numEvents += (num_valuators / 6) + 1;
else if (num_valuators < 2)
return 0;
}
ev = (xEvent *)xcalloc(sizeof(xEvent), numEvents);
if (!ev)
return 0;
*xE = ev;
ms = GetTimeInMillis();
kbp = (deviceKeyButtonPointer *) ev;
kbp->time = ms;
kbp->deviceid = pDev->id;
if (flags & POINTER_ABSOLUTE) {
if (num_valuators >= 1) {
kbp->root_x = valuators[0];
}
else {
if (pDev->coreEvents)
kbp->root_x = cp->valuator->lastx;
else
kbp->root_x = pDev->valuator->lastx;
}
if (num_valuators >= 2) {
kbp->root_y = valuators[1];
}
else {
if (pDev->coreEvents)
kbp->root_x = cp->valuator->lasty;
else
kbp->root_y = pDev->valuator->lasty;
}
}
else {
if (flags & POINTER_ACCELERATE)
acceleratePointer(pDev, num_valuators, valuators);
if (pDev->coreEvents) {
if (num_valuators >= 1)
kbp->root_x = cp->valuator->lastx + valuators[0];
else
kbp->root_x = cp->valuator->lastx;
if (num_valuators >= 2)
kbp->root_y = cp->valuator->lasty + valuators[1];
else
kbp->root_y = cp->valuator->lasty;
}
else {
if (num_valuators >= 1)
kbp->root_x = pDev->valuator->lastx + valuators[0];
else
kbp->root_x = pDev->valuator->lastx;
if (num_valuators >= 2)
kbp->root_y = pDev->valuator->lasty + valuators[1];
else
kbp->root_y = pDev->valuator->lasty;
}
}
/* FIXME: need mipointer-like semantics to move on to different screens. */
axes = pDev->valuator->axes;
if (kbp->root_x < axes->min_value)
kbp->root_x = axes->min_value;
if (kbp->root_x > axes->max_value)
kbp->root_x = axes->max_value;
axes++;
if (kbp->root_y < axes->min_value)
kbp->root_y = axes->min_value;
if (kbp->root_y > axes->max_value)
kbp->root_y = axes->max_value;
if (pDev->coreEvents) {
#ifdef DEBUG
ErrorF("warping core lastx from %d to %d\n", cp->valuator->lastx, kbp->root_x);
ErrorF("x value given was %d\n", valuators[0]);
#endif
cp->valuator->lastx = kbp->root_x;
#ifdef DEBUG
ErrorF("warping core lasty from %d to %d\n", cp->valuator->lasty, kbp->root_y);
ErrorF("y value given was %d\n", valuators[1]);
#endif
cp->valuator->lasty = kbp->root_y;
}
pDev->valuator->lastx = kbp->root_x;
pDev->valuator->lasty = kbp->root_y;
if (type == MotionNotify) {
kbp->type = DeviceMotionNotify;
#ifdef DEBUG
ErrorF("GPE: motion at %d, %d\n", kbp->root_x, kbp->root_y);
#endif
}
else {
if (type == ButtonPress)
kbp->type = DeviceButtonPress;
else if (type == ButtonRelease)
kbp->type = DeviceButtonRelease;
#ifdef DEBUG
ErrorF("GPE: detail is %d\n", buttons);
#endif
kbp->detail = buttons;
}
/* XXX: the spec says that Device{Key,Button}{Press,Release} events
* for relative devices shouldn't contain valuators since only the
* state field will have meaning, but I don't see why. */
if (num_valuators > 2 && (type == MotionNotify ||
flags & POINTER_ABSOLUTE)) {
kbp->deviceid |= MORE_EVENTS;
while (first_valuator < num_valuators) {
xv = (deviceValuator *) ++ev;
xv->type = DeviceValuator;
xv->first_valuator = first_valuator;
xv->num_valuators = num_valuators;
xv->deviceid = kbp->deviceid;
switch (num_valuators - first_valuator) {
case 6:
xv->valuator5 = valuators[first_valuator+5];
case 5:
xv->valuator4 = valuators[first_valuator+4];
case 4:
xv->valuator3 = valuators[first_valuator+3];
case 3:
xv->valuator2 = valuators[first_valuator+2];
case 2:
if (first_valuator == 0)
xv->valuator1 = kbp->root_y;
else
xv->valuator1 = valuators[first_valuator+1];
case 1:
if (first_valuator == 0)
xv->valuator0 = kbp->root_x;
else
xv->valuator0 = valuators[first_valuator];
}
first_valuator += 6;
}
#ifdef DEBUG
ErrorF("GPE: DV event with %d valuators\n", xv->num_valuators);
#endif
}
if (pDev->coreEvents) {
ev++;
ev->u.u.type = type;
ev->u.keyButtonPointer.time = ms;
ev->u.keyButtonPointer.rootX = kbp->root_x;
ev->u.keyButtonPointer.rootY = kbp->root_y;
cp->valuator->lastx = kbp->root_x;
cp->valuator->lasty = kbp->root_y;
#ifdef DEBUG
ErrorF("GPE: core co-ords at %d, %d\n", kbp->root_x, kbp->root_y);
#endif
if (type == ButtonPress || type == ButtonRelease) {
#ifdef DEBUG
ErrorF("GPE: core detail is %d\n", buttons);
#endif
/* Core buttons remapping shouldn't be transitive. */
ev->u.u.detail = pDev->button->map[buttons];
}
else {
ev->u.u.detail = 0;
}
if (inputInfo.pointer->devPrivates[CoreDevicePrivatesIndex].ptr !=
pDev)
inputInfo.pointer->devPrivates[CoreDevicePrivatesIndex].ptr = pDev;
}
return numEvents;
}

View File

@ -372,6 +372,32 @@ extern void InitInput(
int /*argc*/,
char ** /*argv*/);
extern int GetPointerEvents(
xEvent **xE,
DeviceIntPtr pDev,
int type,
int buttons,
int flags,
int num_axes,
int *valuators);
extern int GetKeyboardEvents(
xEvent **xE,
DeviceIntPtr pDev,
int type,
int key_code);
extern int GetKeyboardValuatorEvents(
xEvent **xE,
DeviceIntPtr pDev,
int type,
int key_code,
int num_axes,
int *valuators);
extern DeviceIntPtr LookupDeviceIntRec(
CARD8 deviceid);
/* Implemented by the DDX. */
extern int NewInputDeviceRequest(
InputOption *options);

View File

@ -64,6 +64,10 @@ SOFTWARE.
#define EMASKSIZE MAX_DEVICES
#define POINTER_RELATIVE (1 << 1)
#define POINTER_ABSOLUTE (1 << 2)
#define POINTER_ACCELERATE (1 << 3)
/* Kludge: OtherClients and InputClients must be compatible, see code */
typedef struct _OtherClients {
@ -150,6 +154,9 @@ typedef struct _ValuatorClassRec {
unsigned short numAxes;
int *axisVal;
CARD8 mode;
int lastx, lasty; /* last event recorded, not posted to
* client; see dix/devices.c */
int dxremaind, dyremaind; /* for acceleration */
} ValuatorClassRec, *ValuatorClassPtr;
typedef struct _ButtonClassRec {