xserver: Branch 'master' - 5 commits

Keith Packard keithp at kemper.freedesktop.org
Wed Nov 2 21:22:59 PDT 2011


 dix/devices.c                  |   10 +-
 dix/dispatch.c                 |    2 
 dix/getevents.c                |  142 ++++++++++++++++++++++++++++++-----------
 dix/inpututils.c               |   24 ++++++
 hw/xfree86/common/xf86Cursor.c |    2 
 hw/xfree86/common/xf86RandR.c  |    3 
 hw/xfree86/common/xf86Xinput.c |   19 -----
 hw/xfree86/common/xf86Xinput.h |    1 
 hw/xfree86/modes/xf86RandR12.c |    2 
 include/input.h                |    1 
 include/inputstr.h             |    5 -
 include/scrnintstr.h           |    4 +
 mi/mipointer.c                 |   18 ++++-
 test/misc.c                    |  104 ++++++++++++++++++++++++++++++
 14 files changed, 270 insertions(+), 67 deletions(-)

New commits:
commit d91aa0e6601bdf3e2cfa57b3412ab14ac486edc4
Merge: 8df3a9c... 401150d...
Author: Keith Packard <keithp at keithp.com>
Date:   Wed Nov 2 21:20:07 2011 -0700

    Merge remote-tracking branch 'whot/two-screen-coordinates'

commit 401150d7dcad08be7c1f07e076f810cd61e2105c
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Tue Oct 4 11:41:17 2011 +1000

    input: change pointer screen crossing behaviour for multiple ScreenRecs
    
    miPointerSetPosition traditionally took coordinates on a per-screen basis,
    triggering a screen switch when these went out-of-bounds. For absolute
    devices, this prevented screen crossing in the negative x/y direction.
    
    This patch changes the event generation patch to handle screen coordinates
    in a desktop range (i.e. all screens together). Screen switches are
    triggered 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.
    
    Note: fill_pointer_events has to deal with several different coordinate
    systems. Make sure you read the comment before trying to understand the code.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/dix/devices.c b/dix/devices.c
index 64557aa..7879405 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -612,6 +612,7 @@ CorePointerProc(DeviceIntPtr pDev, int what)
     int i = 0;
     Atom btn_labels[NBUTTONS] = {0};
     Atom axes_labels[NAXES] = {0};
+    ScreenPtr scr = screenInfo.screens[0];
 
     switch (what) {
     case DEVICE_INIT:
@@ -638,10 +639,11 @@ CorePointerProc(DeviceIntPtr pDev, int what)
                    pDev->name);
             return BadAlloc; /* IPDS only fails on allocs */
         }
-        pDev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2;
-        pDev->last.valuators[0] = pDev->valuator->axisVal[0];
-        pDev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2;
-        pDev->last.valuators[1] = pDev->valuator->axisVal[1];
+        /* axisVal is per-screen, last.valuators is desktop-wide */
+        pDev->valuator->axisVal[0] = scr->width / 2;
+        pDev->last.valuators[0] = pDev->valuator->axisVal[0] + scr->x;
+        pDev->valuator->axisVal[1] = scr->height / 2;
+        pDev->last.valuators[1] = pDev->valuator->axisVal[1] + scr->y;
         break;
 
     case DEVICE_CLOSE:
diff --git a/dix/getevents.c b/dix/getevents.c
index 548cc8b..cd6260b 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -295,7 +295,7 @@ updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
     int i;
     DeviceIntPtr lastSlave;
 
-    /* master->last.valuators[0]/[1] is in screen coords and the actual
+    /* master->last.valuators[0]/[1] is in desktop-wide coords and the actual
      * position of the pointer */
     pDev->last.valuators[0] = master->last.valuators[0];
     pDev->last.valuators[1] = master->last.valuators[1];
@@ -757,8 +757,8 @@ accelPointer(DeviceIntPtr dev, ValuatorMask* valuators, CARD32 ms)
  * device's coordinate range.
  *
  * @param dev The device to scale for.
