diff options
Diffstat (limited to 'nx-X11/programs/Xserver/xfixes/cursor.c.NX.original')
-rwxr-xr-x | nx-X11/programs/Xserver/xfixes/cursor.c.NX.original | 754 |
1 files changed, 754 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/xfixes/cursor.c.NX.original b/nx-X11/programs/Xserver/xfixes/cursor.c.NX.original new file mode 100755 index 000000000..f6895d193 --- /dev/null +++ b/nx-X11/programs/Xserver/xfixes/cursor.c.NX.original @@ -0,0 +1,754 @@ +/* + * $Id: cursor.c,v 1.6 2005/07/03 07:37:35 daniels Exp $ + * + * Copyright © 2002 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "xfixesint.h" +#include "scrnintstr.h" +#include "cursorstr.h" +#include "dixevents.h" +#include "servermd.h" +#include "inputstr.h" +#include "windowstr.h" + +static RESTYPE CursorClientType; +static RESTYPE CursorWindowType; +static int CursorScreenPrivateIndex = -1; +static int CursorGeneration; +static CursorPtr CursorCurrent; + +#define VERIFY_CURSOR(pCursor, cursor, client, access) { \ + pCursor = (CursorPtr)SecurityLookupIDByType((client), (cursor), \ + RT_CURSOR, (access)); \ + if (!pCursor) { \ + (client)->errorValue = (cursor); \ + return BadCursor; \ + } \ +} + +/* + * There is a global list of windows selecting for cursor events + */ + +typedef struct _CursorEvent *CursorEventPtr; + +typedef struct _CursorEvent { + CursorEventPtr next; + CARD32 eventMask; + ClientPtr pClient; + WindowPtr pWindow; + XID clientResource; +} CursorEventRec; + +static CursorEventPtr cursorEvents; + +/* + * Wrap DisplayCursor to catch cursor change events + */ + +typedef struct _CursorScreen { + DisplayCursorProcPtr DisplayCursor; + CloseScreenProcPtr CloseScreen; +} CursorScreenRec, *CursorScreenPtr; + +#define GetCursorScreen(s) ((CursorScreenPtr) ((s)->devPrivates[CursorScreenPrivateIndex].ptr)) +#define GetCursorScreenIfSet(s) ((CursorScreenPrivateIndex != -1) ? GetCursorScreen(s) : NULL) +#define SetCursorScreen(s,p) ((s)->devPrivates[CursorScreenPrivateIndex].ptr = (pointer) (p)) +#define Wrap(as,s,elt,func) (((as)->elt = (s)->elt), (s)->elt = func) +#define Unwrap(as,s,elt) ((s)->elt = (as)->elt) + +static Bool +CursorDisplayCursor (ScreenPtr pScreen, + CursorPtr pCursor) +{ + CursorScreenPtr cs = GetCursorScreen(pScreen); + Bool ret; + + Unwrap (cs, pScreen, DisplayCursor); + ret = (*pScreen->DisplayCursor) (pScreen, pCursor); + if (pCursor != CursorCurrent) + { + CursorEventPtr e; + + CursorCurrent = pCursor; + for (e = cursorEvents; e; e = e->next) + { + if ((e->eventMask & XFixesDisplayCursorNotifyMask) && + !e->pClient->clientGone) + { + xXFixesCursorNotifyEvent ev; + ev.type = XFixesEventBase + XFixesCursorNotify; + ev.subtype = XFixesDisplayCursorNotify; + ev.sequenceNumber = e->pClient->sequence; + ev.window = e->pWindow->drawable.id; + ev.cursorSerial = pCursor->serialNumber; + ev.timestamp = currentTime.milliseconds; + ev.name = pCursor->name; + WriteEventsToClient (e->pClient, 1, (xEvent *) &ev); + } + } + } + Wrap (cs, pScreen, DisplayCursor, CursorDisplayCursor); + return ret; +} + +static Bool +CursorCloseScreen (int index, ScreenPtr pScreen) +{ + CursorScreenPtr cs = GetCursorScreen (pScreen); + Bool ret; + + Unwrap (cs, pScreen, CloseScreen); + Unwrap (cs, pScreen, DisplayCursor); + ret = (*pScreen->CloseScreen) (index, pScreen); + xfree (cs); + if (index == 0) + CursorScreenPrivateIndex = -1; + return ret; +} + +#define CursorAllEvents (XFixesDisplayCursorNotifyMask) + +static int +XFixesSelectCursorInput (ClientPtr pClient, + WindowPtr pWindow, + CARD32 eventMask) +{ + CursorEventPtr *prev, e; + + for (prev = &cursorEvents; (e = *prev); prev = &e->next) + { + if (e->pClient == pClient && + e->pWindow == pWindow) + { + break; + } + } + if (!eventMask) + { + if (e) + { + FreeResource (e->clientResource, 0); + } + return Success; + } + if (!e) + { + e = (CursorEventPtr) xalloc (sizeof (CursorEventRec)); + if (!e) + return BadAlloc; + + e->next = 0; + e->pClient = pClient; + e->pWindow = pWindow; + e->clientResource = FakeClientID(pClient->index); + + /* + * Add a resource hanging from the window to + * catch window destroy + */ + if (!LookupIDByType(pWindow->drawable.id, CursorWindowType)) + if (!AddResource (pWindow->drawable.id, CursorWindowType, + (pointer) pWindow)) + { + xfree (e); + return BadAlloc; + } + + if (!AddResource (e->clientResource, CursorClientType, (pointer) e)) + return BadAlloc; + + *prev = e; + } + e->eventMask = eventMask; + return Success; +} + +int +ProcXFixesSelectCursorInput (ClientPtr client) +{ + REQUEST (xXFixesSelectCursorInputReq); + WindowPtr pWin; + + REQUEST_SIZE_MATCH (xXFixesSelectCursorInputReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + if (stuff->eventMask & ~CursorAllEvents) + { + client->errorValue = stuff->eventMask; + return( BadValue ); + } + return XFixesSelectCursorInput (client, pWin, stuff->eventMask); +} + +static int +GetBit (unsigned char *line, int x) +{ + unsigned char mask; + + if (screenInfo.bitmapBitOrder == LSBFirst) + mask = (1 << (x & 7)); + else + mask = (0x80 >> (x & 7)); + /* XXX assumes byte order is host byte order */ + line += (x >> 3); + if (*line & mask) + return 1; + return 0; +} + +int +SProcXFixesSelectCursorInput (ClientPtr client) +{ + register int n; + REQUEST(xXFixesSelectCursorInputReq); + + swaps(&stuff->length, n); + swapl(&stuff->window, n); + swapl(&stuff->eventMask, n); + return (*ProcXFixesVector[stuff->xfixesReqType]) (client); +} + +void +SXFixesCursorNotifyEvent (xXFixesCursorNotifyEvent *from, + xXFixesCursorNotifyEvent *to) +{ + to->type = from->type; + cpswaps (from->sequenceNumber, to->sequenceNumber); + cpswapl (from->window, to->window); + cpswapl (from->cursorSerial, to->cursorSerial); + cpswapl (from->timestamp, to->timestamp); + cpswapl (from->name, to->name); +} + +static void +CopyCursorToImage (CursorPtr pCursor, CARD32 *image) +{ + int width = pCursor->bits->width; + int height = pCursor->bits->height; + int npixels = width * height; + +#ifdef ARGB_CURSOR + if (pCursor->bits->argb) + memcpy (image, pCursor->bits->argb, npixels * sizeof (CARD32)); + else +#endif + { + unsigned char *srcLine = pCursor->bits->source; + unsigned char *mskLine = pCursor->bits->mask; + int stride = BitmapBytePad (width); + int x, y; + CARD32 fg, bg; + + fg = (0xff000000 | + ((pCursor->foreRed & 0xff00) << 8) | + (pCursor->foreGreen & 0xff00) | + (pCursor->foreBlue >> 8)); + bg = (0xff000000 | + ((pCursor->backRed & 0xff00) << 8) | + (pCursor->backGreen & 0xff00) | + (pCursor->backBlue >> 8)); + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + { + if (GetBit (mskLine, x)) + { + if (GetBit (srcLine, x)) + *image++ = fg; + else + *image++ = bg; + } + else + *image++ = 0; + } + srcLine += stride; + mskLine += stride; + } + } +} + +int +ProcXFixesGetCursorImage (ClientPtr client) +{ +/* REQUEST(xXFixesGetCursorImageReq); */ + xXFixesGetCursorImageReply *rep; + CursorPtr pCursor; + CARD32 *image; + int npixels; + int width, height; + int x, y; + + REQUEST_SIZE_MATCH(xXFixesGetCursorImageReq); + pCursor = CursorCurrent; + if (!pCursor) + return BadCursor; + GetSpritePosition (&x, &y); + width = pCursor->bits->width; + height = pCursor->bits->height; + npixels = width * height; + rep = xalloc (sizeof (xXFixesGetCursorImageReply) + + npixels * sizeof (CARD32)); + if (!rep) + return BadAlloc; + + rep->type = X_Reply; + rep->sequenceNumber = client->sequence; + rep->length = npixels; + rep->width = width; + rep->height = height; + rep->x = x; + rep->y = y; + rep->xhot = pCursor->bits->xhot; + rep->yhot = pCursor->bits->yhot; + rep->cursorSerial = pCursor->serialNumber; + + image = (CARD32 *) (rep + 1); + CopyCursorToImage (pCursor, image); + if (client->swapped) + { + int n; + swaps (&rep->sequenceNumber, n); + swapl (&rep->length, n); + swaps (&rep->x, n); + swaps (&rep->y, n); + swaps (&rep->width, n); + swaps (&rep->height, n); + swaps (&rep->xhot, n); + swaps (&rep->yhot, n); + swapl (&rep->cursorSerial, n); + SwapLongs (image, npixels); + } + (void) WriteToClient(client, sizeof (xXFixesGetCursorImageReply) + + (npixels << 2), (char *) rep); + xfree (rep); + return client->noClientException; +} + +int +SProcXFixesGetCursorImage (ClientPtr client) +{ + int n; + REQUEST(xXFixesGetCursorImageReq); + swaps (&stuff->length, n); + return (*ProcXFixesVector[stuff->xfixesReqType]) (client); +} + +int +ProcXFixesSetCursorName (ClientPtr client) +{ + CursorPtr pCursor; + char *tchar; + REQUEST(xXFixesSetCursorNameReq); + Atom atom; + + REQUEST_AT_LEAST_SIZE(xXFixesSetCursorNameReq); + VERIFY_CURSOR(pCursor, stuff->cursor, client, SecurityWriteAccess); + tchar = (char *) &stuff[1]; + atom = MakeAtom (tchar, stuff->nbytes, TRUE); + if (atom == BAD_RESOURCE) + return BadAlloc; + + pCursor->name = atom; + return(client->noClientException); +} + +int +SProcXFixesSetCursorName (ClientPtr client) +{ + int n; + REQUEST(xXFixesSetCursorNameReq); + + swaps (&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xXFixesSetCursorNameReq); + swapl (&stuff->cursor, n); + swaps (&stuff->nbytes, n); + return (*ProcXFixesVector[stuff->xfixesReqType]) (client); +} + +int +ProcXFixesGetCursorName (ClientPtr client) +{ + CursorPtr pCursor; + xXFixesGetCursorNameReply reply; + REQUEST(xXFixesGetCursorNameReq); + char *str; + int len; + + REQUEST_SIZE_MATCH(xXFixesGetCursorNameReq); + VERIFY_CURSOR(pCursor, stuff->cursor, client, SecurityReadAccess); + if (pCursor->name) + str = NameForAtom (pCursor->name); + else + str = ""; + len = strlen (str); + + reply.type = X_Reply; + reply.length = (len + 3) >> 2; + reply.sequenceNumber = client->sequence; + reply.atom = pCursor->name; + reply.nbytes = len; + if (client->swapped) + { + int n; + swaps (&reply.sequenceNumber, n); + swapl (&reply.length, n); + swapl (&reply.atom, n); + swaps (&reply.nbytes, n); + } + WriteReplyToClient(client, sizeof(xXFixesGetCursorNameReply), &reply); + (void)WriteToClient(client, len, str); + + return(client->noClientException); +} + +int +SProcXFixesGetCursorName (ClientPtr client) +{ + int n; + REQUEST(xXFixesSetCursorNameReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xXFixesGetCursorNameReq); + swapl (&stuff->cursor, n); + return (*ProcXFixesVector[stuff->xfixesReqType]) (client); +} + +int +ProcXFixesGetCursorImageAndName (ClientPtr client) +{ +/* REQUEST(xXFixesGetCursorImageAndNameReq); */ + xXFixesGetCursorImageAndNameReply *rep; + CursorPtr pCursor; + CARD32 *image; + int npixels; + char *name; + int nbytes, nbytesRound; + int width, height; + int x, y; + + REQUEST_SIZE_MATCH(xXFixesGetCursorImageAndNameReq); + pCursor = CursorCurrent; + if (!pCursor) + return BadCursor; + GetSpritePosition (&x, &y); + width = pCursor->bits->width; + height = pCursor->bits->height; + npixels = width * height; + name = pCursor->name ? NameForAtom (pCursor->name) : ""; + nbytes = strlen (name); + nbytesRound = (nbytes + 3) & ~3; + rep = xalloc (sizeof (xXFixesGetCursorImageAndNameReply) + + npixels * sizeof (CARD32) + nbytesRound); + if (!rep) + return BadAlloc; + + rep->type = X_Reply; + rep->sequenceNumber = client->sequence; + rep->length = npixels + (nbytesRound >> 2); + rep->width = width; + rep->height = height; + rep->x = x; + rep->y = y; + rep->xhot = pCursor->bits->xhot; + rep->yhot = pCursor->bits->yhot; + rep->cursorSerial = pCursor->serialNumber; + rep->cursorName = pCursor->name; + rep->nbytes = nbytes; + + image = (CARD32 *) (rep + 1); + CopyCursorToImage (pCursor, image); + memcpy ((image + npixels), name, nbytes); + if (client->swapped) + { + int n; + swaps (&rep->sequenceNumber, n); + swapl (&rep->length, n); + swaps (&rep->x, n); + swaps (&rep->y, n); + swaps (&rep->width, n); + swaps (&rep->height, n); + swaps (&rep->xhot, n); + swaps (&rep->yhot, n); + swapl (&rep->cursorSerial, n); + swapl (&rep->cursorName, n); + swaps (&rep->nbytes, n); + SwapLongs (image, npixels); + } + (void) WriteToClient(client, sizeof (xXFixesGetCursorImageAndNameReply) + + (npixels << 2) + nbytesRound, (char *) rep); + xfree (rep); + return client->noClientException; +} + +int +SProcXFixesGetCursorImageAndName (ClientPtr client) +{ + int n; + REQUEST(xXFixesGetCursorImageAndNameReq); + swaps (&stuff->length, n); + return (*ProcXFixesVector[stuff->xfixesReqType]) (client); +} + +/* + * Find every cursor reference in the system, ask testCursor + * whether it should be replaced with a reference to pCursor. + */ + +typedef Bool (*TestCursorFunc) (CursorPtr pOld, pointer closure); + +typedef struct { + RESTYPE type; + TestCursorFunc testCursor; + CursorPtr pNew; + pointer closure; +} ReplaceCursorLookupRec, *ReplaceCursorLookupPtr; + +static const RESTYPE CursorRestypes[] = { + RT_WINDOW, RT_PASSIVEGRAB, RT_CURSOR +}; + +#define NUM_CURSOR_RESTYPES (sizeof (CursorRestypes) / sizeof (CursorRestypes[0])) + +static Bool +ReplaceCursorLookup (pointer value, XID id, pointer closure) +{ + ReplaceCursorLookupPtr rcl = (ReplaceCursorLookupPtr) closure; + WindowPtr pWin; + GrabPtr pGrab; + CursorPtr pCursor = 0, *pCursorRef = 0; + XID cursor = 0; + + switch (rcl->type) { + case RT_WINDOW: + pWin = (WindowPtr) value; + if (pWin->optional) + { + pCursorRef = &pWin->optional->cursor; + pCursor = *pCursorRef; + } + break; + case RT_PASSIVEGRAB: + pGrab = (GrabPtr) value; + pCursorRef = &pGrab->cursor; + pCursor = *pCursorRef; + break; + case RT_CURSOR: + pCursorRef = 0; + pCursor = (CursorPtr) value; + cursor = id; + break; + } + if (pCursor && pCursor != rcl->pNew) + { + if ((*rcl->testCursor) (pCursor, rcl->closure)) + { + rcl->pNew->refcnt++; + /* either redirect reference or update resource database */ + if (pCursorRef) + *pCursorRef = rcl->pNew; + else + ChangeResourceValue (id, RT_CURSOR, rcl->pNew); + FreeCursor (pCursor, cursor); + } + } + return FALSE; /* keep walking */ +} + +static void +ReplaceCursor (CursorPtr pCursor, + TestCursorFunc testCursor, + pointer closure) +{ + int clientIndex; + int resIndex; + ReplaceCursorLookupRec rcl; + + /* + * Cursors exist only in the resource database, windows and grabs. + * All of these are always pointed at by the resource database. Walk + * the whole thing looking for cursors + */ + rcl.testCursor = testCursor; + rcl.pNew = pCursor; + rcl.closure = closure; + + /* for each client */ + for (clientIndex = 0; clientIndex < currentMaxClients; clientIndex++) + { + if (!clients[clientIndex]) + continue; + for (resIndex = 0; resIndex < NUM_CURSOR_RESTYPES; resIndex++) + { + rcl.type = CursorRestypes[resIndex]; + /* + * This function walks the entire client resource database + */ + LookupClientResourceComplex (clients[clientIndex], + rcl.type, + ReplaceCursorLookup, + (pointer) &rcl); + } + } + /* this "knows" that WindowHasNewCursor doesn't depend on it's argument */ + WindowHasNewCursor (WindowTable[0]); +} + +static Bool +TestForCursor (CursorPtr pCursor, pointer closure) +{ + return (pCursor == (CursorPtr) closure); +} + +int +ProcXFixesChangeCursor (ClientPtr client) +{ + CursorPtr pSource, pDestination; + REQUEST(xXFixesChangeCursorReq); + + REQUEST_SIZE_MATCH(xXFixesChangeCursorReq); + VERIFY_CURSOR (pSource, stuff->source, client, SecurityReadAccess); + VERIFY_CURSOR (pDestination, stuff->destination, client, SecurityWriteAccess); + + ReplaceCursor (pSource, TestForCursor, (pointer) pDestination); + return (client->noClientException); +} + +int +SProcXFixesChangeCursor (ClientPtr client) +{ + int n; + REQUEST(xXFixesChangeCursorReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xXFixesChangeCursorReq); + swapl (&stuff->source, n); + swapl (&stuff->destination, n); + return (*ProcXFixesVector[stuff->xfixesReqType]) (client); +} + +static Bool +TestForCursorName (CursorPtr pCursor, pointer closure) +{ + return (pCursor->name == (Atom) closure); +} + +int +ProcXFixesChangeCursorByName (ClientPtr client) +{ + CursorPtr pSource; + Atom name; + char *tchar; + REQUEST(xXFixesChangeCursorByNameReq); + + REQUEST_FIXED_SIZE(xXFixesChangeCursorByNameReq, stuff->nbytes); + VERIFY_CURSOR(pSource, stuff->source, client, SecurityReadAccess); + tchar = (char *) &stuff[1]; + name = MakeAtom (tchar, stuff->nbytes, FALSE); + if (name) + ReplaceCursor (pSource, TestForCursorName, (pointer) name); + return (client->noClientException); +} + +int +SProcXFixesChangeCursorByName (ClientPtr client) +{ + int n; + REQUEST(xXFixesChangeCursorByNameReq); + + swaps (&stuff->length, n); + REQUEST_AT_LEAST_SIZE (xXFixesChangeCursorByNameReq); + swapl (&stuff->source, n); + swaps (&stuff->nbytes, n); + return (*ProcXFixesVector[stuff->xfixesReqType]) (client); +} + +static int +CursorFreeClient (pointer data, XID id) +{ + CursorEventPtr old = (CursorEventPtr) data; + CursorEventPtr *prev, e; + + for (prev = &cursorEvents; (e = *prev); prev = &e->next) + { + if (e == old) + { + *prev = e->next; + xfree (e); + break; + } + } + return 1; +} + +static int +CursorFreeWindow (pointer data, XID id) +{ + WindowPtr pWindow = (WindowPtr) data; + CursorEventPtr e, next; + + for (e = cursorEvents; e; e = next) + { + next = e->next; + if (e->pWindow == pWindow) + { + FreeResource (e->clientResource, 0); + } + } + return 1; +} + +Bool +XFixesCursorInit (void) +{ + int i; + + if (CursorGeneration != serverGeneration) + { + CursorScreenPrivateIndex = AllocateScreenPrivateIndex (); + if (CursorScreenPrivateIndex < 0) + return FALSE; + CursorGeneration = serverGeneration; + } + for (i = 0; i < screenInfo.numScreens; i++) + { + ScreenPtr pScreen = screenInfo.screens[i]; + CursorScreenPtr cs; + + cs = (CursorScreenPtr) xalloc (sizeof (CursorScreenRec)); + if (!cs) + return FALSE; + Wrap (cs, pScreen, CloseScreen, CursorCloseScreen); + Wrap (cs, pScreen, DisplayCursor, CursorDisplayCursor); + SetCursorScreen (pScreen, cs); + } + CursorClientType = CreateNewResourceType(CursorFreeClient); + CursorWindowType = CreateNewResourceType(CursorFreeWindow); + return CursorClientType && CursorWindowType; +} + |