summaryrefslogtreecommitdiff
path: root/xfixes
diff options
context:
space:
mode:
Diffstat (limited to 'xfixes')
-rw-r--r--xfixes/cursor.c432
-rw-r--r--xfixes/xfixes.h17
2 files changed, 5 insertions, 444 deletions
diff --git a/xfixes/cursor.c b/xfixes/cursor.c
index ffee4d6ab..568e717fa 100644
--- a/xfixes/cursor.c
+++ b/xfixes/cursor.c
@@ -56,12 +56,11 @@
#include "windowstr.h"
#include "xace.h"
#include "list.h"
-#include "exglobals.h"
+#include "xibarriers.h"
static RESTYPE CursorClientType;
static RESTYPE CursorHideCountType;
static RESTYPE CursorWindowType;
-RESTYPE PointerBarrierType;
static CursorPtr CursorCurrent[MAXDEVICES];
static DevPrivateKeyRec CursorScreenPrivateKeyRec;
@@ -113,16 +112,6 @@ typedef struct _CursorHideCountRec {
XID resource;
} CursorHideCountRec;
-typedef struct PointerBarrierClient *PointerBarrierClientPtr;
-
-struct PointerBarrierClient {
- ScreenPtr screen;
- struct PointerBarrier barrier;
- struct xorg_list entry;
- int num_devices;
- int *device_ids; /* num_devices */
-};
-
/*
* Wrap DisplayCursor to catch cursor change events
*/
@@ -130,9 +119,7 @@ struct PointerBarrierClient {
typedef struct _CursorScreen {
DisplayCursorProcPtr DisplayCursor;
CloseScreenProcPtr CloseScreen;
- ConstrainCursorHarderProcPtr ConstrainCursorHarder;
CursorHideCountPtr pCursorHideCounts;
- struct xorg_list barriers;
} CursorScreenRec, *CursorScreenPtr;
#define GetCursorScreen(s) ((CursorScreenPtr)dixLookupPrivate(&(s)->devPrivates, CursorScreenPrivateKey))
@@ -199,11 +186,9 @@ CursorCloseScreen(ScreenPtr pScreen)
Bool ret;
_X_UNUSED CloseScreenProcPtr close_proc;
_X_UNUSED DisplayCursorProcPtr display_proc;
- _X_UNUSED ConstrainCursorHarderProcPtr constrain_proc;
Unwrap(cs, pScreen, CloseScreen, close_proc);
Unwrap(cs, pScreen, DisplayCursor, display_proc);
- Unwrap(cs, pScreen, ConstrainCursorHarder, constrain_proc);
deleteCursorHideCountsForScreen(pScreen);
ret = (*pScreen->CloseScreen) (pScreen);
free(cs);
@@ -1013,384 +998,15 @@ CursorFreeWindow(pointer data, XID id)
return 1;
}
-static BOOL
-barrier_is_horizontal(const struct PointerBarrier *barrier)
-{
- return barrier->y1 == barrier->y2;
-}
-
-static BOOL
-barrier_is_vertical(const struct PointerBarrier *barrier)
-{
- return barrier->x1 == barrier->x2;
-}
-
-/**
- * @return The set of barrier movement directions the movement vector
- * x1/y1 → x2/y2 represents.
- */
-int
-barrier_get_direction(int x1, int y1, int x2, int y2)
-{
- int direction = 0;
-
- /* which way are we trying to go */
- if (x2 > x1)
- direction |= BarrierPositiveX;
- if (x2 < x1)
- direction |= BarrierNegativeX;
- if (y2 > y1)
- direction |= BarrierPositiveY;
- if (y2 < y1)
- direction |= BarrierNegativeY;
-
- return direction;
-}
-
-/**
- * Test if the barrier may block movement in the direction defined by
- * x1/y1 → x2/y2. This function only tests whether the directions could be
- * blocked, it does not test if the barrier actually blocks the movement.
- *
- * @return TRUE if the barrier blocks the direction of movement or FALSE
- * otherwise.
- */
-BOOL
-barrier_is_blocking_direction(const struct PointerBarrier * barrier,
- int direction)
-{
- /* Barriers define which way is ok, not which way is blocking */
- return (barrier->directions & direction) != direction;
-}
-
-/**
- * Test if the movement vector x1/y1 → x2/y2 is intersecting with the
- * barrier. A movement vector with the startpoint or endpoint adjacent to
- * the barrier itself counts as intersecting.
- *
- * @param x1 X start coordinate of movement vector
- * @param y1 Y start coordinate of movement vector
- * @param x2 X end coordinate of movement vector
- * @param y2 Y end coordinate of movement vector
- * @param[out] distance The distance between the start point and the
- * intersection with the barrier (if applicable).
- * @return TRUE if the barrier intersects with the given vector
- */
-BOOL
-barrier_is_blocking(const struct PointerBarrier * barrier,
- int x1, int y1, int x2, int y2, double *distance)
-{
- BOOL rc = FALSE;
- float ua, ub, ud;
- int dir = barrier_get_direction(x1, y1, x2, y2);
-
- /* Algorithm below doesn't handle edge cases well, hence the extra
- * checks. */
- if (barrier_is_vertical(barrier)) {
- /* handle immediate barrier adjacency, moving away */
- if (dir & BarrierPositiveX && x1 == barrier->x1)
- return FALSE;
- if (dir & BarrierNegativeX && x1 == (barrier->x1 - 1))
- return FALSE;
- /* startpoint adjacent to barrier, moving towards -> block */
- if (dir & BarrierPositiveX && x1 == (barrier->x1 - 1) && y1 >= barrier->y1 && y1 <= barrier->y2) {
- *distance = 0;
- return TRUE;
- }
- if (dir & BarrierNegativeX && x1 == barrier->x1 && y1 >= barrier->y1 && y1 <= barrier->y2) {
- *distance = 0;
- return TRUE;
- }
- }
- else {
- /* handle immediate barrier adjacency, moving away */
- if (dir & BarrierPositiveY && y1 == barrier->y1)
- return FALSE;
- if (dir & BarrierNegativeY && y1 == (barrier->y1 - 1))
- return FALSE;
- /* startpoint adjacent to barrier, moving towards -> block */
- if (dir & BarrierPositiveY && y1 == (barrier->y1 - 1) && x1 >= barrier->x1 && x1 <= barrier->x2) {
- *distance = 0;
- return TRUE;
- }
- if (dir & BarrierNegativeY && y1 == barrier->y1 && x1 >= barrier->x1 && x1 <= barrier->x2) {
- *distance = 0;
- return TRUE;
- }
- }
-
- /* not an edge case, compute distance */
- ua = 0;
- ud = (barrier->y2 - barrier->y1) * (x2 - x1) - (barrier->x2 -
- barrier->x1) * (y2 - y1);
- if (ud != 0) {
- ua = ((barrier->x2 - barrier->x1) * (y1 - barrier->y1) -
- (barrier->y2 - barrier->y1) * (x1 - barrier->x1)) / ud;
- ub = ((x2 - x1) * (y1 - barrier->y1) -
- (y2 - y1) * (x1 - barrier->x1)) / ud;
- if (ua < 0 || ua > 1 || ub < 0 || ub > 1)
- ua = 0;
- }
-
- if (ua > 0 && ua <= 1) {
- double ix = barrier->x1 + ua * (barrier->x2 - barrier->x1);
- double iy = barrier->y1 + ua * (barrier->y2 - barrier->y1);
-
- *distance = sqrt(pow(x1 - ix, 2) + pow(y1 - iy, 2));
- rc = TRUE;
- }
-
- return rc;
-}
-
-static BOOL
-barrier_blocks_device(struct PointerBarrierClient *client,
- DeviceIntPtr dev)
-{
- int i;
- int master_id;
-
- /* Clients with no devices are treated as
- * if they specified XIAllDevices. */
- if (client->num_devices == 0)
- return TRUE;
-
- master_id = GetMaster(dev, POINTER_OR_FLOAT)->id;
-
- for (i = 0; i < client->num_devices; i++) {
- int device_id = client->device_ids[i];
- if (device_id == XIAllDevices ||
- device_id == XIAllMasterDevices ||
- device_id == master_id)
- return TRUE;
- }
-
- return FALSE;
-}
-
-/**
- * Find the nearest barrier that is blocking movement from x1/y1 to x2/y2.
- *
- * @param dir Only barriers blocking movement in direction dir are checked
- * @param x1 X start coordinate of movement vector
- * @param y1 Y start coordinate of movement vector
- * @param x2 X end coordinate of movement vector
- * @param y2 Y end coordinate of movement vector
- * @return The barrier nearest to the movement origin that blocks this movement.
- */
-static struct PointerBarrier *
-barrier_find_nearest(CursorScreenPtr cs, DeviceIntPtr dev,
- int dir,
- int x1, int y1, int x2, int y2)
-{
- struct PointerBarrierClient *c;
- struct PointerBarrier *nearest = NULL;
- double min_distance = INT_MAX; /* can't get higher than that in X anyway */
-
- xorg_list_for_each_entry(c, &cs->barriers, entry) {
- struct PointerBarrier *b = &c->barrier;
- double distance;
-
- if (!barrier_is_blocking_direction(b, dir))
- continue;
-
- if (!barrier_blocks_device(c, dev))
- continue;
-
- if (barrier_is_blocking(b, x1, y1, x2, y2, &distance)) {
- if (min_distance > distance) {
- min_distance = distance;
- nearest = b;
- }
- }
- }
-
- return nearest;
-}
-
-/**
- * Clamp to the given barrier given the movement direction specified in dir.
- *
- * @param barrier The barrier to clamp to
- * @param dir The movement direction
- * @param[out] x The clamped x coordinate.
- * @param[out] y The clamped x coordinate.
- */
-void
-barrier_clamp_to_barrier(struct PointerBarrier *barrier, int dir, int *x,
- int *y)
-{
- if (barrier_is_vertical(barrier)) {
- if ((dir & BarrierNegativeX) & ~barrier->directions)
- *x = barrier->x1;
- if ((dir & BarrierPositiveX) & ~barrier->directions)
- *x = barrier->x1 - 1;
- }
- if (barrier_is_horizontal(barrier)) {
- if ((dir & BarrierNegativeY) & ~barrier->directions)
- *y = barrier->y1;
- if ((dir & BarrierPositiveY) & ~barrier->directions)
- *y = barrier->y1 - 1;
- }
-}
-
-static void
-CursorConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode,
- int *x, int *y)
-{
- CursorScreenPtr cs = GetCursorScreen(screen);
-
- if (!xorg_list_is_empty(&cs->barriers) && !IsFloating(dev) &&
- mode == Relative) {
- int ox, oy;
- 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.
- * Clamp to that barrier.
- * 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);
-
-#define MAX_BARRIERS 2
- for (i = 0; i < MAX_BARRIERS; i++) {
- nearest = barrier_find_nearest(cs, dev, dir, ox, oy, *x, *y);
- if (!nearest)
- break;
-
- barrier_clamp_to_barrier(nearest, dir, x, y);
-
- if (barrier_is_vertical(nearest)) {
- dir &= ~(BarrierNegativeX | BarrierPositiveX);
- ox = *x;
- }
- else if (barrier_is_horizontal(nearest)) {
- dir &= ~(BarrierNegativeY | BarrierPositiveY);
- oy = *y;
- }
- }
- }
-
- if (cs->ConstrainCursorHarder) {
- screen->ConstrainCursorHarder = cs->ConstrainCursorHarder;
- screen->ConstrainCursorHarder(dev, screen, mode, x, y);
- screen->ConstrainCursorHarder = CursorConstrainCursorHarder;
- }
-}
-
-static int
-CreatePointerBarrierClient(ScreenPtr screen, ClientPtr client,
- xXFixesCreatePointerBarrierReq * stuff,
- PointerBarrierClientPtr *client_out)
-{
- CursorScreenPtr cs = GetCursorScreen(screen);
- int err;
- int size;
- int i;
- CARD16 *in_devices;
- struct PointerBarrierClient *ret;
-
- size = sizeof(*ret) + sizeof(int) * stuff->num_devices;
- ret = malloc(size);
-
- *client_out = NULL;
-
- if (!ret) {
- return BadAlloc;
- }
-
- ret->screen = screen;
- ret->num_devices = stuff->num_devices;
- if (ret->num_devices > 0)
- ret->device_ids = (int*)&ret[1];
- else
- ret->device_ids = NULL;
-
- in_devices = (CARD16 *) &stuff[1];
- for (i = 0; i < stuff->num_devices; i++) {
- int device_id = in_devices[i];
- DeviceIntPtr device;
-
- if ((err = dixLookupDevice (&device, device_id,
- client, DixReadAccess))) {
- client->errorValue = device_id;
- goto error;
- }
-
- if (!IsMaster (device)) {
- client->errorValue = device_id;
- err = BadDevice;
- goto error;
- }
-
- ret->device_ids[i] = device_id;
- }
-
- ret->barrier.x1 = min(stuff->x1, stuff->x2);
- ret->barrier.x2 = max(stuff->x1, stuff->x2);
- ret->barrier.y1 = min(stuff->y1, stuff->y2);
- ret->barrier.y2 = max(stuff->y1, stuff->y2);
- ret->barrier.directions = stuff->directions & 0x0f;
- if (barrier_is_horizontal(&ret->barrier))
- ret->barrier.directions &= ~(BarrierPositiveX | BarrierNegativeX);
- if (barrier_is_vertical(&ret->barrier))
- ret->barrier.directions &= ~(BarrierPositiveY | BarrierNegativeY);
- xorg_list_add(&ret->entry, &cs->barriers);
-
- *client_out = ret;
- return Success;
-
- error:
- free(ret);
- return err;
-}
-
int
ProcXFixesCreatePointerBarrier(ClientPtr client)
{
- int err;
- WindowPtr pWin;
- struct PointerBarrierClient *barrier;
- struct PointerBarrier b;
-
REQUEST(xXFixesCreatePointerBarrierReq);
REQUEST_FIXED_SIZE(xXFixesCreatePointerBarrierReq, pad_to_int32(stuff->num_devices));
LEGAL_NEW_RESOURCE(stuff->barrier, client);
- err = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
- if (err != Success) {
- client->errorValue = stuff->window;
- return err;
- }
-
- b.x1 = stuff->x1;
- b.x2 = stuff->x2;
- b.y1 = stuff->y1;
- b.y2 = stuff->y2;
-
- if (!barrier_is_horizontal(&b) && !barrier_is_vertical(&b))
- return BadValue;
-
- /* no 0-sized barriers */
- if (barrier_is_horizontal(&b) && barrier_is_vertical(&b))
- return BadValue;
-
- if ((err = CreatePointerBarrierClient(pWin->drawable.pScreen,
- client, stuff, &barrier)))
- return err;
-
- if (!AddResource(stuff->barrier, PointerBarrierType, &barrier->barrier))
- return BadAlloc;
-
- return Success;
+ return XICreatePointerBarrier(client, stuff);
}
int
@@ -1418,49 +1034,14 @@ SProcXFixesCreatePointerBarrier(ClientPtr client)
return ProcXFixesVector[stuff->xfixesReqType] (client);
}
-static int
-CursorFreeBarrier(void *data, XID id)
-{
- struct PointerBarrierClient *b = NULL, *barrier;
- ScreenPtr screen;
- CursorScreenPtr cs;
-
- barrier = container_of(data, struct PointerBarrierClient, barrier);
-
- screen = barrier->screen;
- cs = GetCursorScreen(screen);
-
- /* find and unlink from the screen private */
- xorg_list_for_each_entry(b, &cs->barriers, entry) {
- if (b == barrier) {
- xorg_list_del(&b->entry);
- break;
- }
- }
-
- free(barrier);
- return Success;
-}
-
int
ProcXFixesDestroyPointerBarrier(ClientPtr client)
{
- int err;
- void *barrier;
-
REQUEST(xXFixesDestroyPointerBarrierReq);
REQUEST_SIZE_MATCH(xXFixesDestroyPointerBarrierReq);
- err = dixLookupResourceByType((void **) &barrier, stuff->barrier,
- PointerBarrierType, client, DixDestroyAccess);
- if (err != Success) {
- client->errorValue = stuff->barrier;
- return err;
- }
-
- FreeResource(stuff->barrier, RT_NONE);
- return Success;
+ return XIDestroyPointerBarrier(client, stuff);
}
int
@@ -1492,10 +1073,8 @@ XFixesCursorInit(void)
cs = (CursorScreenPtr) calloc(1, sizeof(CursorScreenRec));
if (!cs)
return FALSE;
- xorg_list_init(&cs->barriers);
Wrap(cs, pScreen, CloseScreen, CursorCloseScreen);
Wrap(cs, pScreen, DisplayCursor, CursorDisplayCursor);
- Wrap(cs, pScreen, ConstrainCursorHarder, CursorConstrainCursorHarder);
cs->pCursorHideCounts = NULL;
SetCursorScreen(pScreen, cs);
}
@@ -1505,9 +1084,6 @@ XFixesCursorInit(void)
"XFixesCursorHideCount");
CursorWindowType = CreateNewResourceType(CursorFreeWindow,
"XFixesCursorWindow");
- PointerBarrierType = CreateNewResourceType(CursorFreeBarrier,
- "XFixesPointerBarrier");
- return CursorClientType && CursorHideCountType && CursorWindowType &&
- PointerBarrierType;
+ return CursorClientType && CursorHideCountType && CursorWindowType;
}
diff --git a/xfixes/xfixes.h b/xfixes/xfixes.h
index 19af09f7d..98828710f 100644
--- a/xfixes/xfixes.h
+++ b/xfixes/xfixes.h
@@ -30,7 +30,6 @@
#include "resource.h"
extern _X_EXPORT RESTYPE RegionResType;
-extern _X_EXPORT RESTYPE PointerBarrierType;
extern _X_EXPORT int XFixesErrorBase;
#define VERIFY_REGION(pRegion, rid, client, mode) \
@@ -52,20 +51,6 @@ extern _X_EXPORT int XFixesErrorBase;
extern _X_EXPORT RegionPtr
XFixesRegionCopy(RegionPtr pRegion);
-struct PointerBarrier {
- CARD16 x1, x2, y1, y2;
- CARD32 directions;
-};
-
-extern int
- barrier_get_direction(int, int, int, int);
-extern BOOL
-barrier_is_blocking(const struct PointerBarrier *, int, int, int, int,
- double *);
-extern BOOL barrier_is_blocking_direction(const struct PointerBarrier *, int);
-extern void
-
-barrier_clamp_to_barrier(struct PointerBarrier *barrier, int dir, int *x,
- int *y);
+#include "xibarriers.h"
#endif /* _XFIXES_H_ */