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