- * @param[in, out] mask The mask in sceen coordinates, modified in place to
- * contain device coordinate range.
+ * @param[in, out] mask The mask in desktop coordinates, modified in place
+ * to contain device coordinate range.
  */
 static void
 scale_from_screen(DeviceIntPtr dev, ValuatorMask *mask)
@@ -768,14 +768,16 @@ scale_from_screen(DeviceIntPtr dev, ValuatorMask *mask)
 
     if (valuator_mask_isset(mask, 0))
     {
-        scaled = rescaleValuatorAxis(valuator_mask_get_double(mask, 0),
+        scaled = valuator_mask_get_double(mask, 0) + scr->x;
+        scaled = rescaleValuatorAxis(scaled,
                                      NULL, dev->valuator->axes + 0,
                                      0, scr->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) + scr->y;
+        scaled = rescaleValuatorAxis(scaled,
                                      NULL, dev->valuator->axes + 1,
                                      0, scr->height);
         valuator_mask_set_double(mask, 1, scaled);
@@ -793,16 +795,21 @@ scale_from_screen(DeviceIntPtr dev, ValuatorMask *mask)
  *
  * The coordinates provided are always absolute. The parameter mode
  * specifies whether it was relative or absolute movement that landed us at
- * those coordinates.
+ * those coordinates. see fill_pointer_events for information on coordinate
+ * systems.
  *
  * @param dev The device to be moved.
  * @param mode Movement mode (Absolute or Relative)
- * @param mask Mask of axis values for this event
- * @param screenx Screen x coordinate the sprite is on after the update.
- * @param screeny Screen y coordinate the sprite is on after the update.
+ * @param[in,out] mask Mask of axis values for this event, returns the
+ * per-screen device coordinates after confinement
+ * @param[out] devx x desktop-wide coordinate in device coordinate system
+ * @param[out] devy y desktop-wide coordinate in device coordinate system
+ * @param[out] screenx x coordinate in desktop coordinate system
+ * @param[out] screeny y coordinate in desktop coordinate system
  */
 static ScreenPtr
 positionSprite(DeviceIntPtr dev, int mode, ValuatorMask *mask,
+               double *devx, double *devy,
                double *screenx, double *screeny)
 {
     double x, y;
@@ -821,16 +828,20 @@ positionSprite(DeviceIntPtr dev, int mode, ValuatorMask *mask,
     else
         y = dev->last.valuators[1];
 
-    /* scale x&y to screen */
+    /* scale x&y to desktop coordinates */
     *screenx = rescaleValuatorAxis(x, dev->valuator->axes + 0, NULL,
-                                   0, scr->width);
+                                   screenInfo.x, screenInfo.width);
     *screeny = rescaleValuatorAxis(y, dev->valuator->axes + 1, NULL,
-                                   0, scr->height);
+                                   screenInfo.y, screenInfo.height);
 
     tmpx = *screenx;
     tmpy = *screeny;
+    *devx = x;
+    *devy = y;
+
     /* miPointerSetPosition takes care of crossing screens for us, as well as
-     * clipping to the current screen. */
+     * clipping to the current screen. Coordinates returned are in desktop
+     * coord system */
     scr = miPointerSetPosition(dev, mode, screenx, screeny);
 
     /* If we were constrained, rescale x/y from the screen coordinates so
@@ -838,17 +849,24 @@ positionSprite(DeviceIntPtr dev, int mode, ValuatorMask *mask,
      * crossing this doesn't matter much, the coords would be 0 or max.
      */
     if (tmpx != *screenx)
-        x = rescaleValuatorAxis(*screenx, NULL, dev->valuator->axes + 0,
-                                0, scr->width);
-    if (tmpy != *screeny)
-        y = rescaleValuatorAxis(*screeny, NULL, dev->valuator->axes + 1,
-                                0, scr->height);
+        *devx = rescaleValuatorAxis(*screenx, NULL, dev->valuator->axes + 0,
+                                    screenInfo.x, screenInfo.width);
 
+    if (tmpy != *screeny)
+        *devy = rescaleValuatorAxis(*screeny, NULL, dev->valuator->axes + 1,
+                                    screenInfo.y, screenInfo.height);
 
-    if (valuator_mask_isset(mask, 0))
+    /* Recalculate the per-screen device coordinates */
+    if (valuator_mask_isset(mask, 0)) {
+        x = rescaleValuatorAxis(*screenx - scr->x, NULL, dev->valuator->axes + 0,
+                                0, scr->width);
         valuator_mask_set_double(mask, 0, x);
-    if (valuator_mask_isset(mask, 1))
+    }
+    if (valuator_mask_isset(mask, 1)) {
+        y = rescaleValuatorAxis(*screeny - scr->y, NULL, dev->valuator->axes + 1,
+                                0, scr->height);
         valuator_mask_set_double(mask, 1, y);
+    }
 
     return scr;
 }
@@ -1105,6 +1123,38 @@ QueuePointerEvents(DeviceIntPtr device, int type,
  *
  * Should not be called by anyone other than GetPointerEvents.
  *
+ * We use several different coordinate systems and need to switch between
+ * the three in fill_pointer_events, positionSprite and
+ * miPointerSetPosition. "desktop" refers to the width/height of all
+ * screenInfo.screens[n]->width/height added up. "screen" is ScreenRec, not
+ * output.
+ *
+ * Coordinate systems:
+ * - relative events have a mask_in in relative coordinates, mapped to
+ *   pixels. These events are mapped to the current position±delta.
+ * - absolute events have a mask_in in absolute device coordinates in
+ *   device-specific range. This range is mapped to the desktop.
+ * - POINTER_SCREEN absolute events (x86WarpCursor) are in screen-relative
+ *   screen coordinate range.
+ * - rootx/rooty in events must be be relative to the current screen's
+ *   origin (screen coordinate system)
+ * - XI2 valuators must be relative to the current screen's origin. On
+ *   the protocol the device min/max range maps to the current screen.
+ *
+ * For screen switching we need to get the desktop coordinates for each
+ * event, then map that to the respective position on each screen and
+ * position the cursor there.
+ * The device's last.valuator[] stores the last position in desktop-wide
+ * coordinates (in device range for slave devices, desktop range for master
+ * devices).
+ *
+ * screen-relative device coordinates requires scaling: A device coordinate
+ * x/y of range [n..m] that maps to positions Sx/Sy on Screen S must be
+ * rescaled to match Sx/Sy for [n..m]. In the simplest example, x of (m/2-1)
+ * is the last coordinate on the first screen and must be rescaled for the
+ * event to be m. XI2 clients that do their own coordinate mapping would
+ * otherwise interpret the position of the device elsewere to the cursor.
+ *
  * @return the number of events written into events.
  */
 static int
@@ -1115,8 +1165,10 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
     int num_events = 1, i;
     DeviceEvent *event;
     RawDeviceEvent *raw;
-    double screenx = 0.0, screeny = 0.0;
+    double screenx = 0.0, screeny = 0.0; /* desktop coordinate system */
+    double devx = 0.0, devy = 0.0; /* desktop-wide in device coords */
     ValuatorMask mask;
+    ScreenPtr scr;
 
     switch (type)
     {
@@ -1155,6 +1207,8 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
         set_raw_valuators(raw, &mask, raw->valuators.data_raw);
     }
 
+    /* valuators are in driver-native format (rel or abs) */
+
     if (flags & POINTER_ABSOLUTE)
     {
         if (flags & POINTER_SCREEN) /* valuators are in screen coords */
@@ -1168,22 +1222,34 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
         moveRelative(pDev, &mask);
     }
 
+    /* valuators are in device coordinate system in absolute coordinates */
+
     if ((flags & POINTER_NORAW) == 0)
         set_raw_valuators(raw, &mask, raw->valuators.data);
 
-    positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative,
-                   &mask, &screenx, &screeny);
+    scr = positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative,
+                         &mask, &devx, &devy, &screenx, &screeny);
+
+    /* screenx, screeny are in desktop coordinates,
+       mask is in device coordinates per-screen (the event data)
+       devx/devy is in device coordinate desktop-wide */
     updateHistory(pDev, &mask, ms);
 
     clipValuators(pDev, &mask);
 
