[PATCH 8/8] input: switch miPointerSetPosition to expect desktop-wide coordinates.

Peter Hutterer peter.hutterer at who-t.net
Thu Sep 8 21:20:53 PDT 2011


miPointerSetPosition traditionally took coordinates on a per-screen basis,
triggering a screen switch when these went out-of-bounds. Change it to take
desktop-coordinates instead and trigger screen switches when these coordinates
are not on the current screen.

This unifies the pointer behaviour of single ScreenRec multihead and
multiple ScreenRecs multihead in that the cursor by default moves about the
whole screen rather than be confined to one single screen. The transformation
matrix may then be used to actually confine the cursor to the screen again.

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 dix/getevents.c |   27 +++++++++++++++++----------
 mi/mipointer.c  |   13 ++++++++++++-
 2 files changed, 29 insertions(+), 11 deletions(-)

diff --git a/dix/getevents.c b/dix/getevents.c
index a7624ef..83e61f0 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -786,11 +786,11 @@ positionSprite(DeviceIntPtr dev, int mode, ScreenPtr scr, ValuatorMask *mask,
     else
         y = dev->last.valuators[1];
 
-    /* scale x&y to screen */
+    /* scale x&y to desktop, in screen coord system */
     *screenx = rescaleValuatorAxis(x, dev->valuator->axes + 0, NULL,
-                                   scr->width);
+                                   screenInfo.width);
     *screeny = rescaleValuatorAxis(y, dev->valuator->axes + 1, NULL,
-                                   scr->height);
+                                   screenInfo.height);
 
     /* miPointerSetPosition takes care of crossing screens for us, as well as
      * clipping to the current screen.  In the event we actually change screen,
@@ -799,18 +799,19 @@ positionSprite(DeviceIntPtr dev, int mode, ScreenPtr scr, ValuatorMask *mask,
     isx = trunc(*screenx);
     isy = trunc(*screeny);
     miPointerSetPosition(dev, mode, &isx, &isy);
+
     scr = miPointerGetScreen(dev);
     if (isx != trunc(*screenx))
     {
         *screenx -= trunc(*screenx) - isx;
         x = rescaleValuatorAxis(*screenx, NULL, dev->valuator->axes + 0,
-                                scr->width);
+                                screenInfo.width);
     }
     if (isy != trunc(*screeny))
     {
         *screeny -= trunc(*screeny) - isy;
         y = rescaleValuatorAxis(*screeny, NULL, dev->valuator->axes + 1,
-                                scr->height);
+                                screenInfo.height);
     }
 
     /* Update the MD's co-ordinates, which are always in screen space. */
@@ -1121,22 +1122,27 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
 
     if (flags & POINTER_ABSOLUTE)
     {
-        if (flags & POINTER_SCREEN) /* valuators are in screen coords */
+        /* valuators are in screen coords but relative to the screen */
+        if (flags & POINTER_SCREEN)
         {
             double scaled;
 
             if (valuator_mask_isset(&mask, 0))
             {
-                scaled = rescaleValuatorAxis(valuator_mask_get_double(&mask, 0),
+                scaled = valuator_mask_get_double(&mask, 0);
+                scaled += scr->x; /* convert to desktop-wide coords */
+                scaled = rescaleValuatorAxis(scaled,
                                              NULL, pDev->valuator->axes + 0,
-                                             scr->width);
+                                             screenInfo.width);
                 valuator_mask_set_double(&mask, 0, scaled);
             }
             if (valuator_mask_isset(&mask, 1))
             {
-                scaled = rescaleValuatorAxis(valuator_mask_get_double(&mask, 1),
+                scaled = valuator_mask_get_double(&mask, 1);
+                scaled += scr->y; /* convert to desktop-wide coords */
+                scaled = rescaleValuatorAxis(scaled,
                                              NULL, pDev->valuator->axes + 1,
-                                             scr->height);
+                                             screenInfo.height);
                 valuator_mask_set_double(&mask, 1, scaled);
             }
         }
@@ -1152,6 +1158,7 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
     if ((flags & POINTER_NORAW) == 0)
         set_raw_valuators(raw, &mask, raw->valuators.data);
 
+    /* x/y are in desktop-wide coordinates */
     positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative, scr,
                    &mask, &screenx, &screeny);
     updateHistory(pDev, &mask, ms);
diff --git a/mi/mipointer.c b/mi/mipointer.c
index 670f63b..039e82c 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -580,6 +580,7 @@ miPointerSetPosition(DeviceIntPtr pDev, int mode, int *x, int *y)
     miPointerScreenPtr	pScreenPriv;
     ScreenPtr		pScreen;
     ScreenPtr		newScreen;
+    Bool		switch_screen = FALSE;
 
     miPointerPtr        pPointer; 
 
@@ -591,7 +592,17 @@ miPointerSetPosition(DeviceIntPtr pDev, int mode, int *x, int *y)
     if (!pScreen)
 	return;	    /* called before ready */
 
-    if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height)
+    /* x/y is still in desktop-wide coordinates here */
+    if (mode == Absolute) {
+        switch_screen = !point_on_screen(pScreen, *x, *y);
+
+	/* CursorOffScreen and Pointer->limits expect x/y to be relative to the screen. */
+	*x -= pScreen->x;
+	*y -= pScreen->y;
+    } else if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height)
+	switch_screen = TRUE;
+
+    if (switch_screen)
     {
 	pScreenPriv = GetScreenPrivate (pScreen);
 	if (!pPointer->confined)
-- 
1.7.6



More information about the xorg-devel mailing list