summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2011-11-02 21:20:07 -0700
committerKeith Packard <keithp@keithp.com>2011-11-02 21:20:07 -0700
commitd91aa0e6601bdf3e2cfa57b3412ab14ac486edc4 (patch)
tree7c18b19cfd5fb4d05f54549121fda33e1b9cd249
parent8df3a9ca5abbd56eb2013fa65250d21a8f18865b (diff)
parent401150d7dcad08be7c1f07e076f810cd61e2105c (diff)
Merge remote-tracking branch 'whot/two-screen-coordinates'
-rw-r--r--dix/devices.c10
-rw-r--r--dix/dispatch.c2
-rw-r--r--dix/getevents.c142
-rw-r--r--dix/inpututils.c24
-rw-r--r--hw/xfree86/common/xf86Cursor.c2
-rw-r--r--hw/xfree86/common/xf86RandR.c3
-rw-r--r--hw/xfree86/common/xf86Xinput.c19
-rw-r--r--hw/xfree86/common/xf86Xinput.h1
-rw-r--r--hw/xfree86/modes/xf86RandR12.c2
-rw-r--r--include/input.h1
-rw-r--r--include/inputstr.h5
-rw-r--r--include/scrnintstr.h4
-rw-r--r--mi/mipointer.c18
-rw-r--r--test/misc.c104
14 files changed, 270 insertions, 67 deletions
diff --git a/dix/devices.c b/dix/devices.c
index 673a360fb..da817a8af 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/dispatch.c b/dix/dispatch.c
index 2b6cb8287..6e3361573 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -3906,6 +3906,8 @@ AddScreen(
return -1;
}
+ update_desktop_dimensions();
+
dixRegisterScreenPrivateKey(&cursorScreenDevPriv, pScreen, PRIVATE_CURSOR, 0);
return i;
diff --git a/dix/getevents.c b/dix/getevents.c
index 4845a106c..df47b2b95 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;
@@ -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];
@@ -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++;
}
@@ -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,16 +768,18 @@ 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,
- 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),
+ scaled = valuator_mask_get_double(mask, 1) + scr->y;
+ scaled = rescaleValuatorAxis(scaled,
NULL, dev->valuator->axes + 1,
- scr->height);
+ 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,
- scr->width);
+ screenInfo.x, screenInfo.width);
*screeny = rescaleValuatorAxis(y, dev->valuator->axes + 1, NULL,
- 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,
- scr->width);
- if (tmpy != *screeny)
- y = rescaleValuatorAxis(*screeny, NULL, dev->valuator->axes + 1,
- 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/dix/inpututils.c b/dix/inpututils.c
index 5797f9256..c152b2d8b 100644
--- a/dix/inpututils.c
+++ b/dix/inpututils.c
@@ -665,6 +665,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 929f047cc..6f5d726f0 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 4663d0366..d0e47841e 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/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index ee705a4a8..c3ffc27d0 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -1349,25 +1349,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 189f7abaf..909fb57d6 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,
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index cb20d1c35..d5031a2f1 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 4eee47ce4..5dd5c1bcf 100644
--- a/include/input.h
+++ b/include/input.h
@@ -614,5 +614,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/inputstr.h b/include/inputstr.h
index 7a1554075..0a2128732 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/include/scrnintstr.h b/include/scrnintstr.h
index a9357e8a5..132a67193 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/mi/mipointer.c b/mi/mipointer.c
index 55e4081f2..998c86c15 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
diff --git a/test/misc.c b/test/misc.c
index 3d3b1a1e3..d98449ba0 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;
}