-    for (i = 0; i < valuator_mask_size(&mask); i++)
+    /* store desktop-wide in last.valuators */
+    if (valuator_mask_isset(&mask, 0))
+        pDev->last.valuators[0] = devx;
+    if (valuator_mask_isset(&mask, 1))
+        pDev->last.valuators[1] = devy;
+
+    for (i = 2; i < valuator_mask_size(&mask); i++)
     {
         if (valuator_mask_isset(&mask, i))
             pDev->last.valuators[i] = valuator_mask_get_double(&mask, i);
     }
 
-    /* Update the MD's co-ordinates, which are always in screen space. */
+    /* Update the MD's co-ordinates, which are always in desktop space. */
     if (!IsMaster(pDev) || !IsFloating(pDev)) {
         DeviceIntPtr master = GetMaster(pDev, MASTER_POINTER);
         master->last.valuators[0] = screenx;
@@ -1209,8 +1275,8 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
         event->detail.button = buttons;
     }
 
-    /* root_x and root_y must be in screen co-ordinates */
-    event_set_root_coordinates(event, screenx, screeny);
+    /* root_x and root_y must be in per-screen co-ordinates */
+    event_set_root_coordinates(event, screenx - scr->x, screeny - scr->y);
 
     if (flags & POINTER_EMULATED) {
         raw->flags = XIPointerEmulated;
diff --git a/include/inputstr.h b/include/inputstr.h
index 9d4108e..1238f93 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -534,8 +534,9 @@ typedef struct _DeviceIntRec {
     DeviceIntPtr        lastSlave;  /* last slave device used */
 
     /* last valuator values recorded, not posted to client;
-     * for slave devices, valuators is in device coordinates
-     * for master devices, valuators is in screen coordinates
+     * for slave devices, valuators is in device coordinates, mapped to the
+     * desktop
+     * for master devices, valuators is in desktop coordinates.
      * see dix/getevents.c
      * remainder supports acceleration
      */
diff --git a/mi/mipointer.c b/mi/mipointer.c
index 55e4081..998c86c 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -569,8 +569,8 @@ miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen,
  *
  * @param pDev The device to move
  * @param mode Movement mode (Absolute or Relative)
- * @param[in,out] screenx The x coordinate in screen coordinates
- * @param[in,out] screeny The y coordinate in screen coordinates
+ * @param[in,out] screenx The x coordinate in desktop coordinates
+ * @param[in,out] screeny The y coordinate in desktop coordinates
  */
 ScreenPtr
 miPointerSetPosition(DeviceIntPtr pDev, int mode, double *screenx, double *screeny)
@@ -579,6 +579,7 @@ miPointerSetPosition(DeviceIntPtr pDev, int mode, double *screenx, double *scree
     ScreenPtr		pScreen;
     ScreenPtr		newScreen;
     int			x, y;
+    Bool		switch_screen = FALSE;
 
     miPointerPtr        pPointer; 
 
@@ -593,7 +594,14 @@ miPointerSetPosition(DeviceIntPtr pDev, int mode, double *screenx, double *scree
     x = trunc(*screenx);
     y = trunc(*screeny);
 
-    if (x < 0 || x >= pScreen->width || y < 0 || y >= pScreen->height)
+    switch_screen = !point_on_screen(pScreen, x, y);
+
+    /* Switch to per-screen coordinates for CursorOffScreen and
+     * Pointer->limits */
+    x -= pScreen->x;
+    y -= pScreen->y;
+
+    if (switch_screen)
     {
 	pScreenPriv = GetScreenPrivate (pScreen);
 	if (!pPointer->confined)
@@ -628,6 +636,10 @@ miPointerSetPosition(DeviceIntPtr pDev, int mode, double *screenx, double *scree
             pPointer->pScreen != pScreen)
         miPointerMoveNoEvent(pDev, pScreen, x, y);
 
+    /* Convert to desktop coordinates again */
+    x += pScreen->x;
+    y += pScreen->y;
+
     /* In the event we actually change screen or we get confined, we just
      * drop the float component on the floor
      * FIXME: only drop remainder for ConstrainCursorHarder, not for screen
commit 6bd0eff40fae1e5d8fed28751851eb5b932d131b
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Wed Oct 12 15:53:57 2011 +1000

    dix: extend rescaleValuatorAxis to take a minimum default
    
    Allow rescaling to non-zero based axis ranges as default (for when screen
    offsets are non-zero). Currently unused.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/dix/getevents.c b/dix/getevents.c
index 874189f..548cc8b 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -257,10 +257,10 @@ CreateClassesChangedEvent(InternalEvent* event,
  */
 static double
 rescaleValuatorAxis(double coord, AxisInfoPtr from, AxisInfoPtr to,
-                    double defmax)
+                    double defmin, double defmax)
 {
-    double fmin = 0.0, fmax = defmax;
-    double tmin = 0.0, tmax = defmax;
+    double fmin = defmin, fmax = defmax;
+    double tmin = defmin, tmax = defmax;
 
     if (from && from->min_value < from->max_value) {
         fmin = from->min_value;
@@ -309,14 +309,14 @@ updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
         pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0],
                                                       NULL,
                                                       pDev->valuator->axes + 0,
-                                                      scr->width);
+                                                      0, scr->width);
     }
     if(pDev->valuator->numAxes > 1)
     {
         pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1],
                                                       NULL,
                                                       pDev->valuator->axes + 1,
-                                                      scr->height);
+                                                      0, scr->height);
     }
 
     /* calculate the other axis as well based on info from the old
@@ -333,7 +333,7 @@ updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
             {
                 double val = pDev->last.valuators[i];
                 val = rescaleValuatorAxis(val, lastSlave->valuator->axes + i,
-                                          pDev->valuator->axes + i, 0);
+                                          pDev->valuator->axes + i, 0, 0);
                 pDev->last.valuators[i] = val;
             }
         }
@@ -445,7 +445,7 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
                 /* scale to screen coords */
                 to = &core_axis;
                 to->max_value = pScreen->width;
-                coord = rescaleValuatorAxis(coord, &from, to, pScreen->width);
+                coord = rescaleValuatorAxis(coord, &from, to, 0, pScreen->width);
 
                 memcpy(corebuf, &coord, sizeof(INT16));
                 corebuf++;
@@ -456,7 +456,7 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
                 memcpy(&coord, icbuf++, sizeof(INT32));
 
                 to->max_value = pScreen->height;
-                coord = rescaleValuatorAxis(coord, &from, to, pScreen->height);
+                coord = rescaleValuatorAxis(coord, &from, to, 0, pScreen->height);
                 memcpy(corebuf, &coord, sizeof(INT16));
 
             } else if (IsMaster(pDev))
@@ -484,7 +484,7 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
                         from.max_value = pScreen->height;
 
                     /* scale from stored range into current range */
-                    coord = rescaleValuatorAxis(coord, &from, to, 0);
+                    coord = rescaleValuatorAxis(coord, &from, to, 0, 0);
                     memcpy(ocbuf, &coord, sizeof(INT32));
                     ocbuf++;
                 }
@@ -770,14 +770,14 @@ scale_from_screen(DeviceIntPtr dev, ValuatorMask *mask)
     {
         scaled = rescaleValuatorAxis(valuator_mask_get_double(mask, 0),
                                      NULL, dev->valuator->axes + 0,
-                                     scr->width);
+                                     0, scr->width);
         valuator_mask_set_double(mask, 0, scaled);
     }
     if (valuator_mask_isset(mask, 1))
     {
         scaled = rescaleValuatorAxis(valuator_mask_get_double(mask, 1),
                                      NULL, dev->valuator->axes + 1,
-                                     scr->height);
+                                     0, scr->height);
         valuator_mask_set_double(mask, 1, scaled);
     }
 }
