[PATCH v2 2/2] input: switch miPointerSetPosition to expect desktop-wide coordinates.
Peter Hutterer
peter.hutterer at who-t.net
Mon Sep 5 23:06:56 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>
---
Changes to v1:
- rescale POINTER_SCREEN coordinates to desktop-wide too. The previous code
had a bug where the scaled POINTER_SCREEN offset was not in the right
coordinate system.
dix/getevents.c | 43 +++++++++++++++++++++++++++++++++++--------
mi/mipointer.c | 13 ++++++++++++-
2 files changed, 47 insertions(+), 9 deletions(-)
diff --git a/dix/getevents.c b/dix/getevents.c
index a0a26ce..840cf18 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;
- /* scale x&y to screen */
+ get_desktop_dimensions(&w, &h);
+
+ /* 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,24 +1231,32 @@ 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;
+ int w, h;
+
+ get_desktop_dimensions(&w, &h);
if (valuator_mask_isset(&mask, 0))
{
- scaled = rescaleValuatorAxis(valuator_mask_get(&mask, 0),
+ scaled = valuator_mask_get(&mask, 0);
+ scaled += scr->x; /* convert to desktop-wide coords */
+ scaled = rescaleValuatorAxis(scaled,
0.0, &x_frac, NULL,
pDev->valuator->axes + 0,
- scr->width);
+ w);
valuator_mask_set(&mask, 0, scaled);
}
if (valuator_mask_isset(&mask, 1))
{
- scaled = rescaleValuatorAxis(valuator_mask_get(&mask, 1),
+ scaled = valuator_mask_get(&mask, 1);
+ scaled += scr->y; /* convert to desktop-wide coords */
+ scaled = rescaleValuatorAxis(scaled,
0.0, &y_frac, NULL,
pDev->valuator->axes + 1,
- scr->height);
+ h);
valuator_mask_set(&mask, 1, scaled);
}
}
@@ -1251,6 +1277,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