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 <[email protected]>
---
 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

_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to