barriers: Switch to an explicit hook for barrier constrainment

Rather than riding on the ConstrainCursorHarder hook, which has
several issues, move to an explicit hook, which will help us with
some RANDR interaction issues.

Signed-off-by: Jasper St. Pierre <jstpierre@mecheye.net>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Jasper St. Pierre 2012-11-24 19:39:47 -05:00 committed by Peter Hutterer
parent 2868a93945
commit 7e16dd3628
3 changed files with 37 additions and 40 deletions

View File

@ -74,16 +74,12 @@ struct PointerBarrierClient {
};
typedef struct _BarrierScreen {
CloseScreenProcPtr CloseScreen;
ConstrainCursorHarderProcPtr ConstrainCursorHarder;
struct xorg_list barriers;
} BarrierScreenRec, *BarrierScreenPtr;
#define GetBarrierScreen(s) ((BarrierScreenPtr)dixLookupPrivate(&(s)->devPrivates, BarrierScreenPrivateKey))
#define GetBarrierScreenIfSet(s) GetBarrierScreen(s)
#define SetBarrierScreen(s,p) dixSetPrivate(&(s)->devPrivates, BarrierScreenPrivateKey, p)
#define Wrap(as,s,elt,func) (((as)->elt = (s)->elt), (s)->elt = func)
#define Unwrap(as,s,elt,backup) (((backup) = (s)->elt), (s)->elt = (as)->elt)
static BOOL
barrier_is_horizontal(const struct PointerBarrier *barrier)
@ -306,22 +302,22 @@ barrier_clamp_to_barrier(struct PointerBarrier *barrier, int dir, int *x,
}
}
static void
BarrierConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode,
int *x, int *y)
void
input_constrain_cursor(DeviceIntPtr dev, ScreenPtr screen,
int current_x, int current_y,
int dest_x, int dest_y,
int *out_x, int *out_y)
{
/* Clamped coordinates here refer to screen edge clamping. */
BarrierScreenPtr cs = GetBarrierScreen(screen);
int x = dest_x,
y = dest_y;
if (!xorg_list_is_empty(&cs->barriers) && !IsFloating(dev) &&
mode == Relative) {
int ox, oy;
if (!xorg_list_is_empty(&cs->barriers) && !IsFloating(dev)) {
int dir;
int i;
struct PointerBarrier *nearest = NULL;
/* where are we coming from */
miPointerGetPosition(dev, &ox, &oy);
/* How this works:
* Given the origin and the movement vector, get the nearest barrier
* to the origin that is blocking the movement.
@ -329,32 +325,29 @@ BarrierConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode,
* Then, check from the clamped intersection to the original
* destination, again finding the nearest barrier and clamping.
*/
dir = barrier_get_direction(ox, oy, *x, *y);
dir = barrier_get_direction(current_x, current_y, x, y);
#define MAX_BARRIERS 2
for (i = 0; i < MAX_BARRIERS; i++) {
nearest = barrier_find_nearest(cs, dev, dir, ox, oy, *x, *y);
nearest = barrier_find_nearest(cs, dev, dir, current_x, current_y, x, y);
if (!nearest)
break;
barrier_clamp_to_barrier(nearest, dir, x, y);
barrier_clamp_to_barrier(nearest, dir, &x, &y);
if (barrier_is_vertical(nearest)) {
dir &= ~(BarrierNegativeX | BarrierPositiveX);
ox = *x;
current_x = x;
}
else if (barrier_is_horizontal(nearest)) {
dir &= ~(BarrierNegativeY | BarrierPositiveY);
oy = *y;
current_y = y;
}
}
}
if (cs->ConstrainCursorHarder) {
screen->ConstrainCursorHarder = cs->ConstrainCursorHarder;
screen->ConstrainCursorHarder(dev, screen, mode, x, y);
screen->ConstrainCursorHarder = BarrierConstrainCursorHarder;
}
*out_x = x;
*out_y = y;
}
static int
@ -493,21 +486,6 @@ XIDestroyPointerBarrier(ClientPtr client,
return Success;
}
static Bool
BarrierCloseScreen(ScreenPtr pScreen)
{
BarrierScreenPtr cs = GetBarrierScreen(pScreen);
Bool ret;
_X_UNUSED CloseScreenProcPtr close_proc;
_X_UNUSED ConstrainCursorHarderProcPtr constrain_proc;
Unwrap(cs, pScreen, CloseScreen, close_proc);
Unwrap(cs, pScreen, ConstrainCursorHarder, constrain_proc);
ret = (*pScreen->CloseScreen) (pScreen);
free(cs);
return ret;
}
Bool
XIBarrierInit(void)
{
@ -524,8 +502,6 @@ XIBarrierInit(void)
if (!cs)
return FALSE;
xorg_list_init(&cs->barriers);
Wrap(cs, pScreen, CloseScreen, BarrierCloseScreen);
Wrap(cs, pScreen, ConstrainCursorHarder, BarrierConstrainCursorHarder);
SetBarrierScreen(pScreen, cs);
}

View File

@ -678,4 +678,9 @@ extern _X_EXPORT void input_option_set_value(InputOption *opt,
extern _X_HIDDEN Bool point_on_screen(ScreenPtr pScreen, int x, int y);
extern _X_HIDDEN void update_desktop_dimensions(void);
extern _X_HIDDEN void input_constrain_cursor(DeviceIntPtr pDev, ScreenPtr screen,
int current_x, int current_y,
int dest_x, int dest_y,
int *out_x, int *out_y);
#endif /* INPUT_H */

View File

@ -588,6 +588,22 @@ miPointerSetPosition(DeviceIntPtr pDev, int mode, double *screenx,
x -= pScreen->x;
y -= pScreen->y;
if (mode == Relative) {
/* coordinates after clamped to a barrier */
int constrained_x, constrained_y;
int current_x, current_y; /* current position in per-screen coord */
current_x = MIPOINTER(pDev)->x - pScreen->y;
current_y = MIPOINTER(pDev)->y - pScreen->x;
input_constrain_cursor(pDev, pScreen,
current_x, current_y, x, y,
&constrained_x, &constrained_y);
x = constrained_x;
y = constrained_y;
}
if (switch_screen) {
pScreenPriv = GetScreenPrivate(pScreen);
if (!pPointer->confined) {