diff options
author | Daniel Stone <daniel@fooishbar.org> | 2006-10-14 22:14:07 +0300 |
---|---|---|
committer | Daniel Stone <daniels@endtroducing.fooishbar.org> | 2006-10-14 22:14:07 +0300 |
commit | 4d8030076ed1a7680bdfcb7b89af1045bdc40304 (patch) | |
tree | a96f5ce2b00f11956788eed1b0d96ee276c3d359 /dix | |
parent | 6afc7c284690b1e2bb7544b5bc4f31a3f6a05519 (diff) |
dix: move GetKeyboardEvents/GetPointerEvents to a new file, export symbols
Move GKE and GPE to a separate file, to help stem the events.c explosion.
Mark GKE/GKVE/GPE as _X_EXPORT.
Diffstat (limited to 'dix')
-rw-r--r-- | dix/Makefile.am | 1 | ||||
-rw-r--r-- | dix/events.c | 473 | ||||
-rw-r--r-- | dix/getevents.c | 530 |
3 files changed, 531 insertions, 473 deletions
diff --git a/dix/Makefile.am b/dix/Makefile.am index d26d9ea7a..724d1d1f6 100644 --- a/dix/Makefile.am +++ b/dix/Makefile.am @@ -17,6 +17,7 @@ libdix_la_SOURCES = \ extension.c \ ffs.c \ gc.c \ + getevents.c \ globals.c \ glyphcurs.c \ grabs.c \ diff --git a/dix/events.c b/dix/events.c index ebc43b090..e1a3e75d4 100644 --- a/dix/events.c +++ b/dix/events.c @@ -131,13 +131,10 @@ of the copyright holder. #endif #include "globals.h" -#include "mipointer.h" - #ifdef XKB #include <X11/extensions/XKBproto.h> #include <X11/extensions/XKBsrv.h> extern Bool XkbFilterEvents(ClientPtr, int, xEvent *); -extern Bool XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies); #endif #ifdef XACE @@ -4592,473 +4589,3 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events) (void)WriteToClient(pClient, count * sizeof(xEvent), (char *) events); } } - -/* Maximum number of valuators, divided by six, rounded up. */ -#define MAX_VALUATOR_EVENTS 6 - -/** - * Returns the maximum number of events GetKeyboardEvents, - * GetKeyboardValuatorEvents, and GetPointerEvents will ever return. - * - * Should be used in DIX as: - * xEvent *events = xcalloc(sizeof(xEvent), GetMaximumEventsNum()); - */ -int -GetMaximumEventsNum() { - /* Two base events -- core and device, plus valuator events. Multiply - * by two if we're doing key repeats. */ - int ret = 2 + MAX_VALUATOR_EVENTS; - -#ifdef XKB - if (noXkbExtension) -#endif - ret *= 2; - - return ret; -} - -/** - * Convenience wrapper around GetKeyboardValuatorEvents, that takes no - * valuators. - */ -int -GetKeyboardEvents(xEvent *events, DeviceIntPtr pDev, int type, int key_code) { - return GetKeyboardValuatorEvents(events, pDev, type, key_code, 0, 0, NULL); -} - -/** - * Returns a set of keyboard events for KeyPress/KeyRelease, optionally - * also with valuator events. Handles Xi and XKB. - * - * events is not NULL-terminated; the return value is the number of events. - * The DDX is responsible for allocating the event structure in the first - * place via GetMaximumEventsNum(), and for freeing it. - * - * If pDev is set to send core events, then the keymap on the core - * keyboard will be pivoted to that of the new keyboard and the appropriate - * MapNotify events (both core and XKB) will be sent. - * - * Note that this function recurses! If called for non-XKB, a repeating - * key press will trigger a matching KeyRelease, as well as the - * KeyPresses. - */ -int GetKeyboardValuatorEvents(xEvent *events, DeviceIntPtr pDev, int type, - int key_code, int first_valuator, - int num_valuators, int *valuators) { - int numEvents = 0, ms = 0, i = 0; - int final_valuator = first_valuator + num_valuators; - KeySym sym = pDev->key->curKeySyms.map[key_code * - pDev->key->curKeySyms.mapWidth]; - deviceKeyButtonPointer *kbp = NULL; - deviceValuator *xv = NULL; - KeyClassPtr ckeyc; - - if (!events) - return 0; - - if (type != KeyPress && type != KeyRelease) - return 0; - - if (!pDev->key || !pDev->focus || !pDev->kbdfeed || - (pDev->coreEvents && !inputInfo.keyboard->key)) - return 0; - - if (pDev->coreEvents) - numEvents = 2; - else - numEvents = 1; - - if (num_valuators) { - if ((num_valuators / 6) + 1 > MAX_VALUATOR_EVENTS) - num_valuators = MAX_VALUATOR_EVENTS; - numEvents += (num_valuators / 6) + 1; - } - -#ifdef XKB - if (noXkbExtension) -#endif - { - switch (sym) { - case XK_Num_Lock: - case XK_Caps_Lock: - case XK_Scroll_Lock: - case XK_Shift_Lock: - if (type == KeyRelease) - return 0; - else if (type == KeyPress && - (pDev->key->down[key_code >> 3] & (key_code & 7)) & 1) - type = KeyRelease; - } - } - - /* Handle core repeating, via press/release/press/release. - * FIXME: In theory, if you're repeating with two keyboards, - * you could get unbalanced events here. */ - if (type == KeyPress && - (((pDev->key->down[key_code >> 3] & (key_code & 7))) & 1)) { - if (!pDev->kbdfeed->ctrl.autoRepeat || - pDev->key->modifierMap[key_code] || - !(pDev->kbdfeed->ctrl.autoRepeats[key_code >> 3] - & (1 << (key_code & 7)))) - return 0; - -#ifdef XKB - if (noXkbExtension) -#endif - { - numEvents += GetKeyboardValuatorEvents(events, pDev, - KeyRelease, key_code, - first_valuator, num_valuators, - valuators); - events += numEvents; - } - } - - - ms = GetTimeInMillis(); - - kbp = (deviceKeyButtonPointer *) events; - 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; - for (i = first_valuator; i < final_valuator; i += 6) { - xv = (deviceValuator *) ++events; - xv->type = DeviceValuator; - xv->first_valuator = i; - xv->num_valuators = num_valuators; - xv->deviceid = kbp->deviceid; - switch (num_valuators - first_valuator) { - case 6: - xv->valuator5 = valuators[i+5]; - case 5: - xv->valuator4 = valuators[i+4]; - case 4: - xv->valuator3 = valuators[i+3]; - case 3: - xv->valuator2 = valuators[i+2]; - case 2: - xv->valuator1 = valuators[i+1]; - case 1: - xv->valuator0 = valuators[i]; - } - } - } - - if (pDev->coreEvents) { - events++; - events->u.keyButtonPointer.time = ms; - events->u.u.type = type; - events->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.minKeyCode = pDev->key->curKeySyms.minKeyCode; - ckeyc->curKeySyms.maxKeyCode = pDev->key->curKeySyms.maxKeyCode; - SetKeySymsMap(&ckeyc->curKeySyms, &pDev->key->curKeySyms); -#ifdef XKB - if (!noXkbExtension && pDev->key->xkbInfo && - pDev->key->xkbInfo->desc) { - if (!XkbCopyKeymap(pDev->key->xkbInfo->desc, - ckeyc->xkbInfo->desc, True)) - FatalError("Couldn't pivot keymap from device to core!\n"); - } -#endif - SendMappingNotify(MappingKeyboard, ckeyc->curKeySyms.minKeyCode, - (ckeyc->curKeySyms.maxKeyCode - - ckeyc->curKeySyms.minKeyCode), - serverClient); - inputInfo.keyboard->devPrivates[CoreDevicePrivatesIndex].ptr = pDev; - } - } - - return numEvents; -} - -/* Originally a part of xf86PostMotionEvent. */ -static void -acceleratePointer(DeviceIntPtr pDev, int first_valuator, int num_valuators, - int *valuators) -{ - float mult = 0.0; - int dx = 0, dy = 0; - int *px = NULL, *py = NULL; - - if (!num_valuators || !valuators) - return; - - if (first_valuator == 0) { - dx = valuators[0]; - px = &valuators[0]; - } - if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) { - dy = valuators[1 - first_valuator]; - py = &valuators[1 - first_valuator]; - } - - if (!dx && !dy) - 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; - if (px) { - *px = (int)pDev->valuator->dxremaind; - pDev->valuator->dxremaind = pDev->valuator->dxremaind - - (float)(*px); - } - - pDev->valuator->dyremaind = ((float)dy * - (float)(pDev->ptrfeed->ctrl.num)) / - (float)(pDev->ptrfeed->ctrl.den) + - pDev->valuator->dyremaind; - if (py) { - *py = (int)pDev->valuator->dyremaind; - pDev->valuator->dyremaind = pDev->valuator->dyremaind - - (float)(*py); - } - } - } - else { - 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; - *px = (int)pDev->valuator->dxremaind; - pDev->valuator->dxremaind = pDev->valuator->dxremaind - - (float)(*px); - } - if (dy) { - pDev->valuator->dyremaind = mult * (float)dy + - pDev->valuator->dyremaind; - *py = (int)pDev->valuator->dyremaind; - pDev->valuator->dyremaind = pDev->valuator->dyremaind - - (float)(*py); - } - } - } -} - -/** - * Generate a series of xEvents (returned in xE) representing pointer - * motion, or button presses. Xi and XKB-aware. - * - * events is not NULL-terminated; the return value is the number of events. - * The DDX is responsible for allocating the event structure in the first - * place via GetMaximumEventsNum(), and for freeing it. - */ -int -GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons, - int flags, int first_valuator, int num_valuators, - int *valuators) { - int num_events = 0, ms = 0, final_valuator = 0, i = 0; - deviceKeyButtonPointer *kbp = NULL; - deviceValuator *xv = NULL; - AxisInfoPtr axes = NULL; - Bool sendValuators = (type == MotionNotify || flags & POINTER_ABSOLUTE); - DeviceIntPtr cp = inputInfo.pointer; - int x = 0, y = 0; - - if (type != MotionNotify && type != ButtonPress && type != ButtonRelease) - return 0; - - if (!pDev->button || (pDev->coreEvents && (!cp->button || !cp->valuator))) - return 0; - - /* You fail. */ - if (first_valuator < 0) - return 0; - - if (pDev->coreEvents) - num_events = 2; - else - num_events = 1; - - /* Do we need to send a DeviceValuator event? */ - if ((num_valuators + first_valuator) >= 2 && sendValuators) { - if (((num_valuators / 6) + 1) > MAX_VALUATOR_EVENTS) - num_valuators = MAX_VALUATOR_EVENTS; - num_events += (num_valuators / 6) + 1; - } - else if (type == MotionNotify && num_valuators <= 0) { - return 0; - } - - final_valuator = num_valuators + first_valuator; - - ms = GetTimeInMillis(); - - kbp = (deviceKeyButtonPointer *) events; - kbp->time = ms; - kbp->deviceid = pDev->id; - - if (flags & POINTER_ABSOLUTE) { - if (num_valuators >= 1 && first_valuator == 0) { - x = valuators[0]; - } - else { - if (pDev->coreEvents) - x = cp->valuator->lastx; - else - x = pDev->valuator->lastx; - } - - if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) { - y = valuators[1 - first_valuator]; - } - else { - if (pDev->coreEvents) - x = cp->valuator->lasty; - else - y = pDev->valuator->lasty; - } - } - else { - if (flags & POINTER_ACCELERATE) - acceleratePointer(pDev, first_valuator, num_valuators, - valuators); - - if (pDev->coreEvents) { - if (first_valuator == 0 && num_valuators >= 1) - x = cp->valuator->lastx + valuators[0]; - else - x = cp->valuator->lastx; - - if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) - y = cp->valuator->lasty + valuators[1 - first_valuator]; - else - y = cp->valuator->lasty; - } - else { - if (first_valuator == 0 && num_valuators >= 1) - x = pDev->valuator->lastx + valuators[0]; - else - x = pDev->valuator->lastx; - - if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) - y = pDev->valuator->lasty + valuators[1 - first_valuator]; - else - y = pDev->valuator->lasty; - } - } - - - axes = pDev->valuator->axes; - if (x < axes->min_value) - x = axes->min_value; - if (axes->max_value > 0 && x > axes->max_value) - x = axes->max_value; - - axes++; - if (y < axes->min_value) - y = axes->min_value; - if (axes->max_value > 0 && y > axes->max_value) - y = axes->max_value; - - /* This takes care of crossing screens for us, as well as clipping - * to the current screen. Right now, we only have one history buffer, - * so we don't set this for both the device and core.*/ - miPointerSetPosition(pDev, &x, &y, ms); - - if (pDev->coreEvents) { - cp->valuator->lastx = x; - cp->valuator->lasty = y; - } - pDev->valuator->lastx = x; - pDev->valuator->lasty = y; - - if (type == MotionNotify) { - kbp->type = DeviceMotionNotify; - } - else { - if (type == ButtonPress) - kbp->type = DeviceButtonPress; - else if (type == ButtonRelease) - kbp->type = DeviceButtonRelease; - kbp->detail = pDev->button->map[buttons]; - } - - kbp->root_x = x; - kbp->root_y = y; - - if (final_valuator > 2 && sendValuators) { - kbp->deviceid |= MORE_EVENTS; - for (i = first_valuator; i < final_valuator; i += 6) { - xv = (deviceValuator *) ++events; - xv->type = DeviceValuator; - xv->first_valuator = i; - xv->num_valuators = num_valuators; - xv->deviceid = kbp->deviceid; - switch (final_valuator - i) { - case 6: - xv->valuator5 = valuators[i+5]; - case 5: - xv->valuator4 = valuators[i+4]; - case 4: - xv->valuator3 = valuators[i+3]; - case 3: - xv->valuator2 = valuators[i+2]; - case 2: - /* x and y may have been accelerated. */ - if (i == 0) - xv->valuator1 = kbp->root_y; - else - xv->valuator1 = valuators[i+1]; - case 1: - /* x and y may have been accelerated. */ - if (i == 0) - xv->valuator0 = kbp->root_x; - else - xv->valuator0 = valuators[i]; - } - } - } - - if (pDev->coreEvents) { - events++; - events->u.u.type = type; - events->u.keyButtonPointer.time = ms; - events->u.keyButtonPointer.rootX = x; - events->u.keyButtonPointer.rootY = y; - - if (type == ButtonPress || type == ButtonRelease) { - /* We hijack SetPointerMapping to work on all core-sending - * devices, so we use the device-specific map here instead of - * the core one. */ - events->u.u.detail = pDev->button->map[buttons]; - } - else { - events->u.u.detail = 0; - } - - if (inputInfo.pointer->devPrivates[CoreDevicePrivatesIndex].ptr != - pDev) - inputInfo.pointer->devPrivates[CoreDevicePrivatesIndex].ptr = pDev; - } - - return num_events; -} diff --git a/dix/getevents.c b/dix/getevents.c new file mode 100644 index 000000000..4f9608053 --- /dev/null +++ b/dix/getevents.c @@ -0,0 +1,530 @@ +/* + * Copyright © 2006 Nokia Corporation + * + * 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 this copyright notice and this permission notice appear in + * supporting electronic documentation. + * + * 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 HOLDERS OR AUTHORS 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. + * + * Author: Daniel Stone <daniel@fooishbar.org> + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/keysym.h> +#include "misc.h" +#include "resource.h" +#define NEED_EVENTS +#define NEED_REPLIES +#include <X11/Xproto.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "cursorstr.h" + +#include "dixstruct.h" +#include "globals.h" + +#include "mipointer.h" + +#ifdef XKB +#include <X11/extensions/XKBproto.h> +#include <X11/extensions/XKBsrv.h> +extern Bool XkbFilterEvents(ClientPtr, int, xEvent *); +extern Bool XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies); +#endif + +#ifdef XACE +#include "xace.h" +#endif + +#include <X11/extensions/XIproto.h> +#include "exglobals.h" +#include "exevents.h" +#include "exglobals.h" +#include "extnsionst.h" + +/* Maximum number of valuators, divided by six, rounded up. */ +#define MAX_VALUATOR_EVENTS 6 + +/** + * Returns the maximum number of events GetKeyboardEvents, + * GetKeyboardValuatorEvents, and GetPointerEvents will ever return. + * + * Should be used in DIX as: + * xEvent *events = xcalloc(sizeof(xEvent), GetMaximumEventsNum()); + */ +_X_EXPORT int +GetMaximumEventsNum() { + /* Two base events -- core and device, plus valuator events. Multiply + * by two if we're doing key repeats. */ + int ret = 2 + MAX_VALUATOR_EVENTS; + +#ifdef XKB + if (noXkbExtension) +#endif + ret *= 2; + + return ret; +} + +/** + * Convenience wrapper around GetKeyboardValuatorEvents, that takes no + * valuators. + */ +_X_EXPORT int +GetKeyboardEvents(xEvent *events, DeviceIntPtr pDev, int type, int key_code) { + return GetKeyboardValuatorEvents(events, pDev, type, key_code, 0, 0, NULL); +} + +/** + * Returns a set of keyboard events for KeyPress/KeyRelease, optionally + * also with valuator events. Handles Xi and XKB. + * + * events is not NULL-terminated; the return value is the number of events. + * The DDX is responsible for allocating the event structure in the first + * place via GetMaximumEventsNum(), and for freeing it. + * + * If pDev is set to send core events, then the keymap on the core + * keyboard will be pivoted to that of the new keyboard and the appropriate + * MapNotify events (both core and XKB) will be sent. + * + * Note that this function recurses! If called for non-XKB, a repeating + * key press will trigger a matching KeyRelease, as well as the + * KeyPresses. + */ +_X_EXPORT int +GetKeyboardValuatorEvents(xEvent *events, DeviceIntPtr pDev, int type, + int key_code, int first_valuator, + int num_valuators, int *valuators) { + int numEvents = 0, ms = 0, i = 0; + int final_valuator = first_valuator + num_valuators; + KeySym sym = pDev->key->curKeySyms.map[key_code * + pDev->key->curKeySyms.mapWidth]; + deviceKeyButtonPointer *kbp = NULL; + deviceValuator *xv = NULL; + KeyClassPtr ckeyc; + + if (!events) + return 0; + + if (type != KeyPress && type != KeyRelease) + return 0; + + if (!pDev->key || !pDev->focus || !pDev->kbdfeed || + (pDev->coreEvents && !inputInfo.keyboard->key)) + return 0; + + if (pDev->coreEvents) + numEvents = 2; + else + numEvents = 1; + + if (num_valuators) { + if ((num_valuators / 6) + 1 > MAX_VALUATOR_EVENTS) + num_valuators = MAX_VALUATOR_EVENTS; + numEvents += (num_valuators / 6) + 1; + } + +#ifdef XKB + if (noXkbExtension) +#endif + { + switch (sym) { + case XK_Num_Lock: + case XK_Caps_Lock: + case XK_Scroll_Lock: + case XK_Shift_Lock: + if (type == KeyRelease) + return 0; + else if (type == KeyPress && + (pDev->key->down[key_code >> 3] & (key_code & 7)) & 1) + type = KeyRelease; + } + } + + /* Handle core repeating, via press/release/press/release. + * FIXME: In theory, if you're repeating with two keyboards, + * you could get unbalanced events here. */ + if (type == KeyPress && + (((pDev->key->down[key_code >> 3] & (key_code & 7))) & 1)) { + if (!pDev->kbdfeed->ctrl.autoRepeat || + pDev->key->modifierMap[key_code] || + !(pDev->kbdfeed->ctrl.autoRepeats[key_code >> 3] + & (1 << (key_code & 7)))) + return 0; + +#ifdef XKB + if (noXkbExtension) +#endif + { + numEvents += GetKeyboardValuatorEvents(events, pDev, + KeyRelease, key_code, + first_valuator, num_valuators, + valuators); + events += numEvents; + } + } + + + ms = GetTimeInMillis(); + + kbp = (deviceKeyButtonPointer *) events; + 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; + for (i = first_valuator; i < final_valuator; i += 6) { + xv = (deviceValuator *) ++events; + xv->type = DeviceValuator; + xv->first_valuator = i; + xv->num_valuators = num_valuators; + xv->deviceid = kbp->deviceid; + switch (num_valuators - first_valuator) { + case 6: + xv->valuator5 = valuators[i+5]; + case 5: + xv->valuator4 = valuators[i+4]; + case 4: + xv->valuator3 = valuators[i+3]; + case 3: + xv->valuator2 = valuators[i+2]; + case 2: + xv->valuator1 = valuators[i+1]; + case 1: + xv->valuator0 = valuators[i]; + } + } + } + + if (pDev->coreEvents) { + events++; + events->u.keyButtonPointer.time = ms; + events->u.u.type = type; + events->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.minKeyCode = pDev->key->curKeySyms.minKeyCode; + ckeyc->curKeySyms.maxKeyCode = pDev->key->curKeySyms.maxKeyCode; + SetKeySymsMap(&ckeyc->curKeySyms, &pDev->key->curKeySyms); +#ifdef XKB + if (!noXkbExtension && pDev->key->xkbInfo && + pDev->key->xkbInfo->desc) { + if (!XkbCopyKeymap(pDev->key->xkbInfo->desc, + ckeyc->xkbInfo->desc, True)) + FatalError("Couldn't pivot keymap from device to core!\n"); + } +#endif + SendMappingNotify(MappingKeyboard, ckeyc->curKeySyms.minKeyCode, + (ckeyc->curKeySyms.maxKeyCode - + ckeyc->curKeySyms.minKeyCode), + serverClient); + inputInfo.keyboard->devPrivates[CoreDevicePrivatesIndex].ptr = pDev; + } + } + + return numEvents; +} + +/* Originally a part of xf86PostMotionEvent. */ +static void +acceleratePointer(DeviceIntPtr pDev, int first_valuator, int num_valuators, + int *valuators) +{ + float mult = 0.0; + int dx = 0, dy = 0; + int *px = NULL, *py = NULL; + + if (!num_valuators || !valuators) + return; + + if (first_valuator == 0) { + dx = valuators[0]; + px = &valuators[0]; + } + if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) { + dy = valuators[1 - first_valuator]; + py = &valuators[1 - first_valuator]; + } + + if (!dx && !dy) + 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; + if (px) { + *px = (int)pDev->valuator->dxremaind; + pDev->valuator->dxremaind = pDev->valuator->dxremaind - + (float)(*px); + } + + pDev->valuator->dyremaind = ((float)dy * + (float)(pDev->ptrfeed->ctrl.num)) / + (float)(pDev->ptrfeed->ctrl.den) + + pDev->valuator->dyremaind; + if (py) { + *py = (int)pDev->valuator->dyremaind; + pDev->valuator->dyremaind = pDev->valuator->dyremaind - + (float)(*py); + } + } + } + else { + 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; + *px = (int)pDev->valuator->dxremaind; + pDev->valuator->dxremaind = pDev->valuator->dxremaind - + (float)(*px); + } + if (dy) { + pDev->valuator->dyremaind = mult * (float)dy + + pDev->valuator->dyremaind; + *py = (int)pDev->valuator->dyremaind; + pDev->valuator->dyremaind = pDev->valuator->dyremaind - + (float)(*py); + } + } + } +} + +/** + * Generate a series of xEvents (returned in xE) representing pointer + * motion, or button presses. Xi and XKB-aware. + * + * events is not NULL-terminated; the return value is the number of events. + * The DDX is responsible for allocating the event structure in the first + * place via GetMaximumEventsNum(), and for freeing it. + */ +_X_EXPORT int +GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons, + int flags, int first_valuator, int num_valuators, + int *valuators) { + int num_events = 0, ms = 0, final_valuator = 0, i = 0; + deviceKeyButtonPointer *kbp = NULL; + deviceValuator *xv = NULL; + AxisInfoPtr axes = NULL; + Bool sendValuators = (type == MotionNotify || flags & POINTER_ABSOLUTE); + DeviceIntPtr cp = inputInfo.pointer; + int x = 0, y = 0; + + if (type != MotionNotify && type != ButtonPress && type != ButtonRelease) + return 0; + + if (!pDev->button || (pDev->coreEvents && (!cp->button || !cp->valuator))) + return 0; + + /* You fail. */ + if (first_valuator < 0) + return 0; + + if (pDev->coreEvents) + num_events = 2; + else + num_events = 1; + + /* Do we need to send a DeviceValuator event? */ + if ((num_valuators + first_valuator) >= 2 && sendValuators) { + if (((num_valuators / 6) + 1) > MAX_VALUATOR_EVENTS) + num_valuators = MAX_VALUATOR_EVENTS; + num_events += (num_valuators / 6) + 1; + } + else if (type == MotionNotify && num_valuators <= 0) { + return 0; + } + + final_valuator = num_valuators + first_valuator; + + ms = GetTimeInMillis(); + + kbp = (deviceKeyButtonPointer *) events; + kbp->time = ms; + kbp->deviceid = pDev->id; + + if (flags & POINTER_ABSOLUTE) { + if (num_valuators >= 1 && first_valuator == 0) { + x = valuators[0]; + } + else { + if (pDev->coreEvents) + x = cp->valuator->lastx; + else + x = pDev->valuator->lastx; + } + + if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) { + y = valuators[1 - first_valuator]; + } + else { + if (pDev->coreEvents) + x = cp->valuator->lasty; + else + y = pDev->valuator->lasty; + } + } + else { + if (flags & POINTER_ACCELERATE) + acceleratePointer(pDev, first_valuator, num_valuators, + valuators); + + if (pDev->coreEvents) { + if (first_valuator == 0 && num_valuators >= 1) + x = cp->valuator->lastx + valuators[0]; + else + x = cp->valuator->lastx; + + if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) + y = cp->valuator->lasty + valuators[1 - first_valuator]; + else + y = cp->valuator->lasty; + } + else { + if (first_valuator == 0 && num_valuators >= 1) + x = pDev->valuator->lastx + valuators[0]; + else + x = pDev->valuator->lastx; + + if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) + y = pDev->valuator->lasty + valuators[1 - first_valuator]; + else + y = pDev->valuator->lasty; + } + } + + + axes = pDev->valuator->axes; + if (x < axes->min_value) + x = axes->min_value; + if (axes->max_value > 0 && x > axes->max_value) + x = axes->max_value; + + axes++; + if (y < axes->min_value) + y = axes->min_value; + if (axes->max_value > 0 && y > axes->max_value) + y = axes->max_value; + + /* This takes care of crossing screens for us, as well as clipping + * to the current screen. Right now, we only have one history buffer, + * so we don't set this for both the device and core.*/ + miPointerSetPosition(pDev, &x, &y, ms); + + if (pDev->coreEvents) { + cp->valuator->lastx = x; + cp->valuator->lasty = y; + } + pDev->valuator->lastx = x; + pDev->valuator->lasty = y; + + if (type == MotionNotify) { + kbp->type = DeviceMotionNotify; + } + else { + if (type == ButtonPress) + kbp->type = DeviceButtonPress; + else if (type == ButtonRelease) + kbp->type = DeviceButtonRelease; + kbp->detail = pDev->button->map[buttons]; + } + + kbp->root_x = x; + kbp->root_y = y; + + if (final_valuator > 2 && sendValuators) { + kbp->deviceid |= MORE_EVENTS; + for (i = first_valuator; i < final_valuator; i += 6) { + xv = (deviceValuator *) ++events; + xv->type = DeviceValuator; + xv->first_valuator = i; + xv->num_valuators = num_valuators; + xv->deviceid = kbp->deviceid; + switch (final_valuator - i) { + case 6: + xv->valuator5 = valuators[i+5]; + case 5: + xv->valuator4 = valuators[i+4]; + case 4: + xv->valuator3 = valuators[i+3]; + case 3: + xv->valuator2 = valuators[i+2]; + case 2: + /* x and y may have been accelerated. */ + if (i == 0) + xv->valuator1 = kbp->root_y; + else + xv->valuator1 = valuators[i+1]; + case 1: + /* x and y may have been accelerated. */ + if (i == 0) + xv->valuator0 = kbp->root_x; + else + xv->valuator0 = valuators[i]; + } + } + } + + if (pDev->coreEvents) { + events++; + events->u.u.type = type; + events->u.keyButtonPointer.time = ms; + events->u.keyButtonPointer.rootX = x; + events->u.keyButtonPointer.rootY = y; + + if (type == ButtonPress || type == ButtonRelease) { + /* We hijack SetPointerMapping to work on all core-sending + * devices, so we use the device-specific map here instead of + * the core one. */ + events->u.u.detail = pDev->button->map[buttons]; + } + else { + events->u.u.detail = 0; + } + + if (inputInfo.pointer->devPrivates[CoreDevicePrivatesIndex].ptr != + pDev) + inputInfo.pointer->devPrivates[CoreDevicePrivatesIndex].ptr = pDev; + } + + return num_events; +} |