dix: more device scaling insanity.

Assuming master->last.valuators is in screen coords, SD's are always in device
coordinates.

1. If an event comes in, scale masters->last to the device, drop into device's
last->valuators.
2. Apply motion from the actual event
3. Scale back to screen coords, check if we may need to cross screens
4. Drop screen coords into master->last
5. Rescale to device coords, drop into deviceValuator event and SD->last
6. Drop screen coords into ev->root_x/y

Whoopee...
This commit is contained in:
Peter Hutterer 2008-05-23 12:51:52 +09:30
parent 6c9e9f8a40
commit fe59b1a62b
2 changed files with 41 additions and 31 deletions

View File

@ -183,24 +183,25 @@ rescaleValuatorAxis(int coord, AxisInfoPtr from, AxisInfoPtr to,
* 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);
/* last.valuators[0]/[1] is in screen coords and the actual position
* of the pointer */
/* 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];
/* the valuator axis is in device coords and holds the
* position of the pointer, but in device coords. */
/* scale back to device coordinates */
if(pDev->valuator->numAxes > 0)
pDev->valuator->axisVal[0] = rescaleValuatorAxis(pDev->last.valuators[0], NULL,
pDev->valuator->axes + 0, scr->width);
pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0], NULL, pDev->valuator->axes + 0, scr->width);
if(pDev->valuator->numAxes > 1)
pDev->valuator->axisVal[1] = rescaleValuatorAxis(pDev->last.valuators[1], NULL,
pDev->valuator->axes + 1, scr->height);
pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1], NULL, pDev->valuator->axes + 1, scr->height);
/*TODO calculate the other axis as well based on info from the old slave-device */
}
@ -709,8 +710,9 @@ FreeEventList(EventListPtr list, int num_events)
*
* 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[0]/[1] of the device is always in absolute screen coords
* while the device valuator struct contain the absolute 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.
*/
_X_EXPORT int
GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
@ -720,7 +722,8 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
CARD32 ms;
deviceKeyButtonPointer *kbp = NULL;
DeviceIntPtr master;
int x, y, cx, cy;
int x, y, /* switches between device and screen coords */
cx, cy; /* only screen coordinates */
ScreenPtr scr = miPointerGetScreen(pDev);
int *v0 = NULL, *v1 = NULL;
@ -769,8 +772,8 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
/* Set x and y based on whether this is absolute or relative, and
* accelerate if we need to. */
x = pDev->valuator->axisVal[0];
y = pDev->valuator->axisVal[1];
x = pDev->last.valuators[0];
y = pDev->last.valuators[1];
if (flags & POINTER_ABSOLUTE) {
if(v0) x = *v0;
if(v1) y = *v1;
@ -811,21 +814,26 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
* so we don't set this for both the device and core.*/
miPointerSetPosition(pDev, &pDev->last.valuators[0], &pDev->last.valuators[1], ms);
scr = miPointerGetScreen(pDev);
if(cx != pDev->last.valuators[0])
x = rescaleValuatorAxis(pDev->last.valuators[0], NULL,
pDev->valuator->axes + 0, scr->width);
if(cy != pDev->last.valuators[1])
y = rescaleValuatorAxis(pDev->last.valuators[1], NULL,
pDev->valuator->axes + 1, scr->height);
updateMotionHistory(pDev, ms, first_valuator, num_valuators, valuators);
if (master) {
master->last.valuators[0] = pDev->last.valuators[0];
master->last.valuators[1] = pDev->last.valuators[1];
}
if(cx != pDev->last.valuators[0])
cx = pDev->last.valuators[0];
if(cy != pDev->last.valuators[1])
cy = pDev->last.valuators[1];
/* scale x/y back to device coordinates */
scr = miPointerGetScreen(pDev);
x = rescaleValuatorAxis(pDev->last.valuators[0], NULL,
pDev->valuator->axes + 0, scr->width);
y = rescaleValuatorAxis(pDev->last.valuators[1], NULL,
pDev->valuator->axes + 1, scr->height);
updateMotionHistory(pDev, ms, first_valuator, num_valuators, valuators);
/* update the valuators based on the mode of the InputDevice */
if(pDev->valuator->mode == Absolute) {
/* Update the valuators with the true value sent to the client*/
@ -838,14 +846,14 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
* values. If relative report, keep it as-is.*/
if (flags & POINTER_ABSOLUTE) {
int i;
for (i = 0; i < num_valuators; i++)
valuators[i] = valuators[i] - pDev->valuator->axisVal[i + first_valuator];
for (i = 0; i < num_valuators && i < pDev->last.numValuators; i++)
valuators[i] = valuators[i] - pDev->last.valuators[i + first_valuator];
}
}
/* Save the last calculated device axis value in the device
* valuator for next event */
pDev->valuator->axisVal[0] = x;
pDev->valuator->axisVal[1] = y;
/* dropy x/y (device coordinates) back into valuators for next event */
pDev->last.valuators[0] = x;
pDev->last.valuators[1] = y;
kbp = (deviceKeyButtonPointer *) events->event;
kbp->time = ms;
@ -862,8 +870,8 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
kbp->detail = pDev->button->map[buttons];
}
kbp->root_x = pDev->last.valuators[0];
kbp->root_y = pDev->last.valuators[1];
kbp->root_x = cx; /* root_x/y always in screen coords */
kbp->root_y = cy;
events++;
if (num_valuators) {

View File

@ -422,6 +422,8 @@ typedef struct _DeviceIntRec {
} u;
/* last valuator values recorded, not posted to client;
* for slave devices, valuators is in device coordinates
* for master devices, valuators is in screen coordinates
* see dix/getevents.c */
struct {
int valuators[MAX_VALUATORS];