Merge remote-tracking branch 'whot/two-screen-coordinates'
This commit is contained in:
commit
d91aa0e660
|
@ -612,6 +612,7 @@ CorePointerProc(DeviceIntPtr pDev, int what)
|
||||||
int i = 0;
|
int i = 0;
|
||||||
Atom btn_labels[NBUTTONS] = {0};
|
Atom btn_labels[NBUTTONS] = {0};
|
||||||
Atom axes_labels[NAXES] = {0};
|
Atom axes_labels[NAXES] = {0};
|
||||||
|
ScreenPtr scr = screenInfo.screens[0];
|
||||||
|
|
||||||
switch (what) {
|
switch (what) {
|
||||||
case DEVICE_INIT:
|
case DEVICE_INIT:
|
||||||
|
@ -638,10 +639,11 @@ CorePointerProc(DeviceIntPtr pDev, int what)
|
||||||
pDev->name);
|
pDev->name);
|
||||||
return BadAlloc; /* IPDS only fails on allocs */
|
return BadAlloc; /* IPDS only fails on allocs */
|
||||||
}
|
}
|
||||||
pDev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2;
|
/* axisVal is per-screen, last.valuators is desktop-wide */
|
||||||
pDev->last.valuators[0] = pDev->valuator->axisVal[0];
|
pDev->valuator->axisVal[0] = scr->width / 2;
|
||||||
pDev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2;
|
pDev->last.valuators[0] = pDev->valuator->axisVal[0] + scr->x;
|
||||||
pDev->last.valuators[1] = pDev->valuator->axisVal[1];
|
pDev->valuator->axisVal[1] = scr->height / 2;
|
||||||
|
pDev->last.valuators[1] = pDev->valuator->axisVal[1] + scr->y;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEVICE_CLOSE:
|
case DEVICE_CLOSE:
|
||||||
|
|
|
@ -3906,6 +3906,8 @@ AddScreen(
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update_desktop_dimensions();
|
||||||
|
|
||||||
dixRegisterScreenPrivateKey(&cursorScreenDevPriv, pScreen, PRIVATE_CURSOR, 0);
|
dixRegisterScreenPrivateKey(&cursorScreenDevPriv, pScreen, PRIVATE_CURSOR, 0);
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
|
|
142
dix/getevents.c
142
dix/getevents.c
|
@ -257,10 +257,10 @@ CreateClassesChangedEvent(InternalEvent* event,
|
||||||
*/
|
*/
|
||||||
static double
|
static double
|
||||||
rescaleValuatorAxis(double coord, AxisInfoPtr from, AxisInfoPtr to,
|
rescaleValuatorAxis(double coord, AxisInfoPtr from, AxisInfoPtr to,
|
||||||
double defmax)
|
double defmin, double defmax)
|
||||||
{
|
{
|
||||||
double fmin = 0.0, fmax = defmax;
|
double fmin = defmin, fmax = defmax;
|
||||||
double tmin = 0.0, tmax = defmax;
|
double tmin = defmin, tmax = defmax;
|
||||||
|
|
||||||
if (from && from->min_value < from->max_value) {
|
if (from && from->min_value < from->max_value) {
|
||||||
fmin = from->min_value;
|
fmin = from->min_value;
|
||||||
|
@ -295,7 +295,7 @@ updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
|
||||||
int i;
|
int i;
|
||||||
DeviceIntPtr lastSlave;
|
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 */
|
* position of the pointer */
|
||||||
pDev->last.valuators[0] = master->last.valuators[0];
|
pDev->last.valuators[0] = master->last.valuators[0];
|
||||||
pDev->last.valuators[1] = master->last.valuators[1];
|
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],
|
pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0],
|
||||||
NULL,
|
NULL,
|
||||||
pDev->valuator->axes + 0,
|
pDev->valuator->axes + 0,
|
||||||
scr->width);
|
0, scr->width);
|
||||||
}
|
}
|
||||||
if(pDev->valuator->numAxes > 1)
|
if(pDev->valuator->numAxes > 1)
|
||||||
{
|
{
|
||||||
pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1],
|
pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1],
|
||||||
NULL,
|
NULL,
|
||||||
pDev->valuator->axes + 1,
|
pDev->valuator->axes + 1,
|
||||||
scr->height);
|
0, scr->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* calculate the other axis as well based on info from the old
|
/* 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];
|
double val = pDev->last.valuators[i];
|
||||||
val = rescaleValuatorAxis(val, lastSlave->valuator->axes + i,
|
val = rescaleValuatorAxis(val, lastSlave->valuator->axes + i,
|
||||||
pDev->valuator->axes + i, 0);
|
pDev->valuator->axes + i, 0, 0);
|
||||||
pDev->last.valuators[i] = val;
|
pDev->last.valuators[i] = val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -445,7 +445,7 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
|
||||||
/* scale to screen coords */
|
/* scale to screen coords */
|
||||||
to = &core_axis;
|
to = &core_axis;
|
||||||
to->max_value = pScreen->width;
|
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));
|
memcpy(corebuf, &coord, sizeof(INT16));
|
||||||
corebuf++;
|
corebuf++;
|
||||||
|
@ -456,7 +456,7 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
|
||||||
memcpy(&coord, icbuf++, sizeof(INT32));
|
memcpy(&coord, icbuf++, sizeof(INT32));
|
||||||
|
|
||||||
to->max_value = pScreen->height;
|
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));
|
memcpy(corebuf, &coord, sizeof(INT16));
|
||||||
|
|
||||||
} else if (IsMaster(pDev))
|
} else if (IsMaster(pDev))
|
||||||
|
@ -484,7 +484,7 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
|
||||||
from.max_value = pScreen->height;
|
from.max_value = pScreen->height;
|
||||||
|
|
||||||
/* scale from stored range into current range */
|
/* 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));
|
memcpy(ocbuf, &coord, sizeof(INT32));
|
||||||
ocbuf++;
|
ocbuf++;
|
||||||
}
|
}
|
||||||
|
@ -757,8 +757,8 @@ accelPointer(DeviceIntPtr dev, ValuatorMask* valuators, CARD32 ms)
|
||||||
* device's coordinate range.
|
* device's coordinate range.
|
||||||
*
|
*
|
||||||
* @param dev The device to scale for.
|
* @param dev The device to scale for.
|
||||||
* @param[in, out] mask The mask in sceen coordinates, modified in place to
|
* @param[in, out] mask The mask in desktop coordinates, modified in place
|
||||||
* contain device coordinate range.
|
* to contain device coordinate range.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
scale_from_screen(DeviceIntPtr dev, ValuatorMask *mask)
|
scale_from_screen(DeviceIntPtr dev, ValuatorMask *mask)
|
||||||
|
@ -768,16 +768,18 @@ scale_from_screen(DeviceIntPtr dev, ValuatorMask *mask)
|
||||||
|
|
||||||
if (valuator_mask_isset(mask, 0))
|
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,
|
NULL, dev->valuator->axes + 0,
|
||||||
scr->width);
|
0, scr->width);
|
||||||
valuator_mask_set_double(mask, 0, scaled);
|
valuator_mask_set_double(mask, 0, scaled);
|
||||||
}
|
}
|
||||||
if (valuator_mask_isset(mask, 1))
|
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,
|
NULL, dev->valuator->axes + 1,
|
||||||
scr->height);
|
0, scr->height);
|
||||||
valuator_mask_set_double(mask, 1, scaled);
|
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
|
* The coordinates provided are always absolute. The parameter mode
|
||||||
* specifies whether it was relative or absolute movement that landed us at
|
* 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 dev The device to be moved.
|
||||||
* @param mode Movement mode (Absolute or Relative)
|
* @param mode Movement mode (Absolute or Relative)
|
||||||
* @param mask Mask of axis values for this event
|
* @param[in,out] mask Mask of axis values for this event, returns the
|
||||||
* @param screenx Screen x coordinate the sprite is on after the update.
|
* per-screen device coordinates after confinement
|
||||||
* @param screeny Screen y coordinate the sprite is on after the update.
|
* @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
|
static ScreenPtr
|
||||||
positionSprite(DeviceIntPtr dev, int mode, ValuatorMask *mask,
|
positionSprite(DeviceIntPtr dev, int mode, ValuatorMask *mask,
|
||||||
|
double *devx, double *devy,
|
||||||
double *screenx, double *screeny)
|
double *screenx, double *screeny)
|
||||||
{
|
{
|
||||||
double x, y;
|
double x, y;
|
||||||
|
@ -821,16 +828,20 @@ positionSprite(DeviceIntPtr dev, int mode, ValuatorMask *mask,
|
||||||
else
|
else
|
||||||
y = dev->last.valuators[1];
|
y = dev->last.valuators[1];
|
||||||
|
|
||||||
/* scale x&y to screen */
|
/* scale x&y to desktop coordinates */
|
||||||
*screenx = rescaleValuatorAxis(x, dev->valuator->axes + 0, NULL,
|
*screenx = rescaleValuatorAxis(x, dev->valuator->axes + 0, NULL,
|
||||||
scr->width);
|
screenInfo.x, screenInfo.width);
|
||||||
*screeny = rescaleValuatorAxis(y, dev->valuator->axes + 1, NULL,
|
*screeny = rescaleValuatorAxis(y, dev->valuator->axes + 1, NULL,
|
||||||
scr->height);
|
screenInfo.y, screenInfo.height);
|
||||||
|
|
||||||
tmpx = *screenx;
|
tmpx = *screenx;
|
||||||
tmpy = *screeny;
|
tmpy = *screeny;
|
||||||
|
*devx = x;
|
||||||
|
*devy = y;
|
||||||
|
|
||||||
/* miPointerSetPosition takes care of crossing screens for us, as well as
|
/* 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);
|
scr = miPointerSetPosition(dev, mode, screenx, screeny);
|
||||||
|
|
||||||
/* If we were constrained, rescale x/y from the screen coordinates so
|
/* 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.
|
* crossing this doesn't matter much, the coords would be 0 or max.
|
||||||
*/
|
*/
|
||||||
if (tmpx != *screenx)
|
if (tmpx != *screenx)
|
||||||
x = rescaleValuatorAxis(*screenx, NULL, dev->valuator->axes + 0,
|
*devx = rescaleValuatorAxis(*screenx, NULL, dev->valuator->axes + 0,
|
||||||
scr->width);
|
screenInfo.x, screenInfo.width);
|
||||||
|
|
||||||
if (tmpy != *screeny)
|
if (tmpy != *screeny)
|
||||||
y = rescaleValuatorAxis(*screeny, NULL, dev->valuator->axes + 1,
|
*devy = rescaleValuatorAxis(*screeny, NULL, dev->valuator->axes + 1,
|
||||||
scr->height);
|
screenInfo.y, screenInfo.height);
|
||||||
|
|
||||||
|
/* Recalculate the per-screen device coordinates */
|
||||||
if (valuator_mask_isset(mask, 0))
|
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);
|
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);
|
valuator_mask_set_double(mask, 1, y);
|
||||||
|
}
|
||||||
|
|
||||||
return scr;
|
return scr;
|
||||||
}
|
}
|
||||||
|
@ -1105,6 +1123,38 @@ QueuePointerEvents(DeviceIntPtr device, int type,
|
||||||
*
|
*
|
||||||
* Should not be called by anyone other than GetPointerEvents.
|
* 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.
|
* @return the number of events written into events.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
|
@ -1115,8 +1165,10 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
|
||||||
int num_events = 1, i;
|
int num_events = 1, i;
|
||||||
DeviceEvent *event;
|
DeviceEvent *event;
|
||||||
RawDeviceEvent *raw;
|
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;
|
ValuatorMask mask;
|
||||||
|
ScreenPtr scr;
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
@ -1155,6 +1207,8 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
|
||||||
set_raw_valuators(raw, &mask, raw->valuators.data_raw);
|
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_ABSOLUTE)
|
||||||
{
|
{
|
||||||
if (flags & POINTER_SCREEN) /* valuators are in screen coords */
|
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);
|
moveRelative(pDev, &mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* valuators are in device coordinate system in absolute coordinates */
|
||||||
|
|
||||||
if ((flags & POINTER_NORAW) == 0)
|
if ((flags & POINTER_NORAW) == 0)
|
||||||
set_raw_valuators(raw, &mask, raw->valuators.data);
|
set_raw_valuators(raw, &mask, raw->valuators.data);
|
||||||
|
|
||||||
positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative,
|
scr = positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative,
|
||||||
&mask, &screenx, &screeny);
|
&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);
|
updateHistory(pDev, &mask, ms);
|
||||||
|
|
||||||
clipValuators(pDev, &mask);
|
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))
|
if (valuator_mask_isset(&mask, i))
|
||||||
pDev->last.valuators[i] = valuator_mask_get_double(&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)) {
|
if (!IsMaster(pDev) || !IsFloating(pDev)) {
|
||||||
DeviceIntPtr master = GetMaster(pDev, MASTER_POINTER);
|
DeviceIntPtr master = GetMaster(pDev, MASTER_POINTER);
|
||||||
master->last.valuators[0] = screenx;
|
master->last.valuators[0] = screenx;
|
||||||
|
@ -1209,8 +1275,8 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
|
||||||
event->detail.button = buttons;
|
event->detail.button = buttons;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* root_x and root_y must be in screen co-ordinates */
|
/* root_x and root_y must be in per-screen co-ordinates */
|
||||||
event_set_root_coordinates(event, screenx, screeny);
|
event_set_root_coordinates(event, screenx - scr->x, screeny - scr->y);
|
||||||
|
|
||||||
if (flags & POINTER_EMULATED) {
|
if (flags & POINTER_EMULATED) {
|
||||||
raw->flags = XIPointerEmulated;
|
raw->flags = XIPointerEmulated;
|
||||||
|
|
|
@ -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
|
* Delete the element with the key from the list, freeing all memory
|
||||||
* associated with the element..
|
* associated with the element..
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -838,6 +838,8 @@ xf86InitOrigins(void)
|
||||||
FillOutEdge(pLayout->down, pScreen->width);
|
FillOutEdge(pLayout->down, pScreen->width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update_desktop_dimensions();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -313,6 +313,9 @@ xf86RandRSetConfig (ScreenPtr pScreen,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
update_desktop_dimensions();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Move the cursor back where it belongs; SwitchMode repositions it
|
* Move the cursor back where it belongs; SwitchMode repositions it
|
||||||
* FIXME: duplicated code, see modes/xf86RandR12.c
|
* FIXME: duplicated code, see modes/xf86RandR12.c
|
||||||
|
|
|
@ -1349,25 +1349,6 @@ xf86ScaleAxis(int Cx,
|
||||||
return X;
|
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
|
Bool
|
||||||
xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval,
|
xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval,
|
||||||
int resolution, int min_res, int max_res, int mode)
|
int resolution, int min_res, int max_res, int mode)
|
||||||
|
|
|
@ -143,7 +143,6 @@ extern _X_EXPORT void xf86PostKeyboardEvent(DeviceIntPtr device, unsigned int ke
|
||||||
int is_down);
|
int is_down);
|
||||||
extern _X_EXPORT InputInfoPtr xf86FirstLocalDevice(void);
|
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 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 void xf86ProcessCommonOptions(InputInfoPtr pInfo, XF86OptionPtr options);
|
||||||
extern _X_EXPORT Bool xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval,
|
extern _X_EXPORT Bool xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval,
|
||||||
int maxval, int resolution, int min_res,
|
int maxval, int resolution, int min_res,
|
||||||
|
|
|
@ -736,6 +736,8 @@ xf86RandR12ScreenSetSize (ScreenPtr pScreen,
|
||||||
xf86SetViewport (pScreen, 0, 0);
|
xf86SetViewport (pScreen, 0, 0);
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
|
update_desktop_dimensions();
|
||||||
|
|
||||||
if (pRoot && pScrn->vtSema)
|
if (pRoot && pScrn->vtSema)
|
||||||
(*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE);
|
(*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE);
|
||||||
#if RANDR_12_INTERFACE
|
#if RANDR_12_INTERFACE
|
||||||
|
|
|
@ -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_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 Bool point_on_screen(ScreenPtr pScreen, int x, int y);
|
||||||
|
extern _X_HIDDEN void update_desktop_dimensions(void);
|
||||||
|
|
||||||
#endif /* INPUT_H */
|
#endif /* INPUT_H */
|
||||||
|
|
|
@ -534,8 +534,9 @@ typedef struct _DeviceIntRec {
|
||||||
DeviceIntPtr lastSlave; /* last slave device used */
|
DeviceIntPtr lastSlave; /* last slave device used */
|
||||||
|
|
||||||
/* last valuator values recorded, not posted to client;
|
/* last valuator values recorded, not posted to client;
|
||||||
* for slave devices, valuators is in device coordinates
|
* for slave devices, valuators is in device coordinates, mapped to the
|
||||||
* for master devices, valuators is in screen coordinates
|
* desktop
|
||||||
|
* for master devices, valuators is in desktop coordinates.
|
||||||
* see dix/getevents.c
|
* see dix/getevents.c
|
||||||
* remainder supports acceleration
|
* remainder supports acceleration
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -561,6 +561,10 @@ typedef struct _ScreenInfo {
|
||||||
formats[MAXFORMATS];
|
formats[MAXFORMATS];
|
||||||
int numScreens;
|
int numScreens;
|
||||||
ScreenPtr screens[MAXSCREENS];
|
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;
|
} ScreenInfo;
|
||||||
|
|
||||||
extern _X_EXPORT ScreenInfo screenInfo;
|
extern _X_EXPORT ScreenInfo screenInfo;
|
||||||
|
|
|
@ -569,8 +569,8 @@ miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen,
|
||||||
*
|
*
|
||||||
* @param pDev The device to move
|
* @param pDev The device to move
|
||||||
* @param mode Movement mode (Absolute or Relative)
|
* @param mode Movement mode (Absolute or Relative)
|
||||||
* @param[in,out] screenx The x coordinate in screen coordinates
|
* @param[in,out] screenx The x coordinate in desktop coordinates
|
||||||
* @param[in,out] screeny The y coordinate in screen coordinates
|
* @param[in,out] screeny The y coordinate in desktop coordinates
|
||||||
*/
|
*/
|
||||||
ScreenPtr
|
ScreenPtr
|
||||||
miPointerSetPosition(DeviceIntPtr pDev, int mode, double *screenx, double *screeny)
|
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 pScreen;
|
||||||
ScreenPtr newScreen;
|
ScreenPtr newScreen;
|
||||||
int x, y;
|
int x, y;
|
||||||
|
Bool switch_screen = FALSE;
|
||||||
|
|
||||||
miPointerPtr pPointer;
|
miPointerPtr pPointer;
|
||||||
|
|
||||||
|
@ -593,7 +594,14 @@ miPointerSetPosition(DeviceIntPtr pDev, int mode, double *screenx, double *scree
|
||||||
x = trunc(*screenx);
|
x = trunc(*screenx);
|
||||||
y = trunc(*screeny);
|
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);
|
pScreenPriv = GetScreenPrivate (pScreen);
|
||||||
if (!pPointer->confined)
|
if (!pPointer->confined)
|
||||||
|
@ -628,6 +636,10 @@ miPointerSetPosition(DeviceIntPtr pDev, int mode, double *screenx, double *scree
|
||||||
pPointer->pScreen != pScreen)
|
pPointer->pScreen != pScreen)
|
||||||
miPointerMoveNoEvent(pDev, pScreen, x, y);
|
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
|
/* In the event we actually change screen or we get confined, we just
|
||||||
* drop the float component on the floor
|
* drop the float component on the floor
|
||||||
* FIXME: only drop remainder for ConstrainCursorHarder, not for screen
|
* FIXME: only drop remainder for ConstrainCursorHarder, not for screen
|
||||||
|
|
104
test/misc.c
104
test/misc.c
|
@ -27,6 +27,9 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
#include "scrnintstr.h"
|
||||||
|
|
||||||
|
ScreenInfo screenInfo;
|
||||||
|
|
||||||
static void dix_version_compare(void)
|
static void dix_version_compare(void)
|
||||||
{
|
{
|
||||||
|
@ -54,9 +57,110 @@ static void dix_version_compare(void)
|
||||||
assert(rc < 0);
|
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)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
dix_version_compare();
|
dix_version_compare();
|
||||||
|
dix_update_desktop_dimensions();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue