diff options
author | marha <marha@users.sourceforge.net> | 2009-07-25 20:12:58 +0000 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2009-07-25 20:12:58 +0000 |
commit | 2553bdd7c359cd87525d367761c86932cec5adff (patch) | |
tree | ae71245933c98474a699d3e392de5820879b2018 /xorg-server/dix/getevents.c | |
parent | e2c51f2ee7b0a3ea1a052fc49324057b4a4bbc78 (diff) | |
parent | 4a3dbb926ae3f5410198d7cc4f4ebe4f62eebf05 (diff) | |
download | vcxsrv-2553bdd7c359cd87525d367761c86932cec5adff.tar.gz vcxsrv-2553bdd7c359cd87525d367761c86932cec5adff.tar.bz2 vcxsrv-2553bdd7c359cd87525d367761c86932cec5adff.zip |
svn merge file:///D:/svnrepos/vcxsrv/branches/released .
Diffstat (limited to 'xorg-server/dix/getevents.c')
-rw-r--r-- | xorg-server/dix/getevents.c | 1144 |
1 files changed, 668 insertions, 476 deletions
diff --git a/xorg-server/dix/getevents.c b/xorg-server/dix/getevents.c index 1e0edbf00..9747b35a6 100644 --- a/xorg-server/dix/getevents.c +++ b/xorg-server/dix/getevents.c @@ -47,7 +47,6 @@ #ifdef XKB #include <X11/extensions/XKBproto.h> #include <xkbsrv.h> -extern Bool XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies); #endif #ifdef PANORAMIX @@ -62,14 +61,22 @@ extern Bool XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies); #include "exglobals.h" #include "extnsionst.h" - -/* Maximum number of valuators, divided by six, rounded up, to get number - * of events. */ -#define MAX_VALUATOR_EVENTS 6 - /* Number of motion history events to store. */ #define MOTION_HISTORY_SIZE 256 +/* InputEventList is the container list for all input events generated by the + * DDX. The DDX is expected to call GetEventList() and then pass the list into + * Get{Pointer|Keyboard}Events. + */ +EventListPtr InputEventList = NULL; +int InputEventListLen = 0; + +_X_EXPORT int +GetEventList(EventListPtr* list) +{ + *list = InputEventList; + return InputEventListLen; +} /** * Pick some arbitrary size for Xi motion history. @@ -106,43 +113,151 @@ key_autorepeats(DeviceIntPtr pDev, int key_code) } /** + * Rescale the coord between the two axis ranges. + */ +static int +rescaleValuatorAxis(int coord, AxisInfoPtr from, AxisInfoPtr to, + int defmax) +{ + int fmin = 0, tmin = 0, fmax = defmax, tmax = defmax; + + if(from && from->min_value < from->max_value) { + fmin = from->min_value; + fmax = from->max_value; + } + if(to && to->min_value < to->max_value) { + tmin = to->min_value; + tmax = to->max_value; + } + + if(fmin == tmin && fmax == tmax) + return coord; + + if(fmax == fmin) /* avoid division by 0 */ + return 0; + + return roundf(((float)(coord - fmin)) * (tmax - tmin) / + (fmax - fmin)) + tmin; +} + +/** + * Update all coordinates when changing to a different SD + * to ensure that relative reporting will work as expected + * without loss of precision. + * + * pDev->last.valuators will be in absolute device coordinates after this + * function. + */ +static void +updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev) +{ + ScreenPtr scr = miPointerGetScreen(pDev); + int i; + DeviceIntPtr lastSlave; + + /* master->last.valuators[0]/[1] is in screen coords and the actual + * position of the pointer */ + pDev->last.valuators[0] = master->last.valuators[0]; + pDev->last.valuators[1] = master->last.valuators[1]; + + if (!pDev->valuator) + return; + + /* scale back to device coordinates */ + if(pDev->valuator->numAxes > 0) + pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0], NULL, pDev->valuator->axes + 0, scr->width); + if(pDev->valuator->numAxes > 1) + pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1], NULL, pDev->valuator->axes + 1, scr->height); + + /* calculate the other axis as well based on info from the old + * slave-device. If the old slave had less axes than this one, + * last.valuators is reset to 0. + */ + if ((lastSlave = master->u.lastSlave) && lastSlave->valuator) { + for (i = 2; i < pDev->valuator->numAxes; i++) { + if (i >= lastSlave->valuator->numAxes) + pDev->last.valuators[i] = 0; + else + pDev->last.valuators[i] = + rescaleValuatorAxis(pDev->last.valuators[i], + lastSlave->valuator->axes + i, + pDev->valuator->axes + i, 0); + } + } + +} + +/** * Allocate the motion history buffer. */ _X_EXPORT void AllocateMotionHistory(DeviceIntPtr pDev) { + int size; if (pDev->valuator->motion) xfree(pDev->valuator->motion); if (pDev->valuator->numMotionEvents < 1) return; - pDev->valuator->motion = xalloc(((sizeof(INT32) * pDev->valuator->numAxes) + - sizeof(Time)) * - pDev->valuator->numMotionEvents); + /* An MD must have a motion history size large enough to keep all + * potential valuators, plus the respective range of the valuators. + * 3 * INT32 for (min_val, max_val, curr_val)) + */ + if (pDev->isMaster) + size = sizeof(INT32) * 3 * MAX_VALUATORS; + else + size = sizeof(INT32) * pDev->valuator->numAxes; + + size += sizeof(Time); + + pDev->valuator->motion = xcalloc(pDev->valuator->numMotionEvents, size); pDev->valuator->first_motion = 0; pDev->valuator->last_motion = 0; + if (!pDev->valuator->motion) + ErrorF("[dix] %s: Failed to alloc motion history (%d bytes).\n", + pDev->name, size * pDev->valuator->numMotionEvents); } - /** * Dump the motion history between start and stop into the supplied buffer. * Only records the event for a given screen in theory, but in practice, we * sort of ignore this. + * + * If core is set, we only generate x/y, in INT16, scaled to screen coords. */ _X_EXPORT int -GetMotionHistory(DeviceIntPtr pDev, xTimecoord *buff, unsigned long start, - unsigned long stop, ScreenPtr pScreen) +GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start, + unsigned long stop, ScreenPtr pScreen, BOOL core) { - char *ibuff = NULL, *obuff = (char *) buff; + char *ibuff = NULL, *obuff; int i = 0, ret = 0; + int j, coord; Time current; /* The size of a single motion event. */ - int size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time); + int size; + int dflt; + AxisInfo from, *to; /* for scaling */ + INT32 *ocbuf, *icbuf; /* pointer to coordinates for copying */ + INT16 *corebuf; + AxisInfo core_axis = {0}; if (!pDev->valuator || !pDev->valuator->numMotionEvents) return 0; + if (core && !pScreen) + return 0; + + if (pDev->isMaster) + size = (sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(Time); + else + size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time); + + *buff = xalloc(size * pDev->valuator->numMotionEvents); + if (!(*buff)) + return 0; + obuff = (char *)*buff; + for (i = pDev->valuator->first_motion; i != pDev->valuator->last_motion; i = (i + 1) % pDev->valuator->numMotionEvents) { @@ -156,8 +271,80 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord *buff, unsigned long start, return ret; } else if (current >= start) { - memcpy(obuff, ibuff, size); - obuff += size; + if (core) + { + memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */ + + icbuf = (INT32*)(ibuff + sizeof(Time)); + corebuf = (INT16*)(obuff + sizeof(Time)); + + /* fetch x coordinate + range */ + memcpy(&from.min_value, icbuf++, sizeof(INT32)); + memcpy(&from.max_value, icbuf++, sizeof(INT32)); + memcpy(&coord, icbuf++, sizeof(INT32)); + + /* scale to screen coords */ + to = &core_axis; + to->max_value = pScreen->width; + coord = rescaleValuatorAxis(coord, &from, to, pScreen->width); + + memcpy(corebuf, &coord, sizeof(INT16)); + corebuf++; + + /* fetch y coordinate + range */ + memcpy(&from.min_value, icbuf++, sizeof(INT32)); + memcpy(&from.max_value, icbuf++, sizeof(INT32)); + memcpy(&coord, icbuf++, sizeof(INT32)); + + to->max_value = pScreen->height; + coord = rescaleValuatorAxis(coord, &from, to, pScreen->height); + memcpy(corebuf, &coord, sizeof(INT16)); + + } else if (pDev->isMaster) + { + memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */ + + ocbuf = (INT32*)(obuff + sizeof(Time)); + icbuf = (INT32*)(ibuff + sizeof(Time)); + for (j = 0; j < MAX_VALUATORS; j++) + { + if (j >= pDev->valuator->numAxes) + break; + + /* fetch min/max/coordinate */ + memcpy(&from.min_value, icbuf++, sizeof(INT32)); + memcpy(&from.max_value, icbuf++, sizeof(INT32)); + memcpy(&coord, icbuf++, sizeof(INT32)); + + to = (j < pDev->valuator->numAxes) ? &pDev->valuator->axes[j] : NULL; + + /* x/y scaled to screen if no range is present */ + if (j == 0 && (from.max_value < from.min_value)) + from.max_value = pScreen->width; + else if (j == 1 && (from.max_value < from.min_value)) + from.max_value = pScreen->height; + + if (j == 0 && (to->max_value < to->min_value)) + dflt = pScreen->width; + else if (j == 1 && (to->max_value < to->min_value)) + dflt = pScreen->height; + else + dflt = 0; + + /* scale from stored range into current range */ + coord = rescaleValuatorAxis(coord, &from, to, 0); + memcpy(ocbuf, &coord, sizeof(INT32)); + ocbuf++; + } + } else + memcpy(obuff, ibuff, size); + + /* don't advance by size here. size may be different to the + * actually written size if the MD has less valuators than MAX */ + if (core) + obuff += sizeof(INT32) + sizeof(Time); + else + obuff += (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time); ret++; } } @@ -169,29 +356,65 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord *buff, unsigned long start, /** * Update the motion history for a specific device, with the list of * valuators. + * + * Layout of the history buffer: + * for SDs: [time] [val0] [val1] ... [valn] + * for MDs: [time] [min_val0] [max_val0] [val0] [min_val1] ... [valn] + * + * For events that have some valuators unset (first_valuator > 0): + * min_val == max_val == val == 0. */ static void updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, int first_valuator, int num_valuators, int *valuators) { char *buff = (char *) pDev->valuator->motion; + ValuatorClassPtr v; + int i; if (!pDev->valuator->numMotionEvents) return; - buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) * + v = pDev->valuator; + if (pDev->isMaster) + { + buff += ((sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(CARD32)) * + v->last_motion; + + memcpy(buff, &ms, sizeof(Time)); + buff += sizeof(Time); + + memset(buff, 0, sizeof(INT32) * 3 * MAX_VALUATORS); + buff += 3 * sizeof(INT32) * first_valuator; + + for (i = first_valuator; i < first_valuator + num_valuators; i++) + { + if (i >= v->numAxes) + break; + memcpy(buff, &v->axes[i].min_value, sizeof(INT32)); + buff += sizeof(INT32); + memcpy(buff, &v->axes[i].max_value, sizeof(INT32)); + buff += sizeof(INT32); + memcpy(buff, &valuators[i - first_valuator], sizeof(INT32)); + buff += sizeof(INT32); + } + } else + { + + buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) * pDev->valuator->last_motion; - memcpy(buff, &ms, sizeof(Time)); - buff += sizeof(Time); - bzero(buff, sizeof(INT32) * pDev->valuator->numAxes); + memcpy(buff, &ms, sizeof(Time)); + buff += sizeof(Time); - buff += sizeof(INT32) * first_valuator; - memcpy(buff, valuators, sizeof(INT32) * num_valuators); + memset(buff, 0, sizeof(INT32) * pDev->valuator->numAxes); + buff += sizeof(INT32) * first_valuator; - pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) % - pDev->valuator->numMotionEvents; + memcpy(buff, valuators, sizeof(INT32) * num_valuators); + } + pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) % + pDev->valuator->numMotionEvents; /* If we're wrapping around, just keep the circular buffer going. */ if (pDev->valuator->first_motion == pDev->valuator->last_motion) pDev->valuator->first_motion = (pDev->valuator->first_motion + 1) % @@ -212,9 +435,9 @@ updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, int first_valuator, */ _X_EXPORT int GetMaximumEventsNum(void) { - /* Two base events -- core and device, plus valuator events. Multiply - * by two if we're doing non-XKB key repeats. */ - int ret = 2 + MAX_VALUATOR_EVENTS; + /* One base event -- device, plus valuator events. + * Multiply by two if we're doing non-XKB key repeats. */ + int ret = 1 + MAX_VALUATOR_EVENTS; #ifdef XKB if (noXkbExtension) @@ -225,80 +448,6 @@ GetMaximumEventsNum(void) { } -/* Originally a part of xf86PostMotionEvent; modifies valuators - * in-place. */ -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; - - 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 * (float)dx + (float)dy * (float)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); - } - } - } -} - - /** * Clip an axis to its bounds, which are declared in the call to * InitValuatorAxisClassStruct. @@ -306,15 +455,17 @@ acceleratePointer(DeviceIntPtr pDev, int first_valuator, int num_valuators, static void clipAxis(DeviceIntPtr pDev, int axisNum, int *val) { - AxisInfoPtr axes = pDev->valuator->axes + axisNum; - - /* No clipping if the value-range <= 0 */ - if(axes->min_value < axes->min_value) { - if (*val < axes->min_value) - *val = axes->min_value; - if (*val > axes->max_value) - *val = axes->max_value; - } + AxisInfoPtr axis = pDev->valuator->axes + axisNum; + /* InitValuatoraAxisStruct ensures that (min < max). */ + + /* If a value range is defined, clip. If not, do nothing */ + if (axis->max_value <= axis->min_value) + return; + + if (*val < axis->min_value) + *val = axis->min_value; + if (*val > axis->max_value) + *val = axis->max_value; } /** @@ -335,23 +486,20 @@ clipValuators(DeviceIntPtr pDev, int first_valuator, int num_valuators, /** * Fills events with valuator events for pDev, as given by the other * parameters. - * - * FIXME: Need to fix ValuatorClassRec to store all the valuators as - * last posted, not just x and y; otherwise relative non-x/y - * valuators, though a very narrow use case, will be broken. */ -static xEvent * -getValuatorEvents(xEvent *events, DeviceIntPtr pDev, int first_valuator, - int num_valuators, int *valuators) { - deviceValuator *xv = (deviceValuator *) events; - int i = 0, final_valuator = first_valuator + num_valuators; +static EventList * +getValuatorEvents(EventList *events, DeviceIntPtr pDev, + int first_valuator, int num_valuators, int *valuators) { + deviceValuator *xv; + int i; - for (i = first_valuator; i < final_valuator; i += 6, xv++, events++) { + for (i = 0; i < num_valuators; i += 6, events++) { + xv = (deviceValuator*)events->event; xv->type = DeviceValuator; - xv->first_valuator = i; - xv->num_valuators = ((final_valuator - i) > 6) ? 6 : (final_valuator - i); + xv->first_valuator = first_valuator + i; + xv->num_valuators = ((num_valuators - i) > 6) ? 6 : (num_valuators - i); xv->deviceid = pDev->id; - switch (final_valuator - i) { + switch (num_valuators - i) { case 6: xv->valuator5 = valuators[i + 5]; case 5: @@ -363,23 +511,235 @@ getValuatorEvents(xEvent *events, DeviceIntPtr pDev, int first_valuator, case 2: xv->valuator1 = valuators[i + 1]; case 1: - xv->valuator0 = valuators[i]; + xv->valuator0 = valuators[i + 0]; } - if (i + 6 < final_valuator) + if (i + 6 < num_valuators) xv->deviceid |= MORE_EVENTS; } return events; } +/** + * Create the DCCE event (does not update the master's device state yet, this + * is done in the event processing). + * Pull in the coordinates from the MD if necessary. + * + * @param events Pointer to a pre-allocated event list. + * @param dev The slave device that generated an event. + * @param num_events The current number of events, returns the number of + * events if a DCCE was generated. + * @return The updated @events pointer. + */ +static EventListPtr +updateFromMaster(EventListPtr events, DeviceIntPtr dev, int *num_events) +{ + DeviceIntPtr master = dev->u.master; + if (master && master->u.lastSlave != dev) + { + updateSlaveDeviceCoords(master, dev); + master->u.lastSlave = dev; + master->last.numValuators = dev->last.numValuators; + } + return events; +} + +/** + * Move the device's pointer to the position given in the valuators. + * + * @param dev The device which's pointer is to be moved. + * @param x Returns the x position of the pointer after the move. + * @param y Returns the y position of the pointer after the move. + * @param first The first valuator in @valuators + * @param num Total number of valuators in @valuators. + * @param valuators Valuator data for each axis between @first and + * @first+@num. + */ +static void +moveAbsolute(DeviceIntPtr dev, int *x, int *y, + int first, int num, int *valuators) +{ + int i; + + + if (num >= 1 && first == 0) + *x = *(valuators + 0); + else + *x = dev->last.valuators[0]; + + if (first <= 1 && num >= (2 - first)) + *y = *(valuators + 1 - first); + else + *y = dev->last.valuators[1]; + + clipAxis(dev, 0, x); + clipAxis(dev, 1, y); + + i = (first > 2) ? 0 : 2; + for (; i < num; i++) + { + dev->last.valuators[i + first] = valuators[i]; + clipAxis(dev, i, &dev->last.valuators[i + first]); + } +} + +/** + * Move the device's pointer by the values given in @valuators. + * + * @param dev The device which's pointer is to be moved. + * @param x Returns the x position of the pointer after the move. + * @param y Returns the y position of the pointer after the move. + * @param first The first valuator in @valuators + * @param num Total number of valuators in @valuators. + * @param valuators Valuator data for each axis between @first and + * @first+@num. + */ +static void +moveRelative(DeviceIntPtr dev, int *x, int *y, + int first, int num, int *valuators) +{ + int i; + + *x = dev->last.valuators[0]; + *y = dev->last.valuators[1]; + + if (num >= 1 && first == 0) + *x += *(valuators +0); + + if (first <= 1 && num >= (2 - first)) + *y += *(valuators + 1 - first); + + /* if attached, clip both x and y to the defined limits (usually + * co-ord space limit). If it is attached, we need x/y to go over the + * limits to be able to change screens. */ + if(dev->u.master) { + clipAxis(dev, 0, x); + clipAxis(dev, 1, y); + } + + /* calc other axes, clip, drop back into valuators */ + i = (first > 2) ? 0 : 2; + for (; i < num; i++) + { + dev->last.valuators[i + first] += valuators[i]; + clipAxis(dev, i, &dev->last.valuators[i + first]); + valuators[i] = dev->last.valuators[i + first]; + } +} + +/** + * Accelerate the data in valuators based on the device's acceleration scheme. + * + * @param dev The device which's pointer is to be moved. + * @param first The first valuator in @valuators + * @param num Total number of valuators in @valuators. + * @param valuators Valuator data for each axis between @first and + * @first+@num. + * @param ms Current time. + */ +static void +accelPointer(DeviceIntPtr dev, int first, int num, int *valuators, CARD32 ms) +{ + if (dev->valuator->accelScheme.AccelSchemeProc) + dev->valuator->accelScheme.AccelSchemeProc(dev, first, num, valuators, ms); +} + +/** + * If we have HW cursors, this actually moves the visible sprite. If not, we + * just do all the screen crossing, etc. + * + * We scale from device to screen coordinates here, call + * miPointerSetPosition() and then scale back into device coordinates (if + * needed). miPSP will change x/y if the screen was crossed. + * + * @param dev The device to be moved. + * @param x Pointer to current x-axis value, may be modified. + * @param y Pointer to current y-axis value, may be modified. + * @param scr Screen the device's sprite is currently on. + * @param screenx Screen x coordinate the sprite is on after the update. + * @param screeny Screen y coordinate the sprite is on after the update. + */ +static void +positionSprite(DeviceIntPtr dev, int *x, int *y, + ScreenPtr scr, int *screenx, int *screeny) +{ + /* scale x&y to screen */ + *screenx = rescaleValuatorAxis(*x, dev->valuator->axes + 0, NULL, scr->width); + *screeny = rescaleValuatorAxis(*y, dev->valuator->axes + 1, NULL, scr->height); + dev->last.valuators[0] = *screenx; + dev->last.valuators[1] = *screeny; + + /* This takes care of crossing screens for us, as well as clipping + * to the current screen. */ + miPointerSetPosition(dev, &dev->last.valuators[0], &dev->last.valuators[1]); + + if (dev->u.master) { + dev->u.master->last.valuators[0] = dev->last.valuators[0]; + dev->u.master->last.valuators[1] = dev->last.valuators[1]; + } + + /* Crossed screen? Scale back to device coordiantes */ + if(*screenx != dev->last.valuators[0]) + { + scr = miPointerGetScreen(dev); + *x = rescaleValuatorAxis(dev->last.valuators[0], NULL, + dev->valuator->axes + 0, scr->width); + *screenx = dev->last.valuators[0]; + } + if(*screeny != dev->last.valuators[1]) + { + scr = miPointerGetScreen(dev); + *screeny = dev->last.valuators[1]; + *y = rescaleValuatorAxis(dev->last.valuators[1], NULL, + dev->valuator->axes + 1, scr->height); + } + + /* dropy x/y (device coordinates) back into valuators for next event */ + dev->last.valuators[0] = *x; + dev->last.valuators[1] = *y; +} + +/** + * Update the motion history for the device and (if appropriate) for its + * master device. + * @param dev Slave device to update. + * @param first First valuator to append to history. + * @param num Total number of valuators to append to history. + * @param ms Current time + */ +static void +updateHistory(DeviceIntPtr dev, int first, int num, CARD32 ms) +{ + updateMotionHistory(dev, ms, first, num, &dev->last.valuators[first]); + if (dev->u.master) + updateMotionHistory(dev->u.master, ms, first, num, + &dev->last.valuators[first]); +} + +/** + * Calculate how many DeviceValuator events are needed given a number of + * valuators. + * @param num_valuators Number of valuators to attach to event. + * @return the number of DeviceValuator events needed. + */ +static int +countValuatorEvents(int num_valuators) +{ + if (num_valuators) { + if (((num_valuators - 1) / 6) + 1 > MAX_VALUATOR_EVENTS) + num_valuators = MAX_VALUATOR_EVENTS * 6; + return ((num_valuators - 1)/ 6) + 1; + } else + return 0; +} /** * Convenience wrapper around GetKeyboardValuatorEvents, that takes no * valuators. */ _X_EXPORT int -GetKeyboardEvents(xEvent *events, DeviceIntPtr pDev, int type, int key_code) { +GetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code) { return GetKeyboardValuatorEvents(events, pDev, type, key_code, 0, 0, NULL); } @@ -388,6 +748,9 @@ GetKeyboardEvents(xEvent *events, DeviceIntPtr pDev, int type, int key_code) { * Returns a set of keyboard events for KeyPress/KeyRelease, optionally * also with valuator events. Handles Xi and XKB. * + * DOES NOT GENERATE CORE EVENTS! Core events are created when processing the + * event (ProcessOtherEvent). + * * 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. @@ -402,42 +765,29 @@ GetKeyboardEvents(xEvent *events, DeviceIntPtr pDev, int type, int key_code) { * KeyPresses. */ _X_EXPORT int -GetKeyboardValuatorEvents(xEvent *events, DeviceIntPtr pDev, int type, +GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code, int first_valuator, int num_valuators, int *valuators) { int numEvents = 0; CARD32 ms = 0; - KeySym *map = pDev->key->curKeySyms.map; + KeySym *map; KeySym sym; deviceKeyButtonPointer *kbp = NULL; - if (!events) - return 0; - - /* DO NOT WANT */ - if (type != KeyPress && type != KeyRelease) + if (!events ||!pDev->key || !pDev->focus || !pDev->kbdfeed || + (type != KeyPress && type != KeyRelease) || + (key_code < 8 || key_code > 255)) return 0; - if (!pDev->key || !pDev->focus || !pDev->kbdfeed || - (pDev->coreEvents && !inputInfo.keyboard->key)) - return 0; - - if (key_code < 8 || key_code > 255) - return 0; + numEvents = 1; + map = pDev->key->curKeySyms.map; sym = map[(key_code - pDev->key->curKeySyms.minKeyCode) * pDev->key->curKeySyms.mapWidth]; - if (pDev->coreEvents) - numEvents = 2; - else - numEvents = 1; + events = updateFromMaster(events, pDev, &numEvents); - if (num_valuators) { - if ((num_valuators / 6) + 1 > MAX_VALUATOR_EVENTS) - num_valuators = MAX_VALUATOR_EVENTS; - numEvents += (num_valuators / 6) + 1; - } + numEvents += countValuatorEvents(num_valuators); #ifdef XKB if (noXkbExtension) @@ -470,28 +820,21 @@ GetKeyboardValuatorEvents(xEvent *events, DeviceIntPtr pDev, int type, if (noXkbExtension) #endif { - numEvents += GetKeyboardValuatorEvents(events, pDev, - KeyRelease, key_code, - first_valuator, num_valuators, - valuators); - events += numEvents; + int numReleaseEvents; + + numReleaseEvents = GetKeyboardValuatorEvents(events, pDev, + KeyRelease, key_code, + first_valuator, + num_valuators, + valuators); + numEvents += numReleaseEvents; + events += numReleaseEvents; } } ms = GetTimeInMillis(); - if (pDev->coreEvents) { - events->u.keyButtonPointer.time = ms; - events->u.u.type = type; - events->u.u.detail = key_code; - if (type == KeyPress) - set_key_down(inputInfo.keyboard, key_code); - else if (type == KeyRelease) - set_key_up(inputInfo.keyboard, key_code); - events++; - } - - kbp = (deviceKeyButtonPointer *) events; + kbp = (deviceKeyButtonPointer *) events->event; kbp->time = ms; kbp->deviceid = pDev->id; kbp->detail = key_code; @@ -515,261 +858,179 @@ GetKeyboardValuatorEvents(xEvent *events, DeviceIntPtr pDev, int type, return numEvents; } +/** + * Initialize an event list and fill with 32 byte sized events. + * This event list is to be passed into GetPointerEvents() and + * GetKeyboardEvents(). + * + * @param num_events Number of elements in list. + */ +EventListPtr +InitEventList(int num_events) +{ + EventListPtr events; + int i; + + events = (EventListPtr)xcalloc(num_events, sizeof(EventList)); + if (!events) + return NULL; + + for (i = 0; i < num_events; i++) + { + events[i].evlen = sizeof(xEvent); + events[i].event = xcalloc(1, sizeof(xEvent)); + if (!events[i].event) + { + /* rollback */ + while(i--) + xfree(events[i].event); + xfree(events); + events = NULL; + break; + } + } + + return events; +} + +/** + * Allocs min_size memory for each event in the list. + */ +_X_EXPORT void +SetMinimumEventSize(EventListPtr list, int num_events, int min_size) +{ + if (!list) + return; + + while(num_events--) + { + if (list[num_events].evlen < min_size) + { + list[num_events].evlen = min_size; + list[num_events].event = realloc(list[num_events].event, min_size); + if (!list[num_events].event) + { + FatalError("[dix] Failed to set event list's " + "min_size to %d.\n", min_size); + } + } + } +} + +/** + * Free an event list. + * + * @param list The list to be freed. + * @param num_events Number of elements in list. + */ +_X_EXPORT void +FreeEventList(EventListPtr list, int num_events) +{ + if (!list) + return; + while(num_events--) + xfree(list[num_events].event); + xfree(list); +} /** - * Generate a series of xEvents (returned in xE) representing pointer - * motion, or button presses. Xi and XKB-aware. + * Generate a series of xEvents (filled into the EventList) representing + * pointer motion, or button presses. Xi and XKB-aware. + * + * DOES NOT GENERATE CORE EVENTS! Core events are created when processing the + * event (ProcessOtherEvent). * * 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. + * place via InitEventList() and GetMaximumEventsNum(), and for freeing it. + * + * In the generated events rootX/Y will be in absolute screen coords and + * the valuator information in the absolute or relative device coords. + * + * last.valuators[x] of the device is always in absolute device coords. + * last.valuators[x] of the master device is in absolute screen coords. + * + * master->last.valuators[x] for x > 2 is undefined. */ _X_EXPORT int -GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons, +GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons, int flags, int first_valuator, int num_valuators, int *valuators) { - int num_events = 0, final_valuator = 0; - CARD32 ms = 0; + int num_events = 1; + CARD32 ms; deviceKeyButtonPointer *kbp = NULL; - DeviceIntPtr cp = inputInfo.pointer; - int x = 0, y = 0; - Bool coreOnly = (pDev == inputInfo.pointer); + int x, y, /* switches between device and screen coords */ + cx, cy; /* only screen coordinates */ ScreenPtr scr = miPointerGetScreen(pDev); - /* Sanity checks. */ - if (type != MotionNotify && type != ButtonPress && type != ButtonRelease) - return 0; - - if ((type == ButtonPress || type == ButtonRelease) && !pDev->button) - return 0; - - /* FIXME: I guess it should, in theory, be possible to post button events - * from devices without valuators. */ - if (!pDev->valuator) - return 0; - - if (!coreOnly && pDev->coreEvents) - num_events = 2; - else - num_events = 1; + ms = GetTimeInMillis(); /* before pointer update to help precision */ - if (type == MotionNotify && num_valuators <= 0) + if (!scr || !pDev->valuator || first_valuator < 0 || + ((num_valuators + first_valuator) > pDev->valuator->numAxes) || + (type != MotionNotify && type != ButtonPress && type != ButtonRelease) || + (type != MotionNotify && !pDev->button) || + (type == MotionNotify && num_valuators <= 0)) return 0; - /* Do we need to send a DeviceValuator event? */ - if (!coreOnly && num_valuators) { - if ((((num_valuators - 1) / 6) + 1) > MAX_VALUATOR_EVENTS) - num_valuators = MAX_VALUATOR_EVENTS * 6; - num_events += ((num_valuators - 1) / 6) + 1; - } - - final_valuator = num_valuators + first_valuator; - - /* You fail. */ - if (first_valuator < 0 || final_valuator > pDev->valuator->numAxes) - return 0; + num_events += countValuatorEvents(num_valuators); - ms = GetTimeInMillis(); + events = updateFromMaster(events, pDev, &num_events); - /* Set x and y based on whether this is absolute or relative, and - * accelerate if we need to. */ - if (flags & POINTER_ABSOLUTE) { - if (num_valuators >= 1 && first_valuator == 0) { - x = valuators[0]; - } - else { - /* If we're sending core events but didn't provide a value, - * translate the core value (but use the device coord if - * it translates to the same coord to preserve sub-pixel - * coord information). If we're not sending core events use - * whatever value we have */ - x = pDev->valuator->lastx; - if(pDev->coreEvents) { - int min = pDev->valuator->axes[0].min_value; - int max = pDev->valuator->axes[0].max_value; - if(min < max) { - if((int)((float)(x-min)*scr->width/(max-min+1)) != cp->valuator->lastx) - x = (int)((float)(cp->valuator->lastx)*(max-min+1)/scr->width)+min; - } - else - x = cp->valuator->lastx; - } - } + if (flags & POINTER_ABSOLUTE) + { + if (flags & POINTER_SCREEN) /* valuators are in screen coords */ + { - if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) { - y = valuators[1 - first_valuator]; - } - else { - y = pDev->valuator->lasty; - if(pDev->coreEvents) { - int min = pDev->valuator->axes[1].min_value; - int max = pDev->valuator->axes[1].max_value; - if(min < max) { - if((int)((float)(y-min)*scr->height/(max-min+1)) != cp->valuator->lasty) - y = (int)((float)(cp->valuator->lasty)*(max-min+1)/scr->height)+min; - } - else - y = cp->valuator->lasty; - } + valuators[0] = rescaleValuatorAxis(valuators[0], NULL, + pDev->valuator->axes + 0, + scr->width); + valuators[1] = rescaleValuatorAxis(valuators[1], NULL, + pDev->valuator->axes + 1, + scr->height); } - /* Clip both x and y to the defined limits (usually co-ord space limit). */ - clipAxis(pDev, 0, &x); - clipAxis(pDev, 1, &y); - } - else { + moveAbsolute(pDev, &x, &y, first_valuator, num_valuators, valuators); + } else { if (flags & POINTER_ACCELERATE) - acceleratePointer(pDev, first_valuator, num_valuators, - valuators); - - if (pDev->coreEvents) { - /* Get and convert the core pointer coordinate space into - * device coordinates. Use the device coords if it translates - * into the same position as the core to preserve relative sub- - * pixel movements from the device. */ - int min = pDev->valuator->axes[0].min_value; - int max = pDev->valuator->axes[0].max_value; - if(min < max) { - x = pDev->valuator->lastx; - if((int)((float)(x-min)*scr->width/(max-min+1)) != cp->valuator->lastx) - x = (int)((float)(cp->valuator->lastx)*(max-min+1)/scr->width)+min; - } - else - x = cp->valuator->lastx; - - min = pDev->valuator->axes[1].min_value; - max = pDev->valuator->axes[1].max_value; - if(min < max) { - y = pDev->valuator->lasty; - if((int)((float)(y-min)*scr->height/(max-min+1)) != cp->valuator->lasty) - y = (int)((float)(cp->valuator->lasty)*(max-min+1)/scr->height)+min; - } - else - y = cp->valuator->lasty; - - /* Add relative movement */ - if (first_valuator == 0 && num_valuators >= 1) - x += valuators[0]; - if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) - y += valuators[1 - first_valuator]; - } - else { - x = pDev->valuator->lastx; - y = pDev->valuator->lasty; - if (first_valuator == 0 && num_valuators >= 1) - x += valuators[0]; - if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) - y += valuators[1 - first_valuator]; - - if(!coreOnly) { - /* Since we're not sending core-events we must clip both x and y - * to the defined limits so we don't run outside the box. */ - clipAxis(pDev, 0, &x); - clipAxis(pDev, 1, &y); - } - } + accelPointer(pDev, first_valuator, num_valuators, valuators, ms); + moveRelative(pDev, &x, &y, first_valuator, num_valuators, valuators); } - pDev->valuator->lastx = x; - pDev->valuator->lasty = y; - /* Convert the dev coord back to screen coord if we're - * sending core events */ - if (pDev->coreEvents) { - int min = pDev->valuator->axes[0].min_value; - int max = pDev->valuator->axes[0].max_value; - if(min < max) - x = (int)((float)(x-min)*scr->width/(max-min+1)); - cp->valuator->lastx = x; - min = pDev->valuator->axes[1].min_value; - max = pDev->valuator->axes[1].max_value; - if(min < max) - y = (int)((float)(y-min)*scr->height/(max-min+1)); - cp->valuator->lasty = y; - } + positionSprite(pDev, &x, &y, scr, &cx, &cy); + updateHistory(pDev, first_valuator, num_valuators, ms); - /* 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) { - /* miPointerSetPosition may have changed screen */ - scr = miPointerGetScreen(pDev); - if(x != cp->valuator->lastx) { - int min = pDev->valuator->axes[0].min_value; - int max = pDev->valuator->axes[0].max_value; - cp->valuator->lastx = pDev->valuator->lastx = x; - if(min < max) - pDev->valuator->lastx = (int)((float)(x)*(max-min+1)/scr->width)+min; - } - if(y != cp->valuator->lasty) { - int min = pDev->valuator->axes[1].min_value; - int max = pDev->valuator->axes[1].max_value; - cp->valuator->lasty = pDev->valuator->lasty = y; - if(min < max) - pDev->valuator->lasty = (int)((float)(y)*(max-min+1)/scr->height)+min; - } - } - else if (coreOnly) { - cp->valuator->lastx = x; - cp->valuator->lasty = y; - } - /* Drop x and y back into the valuators list, if they were originally - * present. */ - if (first_valuator == 0 && num_valuators >= 1) - valuators[0] = pDev->valuator->lastx; + /* Update the valuators with the true value sent to the client*/ + if (num_valuators >= 1 && first_valuator == 0) + valuators[0] = x; if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) - valuators[1 - first_valuator] = pDev->valuator->lasty; - - updateMotionHistory(pDev, ms, first_valuator, num_valuators, valuators); - - /* for some reason inputInfo.pointer does not have coreEvents set */ - if (coreOnly || pDev->coreEvents) { - 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; - } + valuators[1 - first_valuator] = y; - events++; - } - - if (!coreOnly) { - kbp = (deviceKeyButtonPointer *) events; - kbp->time = ms; - kbp->deviceid = pDev->id; + kbp = (deviceKeyButtonPointer *) events->event; + kbp->time = ms; + kbp->deviceid = pDev->id; - 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]; - } + if (type == MotionNotify) { + kbp->type = DeviceMotionNotify; + } + else { + if (type == ButtonPress) + kbp->type = DeviceButtonPress; + else if (type == ButtonRelease) + kbp->type = DeviceButtonRelease; + kbp->detail = buttons; + } - kbp->root_x = pDev->valuator->lastx; - kbp->root_y = pDev->valuator->lasty; + kbp->root_x = cx; /* root_x/y always in screen coords */ + kbp->root_y = cy; - events++; - if (num_valuators) { - kbp->deviceid |= MORE_EVENTS; + events++; + if (num_valuators) { + kbp->deviceid |= MORE_EVENTS; + if (flags & POINTER_ABSOLUTE) clipValuators(pDev, first_valuator, num_valuators, valuators); - events = getValuatorEvents(events, pDev, first_valuator, - num_valuators, valuators); - } + events = getValuatorEvents(events, pDev, first_valuator, + num_valuators, valuators); } return num_events; @@ -784,19 +1045,18 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons, * place via GetMaximumEventsNum(), and for freeing it. */ _X_EXPORT int -GetProximityEvents(xEvent *events, DeviceIntPtr pDev, int type, +GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type, int first_valuator, int num_valuators, int *valuators) { int num_events = 1; - deviceKeyButtonPointer *kbp = (deviceKeyButtonPointer *) events; + deviceKeyButtonPointer *kbp; + DeviceIntPtr master; /* Sanity checks. */ if (type != ProximityIn && type != ProximityOut) return 0; - if (!pDev->valuator) return 0; - /* Do we need to send a DeviceValuator event? */ if ((pDev->valuator->mode & 1) == Relative) num_valuators = 0; @@ -812,6 +1072,15 @@ GetProximityEvents(xEvent *events, DeviceIntPtr pDev, int type, (num_valuators + first_valuator) > pDev->valuator->numAxes) return 0; + master = pDev->u.master; + if (master && master->u.lastSlave != pDev) + { + updateSlaveDeviceCoords(master, pDev); + master->u.lastSlave = pDev; + master->last.numValuators = pDev->last.numValuators; + } + + kbp = (deviceKeyButtonPointer *) events->event; kbp->type = type; kbp->deviceid = pDev->id; kbp->detail = 0; @@ -828,87 +1097,6 @@ GetProximityEvents(xEvent *events, DeviceIntPtr pDev, int type, return num_events; } - -/** - * Note that pDev was the last device to send a core event. This function - * copies the complete keymap from the originating device to the core - * device, and makes sure the appropriate notifications are generated. - * - * Call this just before processInputProc. - */ -_X_EXPORT void -SwitchCoreKeyboard(DeviceIntPtr pDev) -{ - KeyClassPtr ckeyc = inputInfo.keyboard->key; - int i = 0; - - if (pDev != dixLookupPrivate(&inputInfo.keyboard->devPrivates, - CoreDevicePrivateKey)) { - 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); - - /* - * Copy state from the extended keyboard to core. If you omit this, - * holding Ctrl on keyboard one, and pressing Q on keyboard two, will - * cause your app to quit. This feels wrong to me, hence the below - * code. - * - * XXX: If you synthesise core modifier events, the state will get - * clobbered here. You'll have to work out something sensible - * to fix that. Good luck. - */ - -#define KEYBOARD_MASK (ShiftMask | LockMask | ControlMask | Mod1Mask | \ - Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask) - ckeyc->state &= ~(KEYBOARD_MASK); - ckeyc->state |= (pDev->key->state & KEYBOARD_MASK); -#undef KEYBOARD_MASK - for (i = 0; i < 8; i++) - ckeyc->modifierKeyCount[i] = pDev->key->modifierKeyCount[i]; - -#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); - dixSetPrivate(&inputInfo.keyboard->devPrivates, CoreDevicePrivateKey, - pDev); - } -} - - -/** - * Note that pDev was the last function to send a core pointer event. - * Currently a no-op. - * - * Call this just before processInputProc. - */ -_X_EXPORT void -SwitchCorePointer(DeviceIntPtr pDev) -{ - if (pDev != dixLookupPrivate(&inputInfo.pointer->devPrivates, - CoreDevicePrivateKey)) - dixSetPrivate(&inputInfo.pointer->devPrivates, - CoreDevicePrivateKey, pDev); -} - - /** * Synthesize a single motion event for the core pointer. * @@ -916,7 +1104,11 @@ SwitchCorePointer(DeviceIntPtr pDev) * to shift the pointer to get it inside the new bounds. */ void -PostSyntheticMotion(int x, int y, int screen, unsigned long time) +PostSyntheticMotion(DeviceIntPtr pDev, + int x, + int y, + int screen, + unsigned long time) { xEvent xE; @@ -936,5 +1128,5 @@ PostSyntheticMotion(int x, int y, int screen, unsigned long time) xE.u.keyButtonPointer.rootY = y; xE.u.keyButtonPointer.time = time; - (*inputInfo.pointer->public.processInputProc)(&xE, inputInfo.pointer, 1); + (*pDev->public.processInputProc)(&xE, pDev, 1); } |