@@ -823,9 +823,9 @@ positionSprite(DeviceIntPtr dev, int mode, ValuatorMask *mask,
 
     /* scale x&y to screen */
     *screenx = rescaleValuatorAxis(x, dev->valuator->axes + 0, NULL,
-                                   scr->width);
+                                   0, scr->width);
     *screeny = rescaleValuatorAxis(y, dev->valuator->axes + 1, NULL,
-                                   scr->height);
+                                   0, scr->height);
 
     tmpx = *screenx;
     tmpy = *screeny;
@@ -839,10 +839,10 @@ positionSprite(DeviceIntPtr dev, int mode, ValuatorMask *mask,
      */
     if (tmpx != *screenx)
         x = rescaleValuatorAxis(*screenx, NULL, dev->valuator->axes + 0,
-                                scr->width);
+                                0, scr->width);
     if (tmpy != *screeny)
         y = rescaleValuatorAxis(*screeny, NULL, dev->valuator->axes + 1,
-                                scr->height);
+                                0, scr->height);
 
 
     if (valuator_mask_isset(mask, 0))
commit 8bebb4b4896d8b6ba3309b5b28fce883bb9f8a96
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Wed Sep 7 14:04:10 2011 +1000

    Store desktop dimensions in screenInfo.
    
    For Zaphod mode screen crossing handling we need to know the size of all
    screens together (i.e. the whole desktop size). Store that in the screenInfo to
    have it readily available in events.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/dix/dispatch.c b/dix/dispatch.c
