diff options
Diffstat (limited to 'xorg-server/xfixes')
-rw-r--r-- | xorg-server/xfixes/cursor.c | 145 |
1 files changed, 110 insertions, 35 deletions
diff --git a/xorg-server/xfixes/cursor.c b/xorg-server/xfixes/cursor.c index 8f55c291e..206505d34 100644 --- a/xorg-server/xfixes/cursor.c +++ b/xorg-server/xfixes/cursor.c @@ -58,6 +58,7 @@ #include "windowstr.h" #include "xace.h" #include "list.h" +#include "exglobals.h" static RESTYPE CursorClientType; static RESTYPE CursorHideCountType; @@ -120,6 +121,8 @@ struct PointerBarrierClient { ScreenPtr screen; struct PointerBarrier barrier; struct xorg_list entry; + int num_devices; + int *device_ids; /* num_devices */ }; /* @@ -197,7 +200,7 @@ CursorCloseScreen(ScreenPtr pScreen) Bool ret; _X_UNUSED CloseScreenProcPtr close_proc; _X_UNUSED DisplayCursorProcPtr display_proc; - ConstrainCursorHarderProcPtr constrain_proc; + _X_UNUSED ConstrainCursorHarderProcPtr constrain_proc; Unwrap(cs, pScreen, CloseScreen, close_proc); Unwrap(cs, pScreen, DisplayCursor, display_proc); @@ -1133,6 +1136,31 @@ barrier_is_blocking(const struct PointerBarrier * barrier, 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. * @@ -1144,7 +1172,8 @@ barrier_is_blocking(const struct PointerBarrier * barrier, * @return The barrier nearest to the movement origin that blocks this movement. */ static struct PointerBarrier * -barrier_find_nearest(CursorScreenPtr cs, int dir, +barrier_find_nearest(CursorScreenPtr cs, DeviceIntPtr dev, + int dir, int x1, int y1, int x2, int y2) { struct PointerBarrierClient *c = NULL; @@ -1158,6 +1187,9 @@ barrier_find_nearest(CursorScreenPtr cs, int dir, 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; @@ -1205,6 +1237,7 @@ CursorConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode, mode == Relative) { int ox, oy; int dir; + int i; struct PointerBarrier *nearest = NULL; /* where are we coming from */ @@ -1219,8 +1252,12 @@ CursorConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode, */ dir = barrier_get_direction(ox, oy, *x, *y); - nearest = barrier_find_nearest(cs, dir, ox, oy, *x, *y); - if (nearest) { +#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)) { @@ -1231,11 +1268,6 @@ CursorConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode, dir &= ~(BarrierNegativeY | BarrierPositiveY); oy = *y; } - - nearest = barrier_find_nearest(cs, dir, ox, oy, *x, *y); - if (nearest) { - barrier_clamp_to_barrier(nearest, dir, x, y); - } } } @@ -1246,28 +1278,67 @@ CursorConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode, } } -static struct PointerBarrierClient * +static int CreatePointerBarrierClient(ScreenPtr screen, ClientPtr client, - xXFixesCreatePointerBarrierReq * stuff) + xXFixesCreatePointerBarrierReq * stuff, + PointerBarrierClientPtr *client_out) { CursorScreenPtr cs = GetCursorScreen(screen); - struct PointerBarrierClient *ret = malloc(sizeof(*ret)); - - if (ret) { - ret->screen = screen; - 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); + 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; } - return ret; + ret->screen = screen; + ret->num_devices = stuff->num_devices; + + 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 @@ -1280,7 +1351,7 @@ ProcXFixesCreatePointerBarrier(ClientPtr client) REQUEST(xXFixesCreatePointerBarrierReq); - REQUEST_SIZE_MATCH(xXFixesCreatePointerBarrierReq); + REQUEST_FIXED_SIZE(xXFixesCreatePointerBarrierReq, pad_to_int32(stuff->num_devices)); LEGAL_NEW_RESOURCE(stuff->barrier, client); err = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess); @@ -1289,10 +1360,6 @@ ProcXFixesCreatePointerBarrier(ClientPtr client) return err; } - /* This sure does need fixing. */ - if (stuff->num_devices) - return BadImplementation; - b.x1 = stuff->x1; b.x2 = stuff->x2; b.y1 = stuff->y1; @@ -1305,9 +1372,9 @@ ProcXFixesCreatePointerBarrier(ClientPtr client) if (barrier_is_horizontal(&b) && barrier_is_vertical(&b)) return BadValue; - if (!(barrier = CreatePointerBarrierClient(pWin->drawable.pScreen, - client, stuff))) - return BadAlloc; + if ((err = CreatePointerBarrierClient(pWin->drawable.pScreen, + client, stuff, &barrier))) + return err; if (!AddResource(stuff->barrier, PointerBarrierType, &barrier->barrier)) return BadAlloc; @@ -1319,9 +1386,13 @@ int SProcXFixesCreatePointerBarrier(ClientPtr client) { REQUEST(xXFixesCreatePointerBarrierReq); + int i; + CARD16 *in_devices = (CARD16 *) &stuff[1]; swaps(&stuff->length); - REQUEST_SIZE_MATCH(xXFixesCreatePointerBarrierReq); + swaps(&stuff->num_devices); + REQUEST_FIXED_SIZE(xXFixesCreatePointerBarrierReq, pad_to_int32(stuff->num_devices)); + swapl(&stuff->barrier); swapl(&stuff->window); swaps(&stuff->x1); @@ -1329,6 +1400,10 @@ SProcXFixesCreatePointerBarrier(ClientPtr client) swaps(&stuff->x2); swaps(&stuff->y2); swapl(&stuff->directions); + for (i = 0; i < stuff->num_devices; i++) { + swaps(in_devices + i); + } + return ProcXFixesVector[stuff->xfixesReqType] (client); } |