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

Peter Hutterer peter.hutterer at who-t.net
Thu Sep 1 20:59:12 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>
---
Hints appreciated on how to make get_desktop_dimensions() more efficient.
Presumably this could be precalculated on screen changes only but frankly I
have no idea where to hook in here.

 dix/getevents.c |   30 ++++++++++++++++++++++++++----
 mi/mipointer.c  |   13 ++++++++++++-
 2 files changed, 38 insertions(+), 5 deletions(-)

diff --git a/dix/getevents.c b/dix/getevents.c
index a0a26ce..7e9bd80 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -808,6 +808,21 @@ accelPointer(DeviceIntPtr dev, ValuatorMask* valuators, CARD32 ms)
         dev->valuator->accelScheme.AccelSchemeProc(dev, valuators, ms);
 }
 
+static void
+get_desktop_dimensions(int *width, int *height)
+{
+    int i;
+    int w = 0, h = 0;
+    for (i = 0; i < screenInfo.numScreens; i++) {
+        ScreenPtr screen = screenInfo.screens[i];
+        w = max(w, screen->x + screen->width);
+        h = max(h, screen->y + screen->height);
+    }
+
+    *width = w;
+    *height = h;
+}
+
 /**
  * If we have HW cursors, this actually moves the visible sprite. If not, we
  * just do all the screen crossing, etc.
@@ -837,11 +852,14 @@ positionSprite(DeviceIntPtr dev, int mode,
                ScreenPtr scr, int *screenx, int *screeny, float *screenx_frac, float *screeny_frac)
 {
     int old_screenx, old_screeny;
+    int w, h;
+
+    get_desktop_dimensions(&w, &h);
 
-    /* scale x&y to screen */
+    /* scale x&y to whole desktop */
     if (dev->valuator && dev->valuator->numAxes > 0) {
         *screenx = rescaleValuatorAxis(*x, x_frac, screenx_frac,
-                dev->valuator->axes + 0, NULL, scr->width);
+                dev->valuator->axes + 0, NULL, w);
     } else {
         *screenx = dev->last.valuators[0];
         *screenx_frac = dev->last.remainder[0];
@@ -849,7 +867,7 @@ positionSprite(DeviceIntPtr dev, int mode,
 
     if (dev->valuator && dev->valuator->numAxes > 1) {
         *screeny = rescaleValuatorAxis(*y, y_frac, screeny_frac,
-                dev->valuator->axes + 1, NULL, scr->height);
+                dev->valuator->axes + 1, NULL, h);
     } else {
         *screeny = dev->last.valuators[1];
         *screeny_frac = dev->last.remainder[1];
@@ -1213,7 +1231,8 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons
 
     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)
         {
             int scaled;
 
@@ -1223,6 +1242,7 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons
                                              0.0, &x_frac, NULL,
                                              pDev->valuator->axes + 0,
                                              scr->width);
+                scaled += scr->x; /* convert to desktop-wide coords */
                 valuator_mask_set(&mask, 0, scaled);
             }
             if (valuator_mask_isset(&mask, 1))
@@ -1231,6 +1251,7 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons
                                              0.0, &y_frac, NULL,
                                              pDev->valuator->axes + 1,
                                              scr->height);
+                scaled += scr->y; /* convert to desktop-wide coords */
                 valuator_mask_set(&mask, 1, scaled);
             }
         }
@@ -1251,6 +1272,7 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons
     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,
                    &x, &y, x_frac, y_frac, scr, &sx, &sy, &sx_frac, &sy_frac);
     updateHistory(pDev, &mask, ms);
diff --git a/mi/mipointer.c b/mi/mipointer.c
index 7680ca1..0e27808 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 global 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