index 43cb4d1..4a4481a 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -3898,6 +3898,8 @@ AddScreen(
 	return -1;
     }
 
+    update_desktop_dimensions();
+
     dixRegisterScreenPrivateKey(&cursorScreenDevPriv, pScreen, PRIVATE_CURSOR, 0);
 
     return i;
diff --git a/dix/inpututils.c b/dix/inpututils.c
index eeae2a7..8a83444 100644
--- a/dix/inpututils.c
+++ b/dix/inpututils.c
@@ -628,6 +628,30 @@ point_on_screen(ScreenPtr pScreen, int x, int y)
 }
 
 /**
+ * Update desktop dimensions on the screenInfo struct.
+ */
+void
+update_desktop_dimensions(void)
+{
+    int i;
+    int x1 = INT_MAX, y1 = INT_MAX; /* top-left */
+    int x2 = INT_MIN, y2 = INT_MIN; /* bottom-right */
+
+    for (i = 0; i < screenInfo.numScreens; i++) {
+        ScreenPtr screen = screenInfo.screens[i];
+        x1 = min(x1, screen->x);
+        y1 = min(y1, screen->y);
+        x2 = max(x2, screen->x + screen->width);
+        y2 = max(y2, screen->y + screen->height);
+    }
+
+    screenInfo.x = x1;
+    screenInfo.y = y1;
+    screenInfo.width = x2 - x1;
+    screenInfo.height = y2 - y1;
+}
+
+/*
  * Delete the element with the key from the list, freeing all memory
  * associated with the element..
  */
diff --git a/hw/xfree86/common/xf86Cursor.c b/hw/xfree86/common/xf86Cursor.c
index 929f047..6f5d726 100644
--- a/hw/xfree86/common/xf86Cursor.c
+++ b/hw/xfree86/common/xf86Cursor.c
@@ -838,6 +838,8 @@ xf86InitOrigins(void)
 		FillOutEdge(pLayout->down, pScreen->width);
 	}
     }
+
+    update_desktop_dimensions();
 }
 
 void
diff --git a/hw/xfree86/common/xf86RandR.c b/hw/xfree86/common/xf86RandR.c
index 4663d03..d0e4784 100644
--- a/hw/xfree86/common/xf86RandR.c
+++ b/hw/xfree86/common/xf86RandR.c
@@ -313,6 +313,9 @@ xf86RandRSetConfig (ScreenPtr		pScreen,
 	return FALSE;
     }
 
