[RFC] dix: Re-introduce rescaling on motion events for extended event reporting
Magnus Vigerlöf
Magnus.Vigerlof at home.se
Sun Dec 16 09:53:46 PST 2007
Hello,
As xserver 1.4 removed the scaling callbacks for X&Y on extended
InputDevices [1], we've been forced to scale down the reported values
to the screen size. This means that we looses all the fine-grained
movement that we previously could report and for some applications this
means a loss of quality in the result for the end-user as the
applications now must work on more coarse-grained data.
Since the work to correct this is postponed for some time I propose
an interim solution where we get back the scaling so devices can
register any values on X&Y and not be tied to the changing values of
the screen size.
The patch below is tested with a Wacom tablet and works well with my
Volito 2 both as a pointer on the desktop and as a pressure-sensitive,
high-resolution pen in Gimp. At the same time my synaptic touchpad and
USB mouse worked as before.
This time I haven't introduced any interface changes. The values that
should be reported for the device are the same as in xserver 1.3,
including the max-values on X&Y. The drivers that has been adapted to
cope with the current situation will continue to work as the max-value
registered by the driver is used in the scaling.
The only worry I have with this patch is the check for if we should
scale or not. The devices I have in my system that shouldn't scale all
have '-1' as max and this is what's used to detect this situation. Is
that safe?
Comments are appreciated.
Cheers
Magnus
[1] https://bugs.freedesktop.org/show_bug.cgi?id=10324
---
dix/getevents.c | 54 +++++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 41 insertions(+), 13 deletions(-)
diff --git a/dix/getevents.c b/dix/getevents.c
index 6e840d4..d562e18 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -528,6 +528,7 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
DeviceIntPtr cp = inputInfo.pointer;
int x = 0, y = 0;
Bool coreOnly = (pDev == inputInfo.pointer);
+ ScreenPtr scr = miPointerGetScreen(pDev);
/* Sanity checks. */
if (type != MotionNotify && type != ButtonPress && type != ButtonRelease)
@@ -593,15 +594,33 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
valuators);
if (pDev->coreEvents) {
- if (first_valuator == 0 && num_valuators >= 1)
- x = cp->valuator->lastx + valuators[0];
+ /* 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 max = pDev->valuator->axes[0].max_value;
+ if(max > 0) {
+ x = pDev->valuator->lastx;
+ if((int)((float)(x)*scr->width/(max+1)) != cp->valuator->lastx)
+ x = (int)((float)(cp->valuator->lastx)*(max+1)/scr->width);
+ }
else
x = cp->valuator->lastx;
- if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
- y = cp->valuator->lasty + valuators[1 - first_valuator];
+ max = pDev->valuator->axes[1].max_value;
+ if(max > 0) {
+ y = pDev->valuator->lasty;
+ if((int)((float)(y)*scr->height/(max+1)) != cp->valuator->lasty)
+ y = (int)((float)(cp->valuator->lasty)*(max+1)/scr->height);
+ }
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 {
if (first_valuator == 0 && num_valuators >= 1)
@@ -620,11 +639,6 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
clipAxis(pDev, 0, &x);
clipAxis(pDev, 1, &y);
- /* 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);
-
/* Drop x and y back into the valuators list, if they were originally
* present. */
if (first_valuator == 0 && num_valuators >= 1)
@@ -634,12 +648,26 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
updateMotionHistory(pDev, ms, 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) {
+ if(pDev->valuator->axes[0].max_value > 0)
+ x = (int)((float)(x)*scr->width/(pDev->valuator->axes[0].max_value+1));
+ if(pDev->valuator->axes[1].max_value > 0)
+ y = (int)((float)(y)*scr->height/(pDev->valuator->axes[1].max_value+1));
+ }
+
+ /* 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;
/* for some reason inputInfo.pointer does not have coreEvents set */
if (coreOnly || pDev->coreEvents) {
@@ -677,8 +705,8 @@ GetPointerEvents(xEvent *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->valuator->lastx;
+ kbp->root_y = pDev->valuator->lasty;
events++;
if (num_valuators) {
--
1.5.2.5
More information about the xorg
mailing list