Make all conversion handling in GPE.

This isn't quite finished yet, but at least it gives us the ability to use a
tablet as a normal mouse - with all the scaling in place.

Signed-off-by: Peter Hutterer <peter@cs.unisa.edu.au>
This commit is contained in:
Magnus Vigerlöf 2008-05-17 19:24:00 +02:00 committed by Peter Hutterer
parent 74372fd004
commit 0f15875a27

View File

@ -155,6 +155,55 @@ CreateClassesChangedEvent(EventList* event,
dcce->length = (len - sizeof(xEvent))/4;
}
/**
* Rescale the coord between the two axis ranges.
*/
static int
rescaleValuatorAxis(int coord, int fmin, int fmax,
int tmin, int tmax, int smax)
{
if(fmin >= fmax) {
fmin = 0;
fmax = smax;
}
if(tmin >= tmax) {
tmin = 0;
tmax = smax;
}
if(fmin == tmin && fmax == tmax)
return coord;
return (int)(((float)(coord - fmin)) * (tmax - tmin + 1) /
(fmax - fmin + 1)) + tmin;
}
/**
* Update all coordinates when changing to a different SD
* to ensure that relative reporting will work as expected
* without loss of precision.
*/
static void
updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
{
ScreenPtr scr = miPointerGetScreen(pDev);
/* lastx/y is in screen coords and the actual position
* of the pointer */
pDev->lastx = master->lastx;
pDev->lasty = master->lasty;
/* the valuator axis is in device coords and holds the
* position of the pointer, but in device coords. */
if(pDev->valuator->numAxes > 0)
pDev->valuator->axisVal[0] = rescaleValuatorAxis(pDev->lastx, 0, scr->width,
pDev->valuator->axes[0].min_value,
pDev->valuator->axes[0].max_value, scr->width);
if(pDev->valuator->numAxes > 1)
pDev->valuator->axisVal[1] = rescaleValuatorAxis(pDev->lasty, 0, scr->height,
pDev->valuator->axes[1].min_value,
pDev->valuator->axes[1].max_value, scr->height);
/*TODO calculate the other axis as well based on info from the old slave-device */
}
/**
* Allocate the motion history buffer.
*/
@ -395,25 +444,23 @@ clipValuators(DeviceIntPtr pDev, int first_valuator, int num_valuators,
* Fills events with valuator events for pDev, as given by the other
* parameters.
*
* Note that we mis-use the sequence number to store the absolute bit.
*
* 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 EventList *
getValuatorEvents(EventList *events, DeviceIntPtr pDev, int absolute,
getValuatorEvents(EventList *events, DeviceIntPtr pDev,
int first_valuator, int num_valuators, int *valuators) {
deviceValuator *xv;
int i = 0, final_valuator = first_valuator + num_valuators;
int i;
for (i = first_valuator; i < final_valuator; i += 6, 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:
@ -425,13 +472,11 @@ getValuatorEvents(EventList *events, DeviceIntPtr pDev, int absolute,
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;
xv->sequenceNumber = (absolute) ? Absolute : Relative;
}
return events;
@ -576,8 +621,8 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
if (num_valuators) {
kbp->deviceid |= MORE_EVENTS;
clipValuators(pDev, first_valuator, num_valuators, valuators);
events = getValuatorEvents(events, pDev, FALSE /* relative */,
first_valuator, num_valuators, valuators);
events = getValuatorEvents(events, pDev, first_valuator,
num_valuators, valuators);
}
return numEvents;
@ -674,44 +719,28 @@ _X_EXPORT int
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;
int num_events = 1;
CARD32 ms = 0;
deviceKeyButtonPointer *kbp = NULL;
DeviceIntPtr master;
int x = 0, y = 0;
int x, y, cx, cy;
ScreenPtr scr = miPointerGetScreen(pDev);
/* Sanity checks. */
if (type != MotionNotify && type != ButtonPress && type != ButtonRelease)
return 0;
if ((type == ButtonPress || type == ButtonRelease) && !pDev->button)
if (type != MotionNotify && !pDev->button)
return 0;
/* FIXME: I guess it should, in theory, be possible to post button events
* from devices without valuators. */
if (!pDev->valuator)
/* This method require at least valuator 0&1 defined on the InputDevice */
if (!pDev->valuator || pDev->valuator->numAxes < 2)
return 0;
if (type == MotionNotify && num_valuators <= 0)
return 0;
ms = GetTimeInMillis();
num_events = 1;
master = pDev->u.master;
if (master && master->u.lastSlave != pDev)
{
CreateClassesChangedEvent(events, master, pDev);
pDev->lastx = master->lastx;
pDev->lasty = master->lasty;
master->u.lastSlave = pDev;
num_events++;
events++;
}
/* Do we need to send a DeviceValuator event? */
if (num_valuators) {
if ((((num_valuators - 1) / 6) + 1) > MAX_VALUATOR_EVENTS)
@ -719,28 +748,34 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
num_events += ((num_valuators - 1) / 6) + 1;
}
final_valuator = num_valuators + first_valuator;
/* You fail. */
if (first_valuator < 0 || final_valuator > pDev->valuator->numAxes)
if (first_valuator < 0 ||
(num_valuators + first_valuator) > pDev->valuator->numAxes)
return 0;
master = pDev->u.master;
if (master && master->u.lastSlave != pDev)
{
CreateClassesChangedEvent(events, master, pDev);
updateSlaveDeviceCoords(master, pDev);
master->u.lastSlave = pDev;
num_events++;
events++;
}
/* 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];
if (flags & POINTER_ABSOLUTE) {
if (num_valuators >= 1 && first_valuator == 0) {
if (num_valuators >= 1 && first_valuator == 0)
x = valuators[0];
}
else {
x = pDev->lastx;
}
if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) {
if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
y = valuators[1 - first_valuator];
}
else {
y = pDev->lasty;
}
/* Clip both x and y to the defined limits (usually co-ord space limit). */
clipAxis(pDev, 0, &x);
clipAxis(pDev, 1, &y);
}
else {
if (flags & POINTER_ACCELERATE)
@ -748,34 +783,69 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
valuators);
if (first_valuator == 0 && num_valuators >= 1)
x = pDev->lastx + valuators[0];
else
x = pDev->lastx;
x += valuators[0];
if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
y = pDev->lasty + valuators[1 - first_valuator];
else
y = pDev->lasty;
y += valuators[1 - first_valuator];
/* if not core -> clip both x and y to the defined limits (usually
* co-ord space limit). */
if(!pDev->coreEvents) {
clipAxis(pDev, 0, &x);
clipAxis(pDev, 1, &y);
}
}
/* Clip both x and y to the defined limits (usually co-ord space limit). */
clipAxis(pDev, 0, &x);
clipAxis(pDev, 1, &y);
/* scale x&y to screen */
pDev->lastx = cx = rescaleValuatorAxis(x, pDev->valuator->axes[0].min_value,
pDev->valuator->axes[0].max_value,
0, scr->width, scr->width);
pDev->lasty = cy = rescaleValuatorAxis(y, pDev->valuator->axes[1].min_value,
pDev->valuator->axes[1].max_value,
0, scr->height, scr->height);
/* 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);
miPointerSetPosition(pDev, &pDev->lastx, &pDev->lasty, ms);
scr = miPointerGetScreen(pDev);
if(cx != pDev->lastx)
x = rescaleValuatorAxis(pDev->lastx, 0, scr->width,
pDev->valuator->axes[0].min_value,
pDev->valuator->axes[0].max_value,
scr->width);
if(cy != pDev->lasty)
y = rescaleValuatorAxis(pDev->lasty, 0, scr->height,
pDev->valuator->axes[1].min_value,
pDev->valuator->axes[1].max_value,
scr->height);
updateMotionHistory(pDev, ms, first_valuator, num_valuators, valuators);
pDev->lastx = x;
pDev->lasty = y;
if (master)
{
master->lastx = x;
master->lasty = y;
if (master) {
master->lastx = pDev->lastx;
master->lasty = pDev->lasty;
}
/* update the contents of the valuators based on the mode of the InputDevice */
if(1) { /*TODO Absolute mode */
/* Update the valuators with the true value sent to the client
* (only absolute mode on the InputDevice) */
if (first_valuator == 0 && num_valuators >= 1)
pDev->valuator->axisVal[0] = x;
if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
pDev->valuator->axisVal[1] = y;
} else {/* Relative mode */
/* If driver reported in absolute, calculate the relative valuator
* values as a delta from the old absolute values of the valuator
* values. If relative report, keep it as-is.*/
/*TODO*/
}
/* Save the last calculated device axis value in the device
* valuator for next event */
pDev->valuator->axisVal[0] = x;
pDev->valuator->axisVal[1] = y;
kbp = (deviceKeyButtonPointer *) events->event;
kbp->time = ms;
kbp->deviceid = pDev->id;
@ -791,15 +861,15 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
kbp->detail = pDev->button->map[buttons];
}
kbp->root_x = x;
kbp->root_y = y;
kbp->root_x = pDev->lastx;
kbp->root_y = pDev->lasty;
events++;
if (num_valuators) {
kbp->deviceid |= MORE_EVENTS;
clipValuators(pDev, first_valuator, num_valuators, valuators);
events = getValuatorEvents(events, pDev, (flags & POINTER_ABSOLUTE),
first_valuator, num_valuators, valuators);
events = getValuatorEvents(events, pDev, first_valuator,
num_valuators, valuators);
}
return num_events;
@ -824,10 +894,8 @@ GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
/* 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;
@ -847,11 +915,8 @@ GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
if (master && master->u.lastSlave != pDev)
{
CreateClassesChangedEvent(events, master, pDev);
pDev->lastx = master->lastx;
pDev->lasty = master->lasty;
updateSlaveDeviceCoords(master, pDev);
master->u.lastSlave = pDev;
num_events++;
events++;
}
@ -866,8 +931,8 @@ GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
kbp->deviceid |= MORE_EVENTS;
events++;
clipValuators(pDev, first_valuator, num_valuators, valuators);
events = getValuatorEvents(events, pDev, False /* relative */,
first_valuator, num_valuators, valuators);
events = getValuatorEvents(events, pDev, first_valuator,
num_valuators, valuators);
}
return num_events;