+
+    update_desktop_dimensions();
+
     /*
      * Move the cursor back where it belongs; SwitchMode repositions it
      * FIXME: duplicated code, see modes/xf86RandR12.c
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index cb20d1c..d5031a2 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -736,6 +736,8 @@ xf86RandR12ScreenSetSize (ScreenPtr	pScreen,
     xf86SetViewport (pScreen, 0, 0);
 
 finish:
+    update_desktop_dimensions();
+
     if (pRoot && pScrn->vtSema)
 	(*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE);
 #if RANDR_12_INTERFACE
diff --git a/include/input.h b/include/input.h
index b7de5ca..2544996 100644
--- a/include/input.h
+++ b/include/input.h
@@ -609,5 +609,6 @@ extern _X_EXPORT void input_option_set_key(InputOption *opt, const char* key);
 extern _X_EXPORT void input_option_set_value(InputOption *opt, const char* value);
 
 extern _X_HIDDEN Bool point_on_screen(ScreenPtr pScreen, int x, int y);
+extern _X_HIDDEN void update_desktop_dimensions(void);
 
 #endif /* INPUT_H */
diff --git a/include/scrnintstr.h b/include/scrnintstr.h
index a9357e8..132a671 100644
--- a/include/scrnintstr.h
+++ b/include/scrnintstr.h
@@ -561,6 +561,10 @@ typedef struct _ScreenInfo {
 		formats[MAXFORMATS];
     int		numScreens;
     ScreenPtr	screens[MAXSCREENS];
+    int         x;      /* origin */
+    int         y;      /* origin */
+    int		width;  /* total width of all screens together */
+    int		height; /* total height of all screens together */
 } ScreenInfo;
 
 extern _X_EXPORT ScreenInfo screenInfo;
diff --git a/test/misc.c b/test/misc.c
index 3d3b1a1..d98449b 100644
--- a/test/misc.c
+++ b/test/misc.c
@@ -27,6 +27,9 @@
 
 #include <stdint.h>
 #include "misc.h"
+#include "scrnintstr.h"
+
+ScreenInfo screenInfo;
 
 static void dix_version_compare(void)
 {
@@ -54,9 +57,110 @@ static void dix_version_compare(void)
     assert(rc < 0);
 }
 
+static void dix_update_desktop_dimensions(void)
+{
+    int i;
+    int x, y, w, h;
+    int w2, h2;
+    ScreenRec screens[MAXSCREENS];
+
+    for (i = 0; i < MAXSCREENS; i++)
+        screenInfo.screens[i] = &screens[i];
+
+    x = 0;
+    y = 0;
+    w = 10;
+    h = 5;
+    w2 = 35;
+    h2 = 25;
+
+#define assert_dimensions(_x, _y, _w, _h) \
+    update_desktop_dimensions();          \
+    printf("%d %d %d %d\n", screenInfo.x, screenInfo.y, screenInfo.width, screenInfo.height); \
+    assert(screenInfo.x == _x);           \
+    assert(screenInfo.y == _y);           \
+    assert(screenInfo.width == _w);       \
+    assert(screenInfo.height == _h);
+
+#define set_screen(idx, _x, _y, _w, _h)   \
+    screenInfo.screens[idx]->x = _x;      \
+    screenInfo.screens[idx]->y = _y;      \
+    screenInfo.screens[idx]->width = _w;  \
+    screenInfo.screens[idx]->height = _h; \
+
+    printf("Testing\n");
+
+    /* single screen */
+    screenInfo.numScreens = 1;
+    set_screen(0, x, y, w, h);
+    assert_dimensions(x, y, w, h);
+
+    /* dualhead rightof */
+    screenInfo.numScreens = 2;
+    set_screen(1, w, 0, w2, h2);
+    assert_dimensions(x, y, w + w2, h2);
+
+    /* dualhead belowof */
+    screenInfo.numScreens = 2;
+    set_screen(1, 0, h, w2, h2);
+    assert_dimensions(x, y, w2, h + h2);
+
+    /* triplehead L shape */
+    screenInfo.numScreens = 3;
+    set_screen(1, 0, h, w2, h2);
+    set_screen(2, w2, h2, w, h);
+    assert_dimensions(x, y, w + w2, h + h2);
+
+    /* quadhead 2x2 */
+    screenInfo.numScreens = 4;
+    set_screen(1, 0, h, w, h);
+    set_screen(2, w, h, w, h2);
+    set_screen(3, w, 0, w2, h);
+    assert_dimensions(x, y, w + w2, h + h2);
+
+    /* quadhead horiz line */
+    screenInfo.numScreens = 4;
+    set_screen(1, w, 0, w, h);
+    set_screen(2, 2 * w, 0, w, h);
+    set_screen(3, 3 * w, 0, w, h);
+    assert_dimensions(x, y, 4 * w, h);
+
+    /* quadhead vert line */
+    screenInfo.numScreens = 4;
+    set_screen(1, 0, h, w, h);
+    set_screen(2, 0, 2 * h, w, h);
+    set_screen(3, 0, 3 * h, w, h);
+    assert_dimensions(x, y, w, 4 * h);
+
+
+    /* x overlap */
+    screenInfo.numScreens = 2;
+    set_screen(0, 0, 0, w2, h2);
+    set_screen(1, w, 0, w2, h2);
+    assert_dimensions(x, y, w2 + w, h2);
+
+    /* y overlap */
+    screenInfo.numScreens = 2;
+    set_screen(0, 0, 0, w2, h2);
+    set_screen(1, 0, h, w2, h2);
+    assert_dimensions(x, y, w2, h2 + h);
+
+    /* negative origin */
+    screenInfo.numScreens = 1;
+    set_screen(0, -w2, -h2, w, h);
+    assert_dimensions(-w2, -h2, w, h);
+
+    /* dualhead negative origin, overlap */
+    screenInfo.numScreens = 2;
+    set_screen(0, -w2, -h2, w2, h2);
+    set_screen(1, -w, -h, w, h);
+    assert_dimensions(-w2, -h2, w2, h2);
+}
+
 int main(int argc, char** argv)
 {
     dix_version_compare();
+    dix_update_desktop_dimensions();
 
     return 0;
 }
