Ensure the motion history is merged for master devices.

Add each event to the master's MH as well as to the SDs. In the MD, store
min/max and the actual value. When retrieving the MH, rescale all coordinates
to the current coordinate range and only post those valuators that are
currently active on the device.
This commit is contained in:
Peter Hutterer 2008-05-26 13:53:45 +09:30
parent d22c25bda4
commit 0b88510069
4 changed files with 111 additions and 25 deletions

View File

@ -571,12 +571,8 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
v = to->valuator;
if (!v)
FatalError("[Xi] no memory for class shift.\n");
memcpy(v, from->valuator, sizeof(ValuatorClassRec));
v->motion = NULL;
AllocateMotionHistory(to); /*XXX should be copied somehow */
v->first_motion = 0;
v->last_motion = 0;
v->numAxes = from->valuator->numAxes;
v->axes = (AxisInfoPtr)&v[1];
memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));

View File

@ -132,12 +132,8 @@ ProcXGetDeviceMotionEvents(ClientPtr client)
stop = currentTime;
num_events = v->numMotionEvents;
if (num_events) {
size = sizeof(Time) + (axes * sizeof(INT32));
tsize = num_events * size;
coords = (INT32 *) xalloc(tsize);
if (!coords)
return BadAlloc;
rep.nEvents = GetMotionHistory(dev, (xTimecoord *) coords,/* XXX */
size = sizeof(Time) + (axes * sizeof(INT32));
rep.nEvents = GetMotionHistory(dev, (xTimecoord **) &coords,/* XXX */
start.milliseconds, stop.milliseconds,
(ScreenPtr) NULL);
}

View File

@ -253,6 +253,9 @@ AllocateMotionHistory(DeviceIntPtr pDev)
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);
}
@ -262,18 +265,32 @@ AllocateMotionHistory(DeviceIntPtr pDev)
* sort of ignore this.
*/
_X_EXPORT int
GetMotionHistory(DeviceIntPtr pDev, xTimecoord *buff, unsigned long start,
GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
unsigned long stop, ScreenPtr pScreen)
{
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 */
CARD32 *ocbuf, *icbuf; /* pointer to coordinates for copying */
if (!pDev->valuator || !pDev->valuator->numMotionEvents)
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 = *buff;
for (i = pDev->valuator->first_motion;
i != pDev->valuator->last_motion;
i = (i + 1) % pDev->valuator->numMotionEvents) {
@ -287,8 +304,48 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord *buff, unsigned long start,
return ret;
}
else if (current >= start) {
memcpy(obuff, ibuff, size);
obuff += size;
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 */
obuff += (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
ret++;
}
}
@ -300,29 +357,63 @@ 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++)
{
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;
memcpy(buff, valuators, sizeof(INT32) * num_valuators);
}
pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) %
pDev->valuator->numMotionEvents;
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) %
@ -875,6 +966,9 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
pDev->valuator->axes + 1, scr->height);
updateMotionHistory(pDev, ms, first_valuator, num_valuators, valuators);
if (master)
updateMotionHistory(master, ms, first_valuator, num_valuators,
valuators);
/* Update the valuators with the true value sent to the client*/
if(v0) *v0 = x;

View File

@ -483,7 +483,7 @@ extern void AllocateMotionHistory(
extern int GetMotionHistory(
DeviceIntPtr pDev,
xTimecoord *buff,
xTimecoord **buff,
unsigned long start,
unsigned long stop,
ScreenPtr pScreen);