[PATCH] fixes: Pointer barriers
Adam Jackson
ajax at redhat.com
Wed Feb 9 18:30:08 PST 2011
This is pretty much a 'version 0' kind of thing, it looks right to me
but reviews strongly needed.
This assumes the calls to ConstrainCursorHarder actually happen,
obviously.
Signed-off-by: Adam Jackson <ajax at redhat.com>
---
include/protocol-versions.h | 2 +-
xfixes/cursor.c | 201 ++++++++++++++++++++++++++++++++++++++++++-
xfixes/xfixes.c | 22 +++--
xfixes/xfixesint.h | 16 ++++
4 files changed, 230 insertions(+), 11 deletions(-)
diff --git a/include/protocol-versions.h b/include/protocol-versions.h
index c8c7f5f..7be1af3 100644
--- a/include/protocol-versions.h
+++ b/include/protocol-versions.h
@@ -126,7 +126,7 @@
#define SERVER_XF86VIDMODE_MINOR_VERSION 2
/* Fixes */
-#define SERVER_XFIXES_MAJOR_VERSION 4
+#define SERVER_XFIXES_MAJOR_VERSION 5
#define SERVER_XFIXES_MINOR_VERSION 0
/* X Input */
diff --git a/xfixes/cursor.c b/xfixes/cursor.c
index 54e5d75..4d578ba 100644
--- a/xfixes/cursor.c
+++ b/xfixes/cursor.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2010 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -50,13 +51,16 @@
#include "cursorstr.h"
#include "dixevents.h"
#include "servermd.h"
+#include "mipointer.h"
#include "inputstr.h"
#include "windowstr.h"
#include "xace.h"
+#include "list.h"
static RESTYPE CursorClientType;
static RESTYPE CursorHideCountType;
static RESTYPE CursorWindowType;
+static RESTYPE PointerBarrierType;
static CursorPtr CursorCurrent[MAXDEVICES];
static DevPrivateKeyRec CursorScreenPrivateKeyRec;
@@ -107,6 +111,19 @@ typedef struct _CursorHideCountRec {
XID resource;
} CursorHideCountRec;
+struct PointerBarrier {
+ CARD16 x1, x2, y1, y2;
+ CARD32 directions;
+};
+
+typedef struct PointerBarrierClient *PointerBarrierClientPtr;
+
+struct PointerBarrierClient {
+ ScreenPtr screen;
+ struct PointerBarrier barrier;
+ PointerBarrierClientPtr next;
+};
+
/*
* Wrap DisplayCursor to catch cursor change events
*/
@@ -114,7 +131,9 @@ typedef struct _CursorHideCountRec {
typedef struct _CursorScreen {
DisplayCursorProcPtr DisplayCursor;
CloseScreenProcPtr CloseScreen;
+ ConstrainCursorHarderProcPtr ConstrainCursorHarder;
CursorHideCountPtr pCursorHideCounts;
+ PointerBarrierClientPtr barriers;
} CursorScreenRec, *CursorScreenPtr;
#define GetCursorScreen(s) ((CursorScreenPtr)dixLookupPrivate(&(s)->devPrivates, CursorScreenPrivateKey))
@@ -184,9 +203,11 @@ CursorCloseScreen (int index, ScreenPtr pScreen)
Bool ret;
CloseScreenProcPtr close_proc;
DisplayCursorProcPtr display_proc;
+ 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) (index, pScreen);
free(cs);
@@ -1029,6 +1050,180 @@ CursorFreeWindow (pointer data, XID id)
return 1;
}
+static void
+CursorConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int *x, int *y)
+{
+ CursorScreenPtr cs = GetCursorScreen(screen);
+ struct PointerBarrierClient *c;
+
+ if (cs->barriers) {
+ int ox, oy, direction = 0;
+
+ /* where are we coming from */
+ miPointerGetPosition(dev, &ox, &oy);
+
+ /* which way are we trying to go */
+ if (*x > ox)
+ direction |= BarrierPositiveX;
+ if (*x < ox)
+ direction |= BarrierNegativeX;
+ if (*y > oy)
+ direction |= BarrierPositiveY;
+ if (*y < oy)
+ direction |= BarrierNegativeY;
+
+ /* and is that acceptable */
+ for (c = cs->barriers; c; c = c->next) {
+ struct PointerBarrier *b = &c->barrier;
+ int d = b->directions & direction;
+
+ if (b->x1 == b->x2) {
+ if ((ox < b->x1 && *x > b->x1 && !(d & BarrierPositiveX)) ||
+ (ox > b->x1 && *x < b->x1 && !(d & BarrierNegativeX)))
+ *x = b->x1;
+ }
+ if (b->y1 == b->y2) {
+ if ((oy < b->y1 && *y > b->y1 && !(d & BarrierPositiveY)) ||
+ (oy > b->y1 && *y < b->y1 && !(d & BarrierNegativeY)))
+ *y = b->y1;
+ }
+ }
+ }
+
+ if (cs->ConstrainCursorHarder) {
+ screen->ConstrainCursorHarder = cs->ConstrainCursorHarder;
+ screen->ConstrainCursorHarder(dev, screen, x, y);
+ screen->ConstrainCursorHarder = CursorConstrainCursorHarder;
+ }
+}
+
+static struct PointerBarrierClient *
+CreatePointerBarrierClient(ScreenPtr screen, ClientPtr client,
+ xXFixesCreatePointerBarrierReq *stuff)
+{
+ CursorScreenPtr cs = GetCursorScreen(screen);
+ struct PointerBarrierClient *ret = malloc(sizeof(*ret));
+
+ if (ret) {
+ ret->screen = screen;
+ ret->barrier.x1 = stuff->x1;
+ ret->barrier.x2 = stuff->x2;
+ ret->barrier.y1 = stuff->y1;
+ ret->barrier.y2 = stuff->y2;
+ ret->barrier.directions = stuff->directions & 0x0f;
+ ret->next = cs->barriers;
+ cs->barriers = ret;
+ }
+
+ return ret;
+}
+
+int
+ProcXFixesCreatePointerBarrier (ClientPtr client)
+{
+ int err;
+ WindowPtr pWin;
+ struct PointerBarrierClient *barrier;
+ REQUEST (xXFixesCreatePointerBarrierReq);
+
+ REQUEST_SIZE_MATCH(xXFixesCreatePointerBarrierReq);
+ LEGAL_NEW_RESOURCE(stuff->barrier, client);
+
+ err = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
+ if (err != Success) {
+ client->errorValue = stuff->window;
+ return err;
+ }
+
+ if ((stuff->x1 != stuff->x2) || (stuff->y1 != stuff->y2))
+ return BadValue;
+
+ if (!(barrier = CreatePointerBarrierClient(pWin->drawable.pScreen,
+ client, stuff)))
+ return BadAlloc;
+
+ if (!AddResource(stuff->barrier, PointerBarrierType, &barrier->barrier))
+ return BadAlloc;
+
+ return Success;
+}
+
+int
+SProcXFixesCreatePointerBarrier (ClientPtr client)
+{
+ int n;
+ REQUEST(xXFixesCreatePointerBarrierReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXFixesCreatePointerBarrierReq);
+ swapl(&stuff->barrier, n);
+ swapl(&stuff->window, n);
+ swaps(&stuff->x1, n);
+ swaps(&stuff->y1, n);
+ swaps(&stuff->x2, n);
+ swaps(&stuff->y2, n);
+ swapl(&stuff->directions, n);
+ 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 */
+ if (cs->barriers == barrier)
+ cs->barriers = cs->barriers->next;
+ else for (b = cs->barriers; b; b = b->next) {
+ if (b->next == barrier) {
+ b->next = b->next->next;
+ 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;
+}
+
+int
+SProcXFixesDestroyPointerBarrier (ClientPtr client)
+{
+ int n;
+ REQUEST(xXFixesDestroyPointerBarrierReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXFixesDestroyPointerBarrierReq);
+ swapl(&stuff->barrier, n);
+ return ProcXFixesVector[stuff->xfixesReqType](client);
+}
+
Bool
XFixesCursorInit (void)
{
@@ -1050,6 +1245,7 @@ XFixesCursorInit (void)
return FALSE;
Wrap (cs, pScreen, CloseScreen, CursorCloseScreen);
Wrap (cs, pScreen, DisplayCursor, CursorDisplayCursor);
+ Wrap (cs, pScreen, ConstrainCursorHarder, CursorConstrainCursorHarder);
cs->pCursorHideCounts = NULL;
SetCursorScreen (pScreen, cs);
}
@@ -1059,7 +1255,10 @@ XFixesCursorInit (void)
"XFixesCursorHideCount");
CursorWindowType = CreateNewResourceType(CursorFreeWindow,
"XFixesCursorWindow");
+ PointerBarrierType = CreateNewResourceType(CursorFreeBarrier,
+ "XFixesPointerBarrier");
- return CursorClientType && CursorHideCountType && CursorWindowType;
+ return CursorClientType && CursorHideCountType && CursorWindowType &&
+ PointerBarrierType;
}
diff --git a/xfixes/xfixes.c b/xfixes/xfixes.c
index e8c7bf1..97f2ba6 100644
--- a/xfixes/xfixes.c
+++ b/xfixes/xfixes.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2010 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -47,10 +48,6 @@
#include "xfixesint.h"
#include "protocol-versions.h"
-/*
- * Must use these instead of the constants from xfixeswire.h. They advertise
- * what we implement, not what the protocol headers define.
- */
static unsigned char XFixesReqCode;
int XFixesEventBase;
@@ -97,11 +94,12 @@ ProcXFixesQueryVersion(ClientPtr client)
/* Major version controls available requests */
static const int version_requests[] = {
- X_XFixesQueryVersion, /* before client sends QueryVersion */
- X_XFixesGetCursorImage, /* Version 1 */
- X_XFixesChangeCursorByName, /* Version 2 */
- X_XFixesExpandRegion, /* Version 3 */
- X_XFixesShowCursor, /* Version 4 */
+ X_XFixesQueryVersion, /* before client sends QueryVersion */
+ X_XFixesGetCursorImage, /* Version 1 */
+ X_XFixesChangeCursorByName, /* Version 2 */
+ X_XFixesExpandRegion, /* Version 3 */
+ X_XFixesShowCursor, /* Version 4 */
+ X_XFixesCreatePointerBarrier, /* Version 5 */
};
#define NUM_VERSION_REQUESTS (sizeof (version_requests) / sizeof (version_requests[0]))
@@ -142,6 +140,9 @@ int (*ProcXFixesVector[XFixesNumberRequests])(ClientPtr) = {
/*************** Version 4 ****************/
ProcXFixesHideCursor,
ProcXFixesShowCursor,
+/*************** Version 5 ****************/
+ ProcXFixesCreatePointerBarrier,
+ ProcXFixesDestroyPointerBarrier,
};
static int
@@ -205,6 +206,9 @@ static int (*SProcXFixesVector[XFixesNumberRequests])(ClientPtr) = {
/*************** Version 4 ****************/
SProcXFixesHideCursor,
SProcXFixesShowCursor,
+/*************** Version 5 ****************/
+ SProcXFixesCreatePointerBarrier,
+ SProcXFixesDestroyPointerBarrier,
};
static int
diff --git a/xfixes/xfixesint.h b/xfixes/xfixesint.h
index d005369..6ba276e 100644
--- a/xfixes/xfixesint.h
+++ b/xfixes/xfixesint.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2010 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -278,6 +279,21 @@ ProcXFixesShowCursor (ClientPtr client);
int
SProcXFixesShowCursor (ClientPtr client);
+/* Version 5 */
+
+int
+ProcXFixesCreatePointerBarrier (ClientPtr client);
+
+int
+SProcXFixesCreatePointerBarrier (ClientPtr client);
+
+int
+ProcXFixesDestroyPointerBarrier (ClientPtr client);
+
+int
+SProcXFixesDestroyPointerBarrier (ClientPtr client);
+
+/* Xinerama */
extern int (*PanoramiXSaveXFixesVector[XFixesNumberRequests])(ClientPtr);
void PanoramiXFixesInit (void);
void PanoramiXFixesReset (void);
--
1.7.3.5
More information about the xorg-devel
mailing list