commit 9cbfa4739a51e4cc6b8094833928bf8678f63876
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Tue Sep 6 15:55:19 2011 +1000

    xfree86: remove xf86XInputSetScreen
    
    Keeping track of which screen the pointer within the input driver is
    obsolete now. To bind to a screen, use the transformation matrix instead.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Jamey Sharp <jamey at minilop.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index ea1f927..ad18339 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -1345,25 +1345,6 @@ xf86ScaleAxis(int	Cx,
     return X;
 }
 
-/*
- * This function checks the given screen against the current screen and
- * makes changes if appropriate. It should be called from an XInput driver's
- * ReadInput function before any events are posted, if the device is screen
- * specific like a touch screen.
- */
-void
-xf86XInputSetScreen(InputInfoPtr	pInfo,
-		    int			screen_number,
-		    int			x,
-		    int			y)
-{
-    if (miPointerGetScreen(pInfo->dev) !=
-          screenInfo.screens[screen_number]) {
-	miPointerSetScreen(pInfo->dev, screen_number, x, y);
-    }
-}
-
-
 Bool
 xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval,
 			   int resolution, int min_res, int max_res, int mode)
diff --git a/hw/xfree86/common/xf86Xinput.h b/hw/xfree86/common/xf86Xinput.h
index 189f7ab..909fb57 100644
--- a/hw/xfree86/common/xf86Xinput.h
+++ b/hw/xfree86/common/xf86Xinput.h
@@ -143,7 +143,6 @@ extern _X_EXPORT void xf86PostKeyboardEvent(DeviceIntPtr device, unsigned int ke
                            int is_down);
 extern _X_EXPORT InputInfoPtr xf86FirstLocalDevice(void);
 extern _X_EXPORT int xf86ScaleAxis(int Cx, int to_max, int to_min, int from_max, int from_min);
-extern _X_EXPORT void xf86XInputSetScreen(InputInfoPtr pInfo, int screen_number, int x, int y);
 extern _X_EXPORT void xf86ProcessCommonOptions(InputInfoPtr pInfo, XF86OptionPtr options);
 extern _X_EXPORT Bool xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval,
 				int maxval, int resolution, int min_res,


More information about the xorg-commit mailing list