diff options
Diffstat (limited to 'xorg-server/xfixes')
-rw-r--r-- | xorg-server/xfixes/cursor.c | 432 | ||||
-rw-r--r-- | xorg-server/xfixes/xfixes.h | 17 |
2 files changed, 5 insertions, 444 deletions
diff --git a/xorg-server/xfixes/cursor.c b/xorg-server/xfixes/cursor.c index ffee4d6ab..568e717fa 100644 --- a/xorg-server/xfixes/cursor.c +++ b/xorg-server/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/xorg-server/xfixes/xfixes.h b/xorg-server/xfixes/xfixes.h index 19af09f7d..98828710f 100644 --- a/xorg-server/xfixes/xfixes.h +++ b/xorg-server/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_ */ |