summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stone <daniel.stone@nokia.com>2006-07-19 13:56:23 -0400
committerDaniel Stone <daniels@endtroducing.fooishbar.org>2006-07-21 15:19:51 -0400
commita274e7296b1bdd6f6c921f28b087610cec9548e0 (patch)
tree4966c52feb1b4a35cf2ba66b74b8e76804f1b2a9
parentb308dbf273f8c26361b0fee7aca64aec3245f60b (diff)
add GetPointerEvents/GetKeyboardEvents framework
Add GetPointerEvents (with XFree86 pointer acceleration) and GetKeyboardEvents to the DIX. Extend the ValuatorClass structure to account for same.
-rw-r--r--dix/devices.c4
-rw-r--r--dix/events.c401
-rw-r--r--include/input.h26
-rw-r--r--include/inputstr.h7
4 files changed, 438 insertions, 0 deletions
diff --git a/dix/devices.c b/dix/devices.c
index 40afac96f..37720f3b7 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -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;
}
diff --git a/dix/events.c b/dix/events.c
index 479b4d80c..1b0aee5fb 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -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;
+}
diff --git a/include/input.h b/include/input.h
index 3e00be671..d550bbe97 100644
--- a/include/input.h
+++ b/include/input.h
@@ -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);
diff --git a/include/inputstr.h b/include/inputstr.h
index 5c294975a..8b877bcbd 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -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 {