aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/xfixes/cursor.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/xfixes/cursor.c')
-rw-r--r--xorg-server/xfixes/cursor.c145
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);
}