cursor.c revision 4642e01f
105b261ecSmrg/*
205b261ecSmrg * Copyright © 2006 Sun Microsystems
305b261ecSmrg *
405b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its
505b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that
605b261ecSmrg * the above copyright notice appear in all copies and that both that
705b261ecSmrg * copyright notice and this permission notice appear in supporting
805b261ecSmrg * documentation, and that the name of Sun Microsystems not be used in
905b261ecSmrg * advertising or publicity pertaining to distribution of the software without
1005b261ecSmrg * specific, written prior permission.  Sun Microsystems makes no
1105b261ecSmrg * representations about the suitability of this software for any purpose.  It
1205b261ecSmrg * is provided "as is" without express or implied warranty.
1305b261ecSmrg *
1405b261ecSmrg * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1505b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1605b261ecSmrg * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1705b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1805b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1905b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2005b261ecSmrg * PERFORMANCE OF THIS SOFTWARE.
2105b261ecSmrg *
2205b261ecSmrg * Copyright © 2002 Keith Packard
2305b261ecSmrg *
2405b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its
2505b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that
2605b261ecSmrg * the above copyright notice appear in all copies and that both that
2705b261ecSmrg * copyright notice and this permission notice appear in supporting
2805b261ecSmrg * documentation, and that the name of Keith Packard not be used in
2905b261ecSmrg * advertising or publicity pertaining to distribution of the software without
3005b261ecSmrg * specific, written prior permission.  Keith Packard makes no
3105b261ecSmrg * representations about the suitability of this software for any purpose.  It
3205b261ecSmrg * is provided "as is" without express or implied warranty.
3305b261ecSmrg *
3405b261ecSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
3505b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
3605b261ecSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
3705b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
3805b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
3905b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
4005b261ecSmrg * PERFORMANCE OF THIS SOFTWARE.
4105b261ecSmrg */
4205b261ecSmrg
4305b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
4405b261ecSmrg#include <dix-config.h>
4505b261ecSmrg#endif
4605b261ecSmrg
4705b261ecSmrg#include "xfixesint.h"
4805b261ecSmrg#include "scrnintstr.h"
4905b261ecSmrg#include "cursorstr.h"
5005b261ecSmrg#include "dixevents.h"
5105b261ecSmrg#include "servermd.h"
5205b261ecSmrg#include "inputstr.h"
5305b261ecSmrg#include "windowstr.h"
544642e01fSmrg#include "xace.h"
5505b261ecSmrg
5605b261ecSmrgstatic RESTYPE		CursorClientType;
5705b261ecSmrgstatic RESTYPE		CursorHideCountType;
5805b261ecSmrgstatic RESTYPE		CursorWindowType;
5905b261ecSmrgstatic CursorPtr	CursorCurrent;
6005b261ecSmrgstatic CursorPtr        pInvisibleCursor = NULL;
6105b261ecSmrg
624642e01fSmrgstatic int CursorScreenPrivateKeyIndex;
634642e01fSmrgstatic DevPrivateKey CursorScreenPrivateKey = &CursorScreenPrivateKeyIndex;
644642e01fSmrg
6505b261ecSmrgstatic void deleteCursorHideCountsForScreen (ScreenPtr pScreen);
6605b261ecSmrg
6705b261ecSmrg#define VERIFY_CURSOR(pCursor, cursor, client, access) { \
6805b261ecSmrg    pCursor = (CursorPtr)SecurityLookupIDByType((client), (cursor), \
6905b261ecSmrg					RT_CURSOR, (access)); \
7005b261ecSmrg    if (!pCursor) { \
7105b261ecSmrg	(client)->errorValue = (cursor); \
7205b261ecSmrg	return BadCursor; \
7305b261ecSmrg    } \
7405b261ecSmrg}
754642e01fSmrg
7605b261ecSmrg/*
7705b261ecSmrg * There is a global list of windows selecting for cursor events
7805b261ecSmrg */
7905b261ecSmrg
8005b261ecSmrgtypedef struct _CursorEvent *CursorEventPtr;
8105b261ecSmrg
8205b261ecSmrgtypedef struct _CursorEvent {
8305b261ecSmrg    CursorEventPtr	next;
8405b261ecSmrg    CARD32		eventMask;
8505b261ecSmrg    ClientPtr		pClient;
8605b261ecSmrg    WindowPtr		pWindow;
8705b261ecSmrg    XID			clientResource;
8805b261ecSmrg} CursorEventRec;
8905b261ecSmrg
9005b261ecSmrgstatic CursorEventPtr	    cursorEvents;
9105b261ecSmrg
9205b261ecSmrg/*
9305b261ecSmrg * Each screen has a list of clients which have requested
9405b261ecSmrg * that the cursor be hid, and the number of times each
9505b261ecSmrg * client has requested.
9605b261ecSmrg*/
9705b261ecSmrg
9805b261ecSmrgtypedef struct _CursorHideCountRec *CursorHideCountPtr;
9905b261ecSmrg
10005b261ecSmrgtypedef struct _CursorHideCountRec {
10105b261ecSmrg    CursorHideCountPtr   pNext;
10205b261ecSmrg    ClientPtr            pClient;
10305b261ecSmrg    ScreenPtr            pScreen;
10405b261ecSmrg    int                  hideCount;
10505b261ecSmrg    XID			 resource;
10605b261ecSmrg} CursorHideCountRec;
10705b261ecSmrg
10805b261ecSmrg/*
10905b261ecSmrg * Wrap DisplayCursor to catch cursor change events
11005b261ecSmrg */
11105b261ecSmrg
11205b261ecSmrgtypedef struct _CursorScreen {
11305b261ecSmrg    DisplayCursorProcPtr	DisplayCursor;
11405b261ecSmrg    CloseScreenProcPtr		CloseScreen;
11505b261ecSmrg    CursorHideCountPtr          pCursorHideCounts;
11605b261ecSmrg} CursorScreenRec, *CursorScreenPtr;
11705b261ecSmrg
1184642e01fSmrg#define GetCursorScreen(s) ((CursorScreenPtr)dixLookupPrivate(&(s)->devPrivates, CursorScreenPrivateKey))
1194642e01fSmrg#define GetCursorScreenIfSet(s) GetCursorScreen(s)
1204642e01fSmrg#define SetCursorScreen(s,p) dixSetPrivate(&(s)->devPrivates, CursorScreenPrivateKey, p)
12105b261ecSmrg#define Wrap(as,s,elt,func)	(((as)->elt = (s)->elt), (s)->elt = func)
12205b261ecSmrg#define Unwrap(as,s,elt)	((s)->elt = (as)->elt)
12305b261ecSmrg
1244642e01fSmrg/* The cursor doesn't show up until the first XDefineCursor() */
1254642e01fSmrgstatic Bool CursorVisible = FALSE;
1264642e01fSmrg
12705b261ecSmrgstatic Bool
1284642e01fSmrgCursorDisplayCursor (DeviceIntPtr pDev,
1294642e01fSmrg                     ScreenPtr pScreen,
13005b261ecSmrg		     CursorPtr pCursor)
13105b261ecSmrg{
13205b261ecSmrg    CursorScreenPtr	cs = GetCursorScreen(pScreen);
13305b261ecSmrg    Bool		ret;
13405b261ecSmrg
13505b261ecSmrg    Unwrap (cs, pScreen, DisplayCursor);
13605b261ecSmrg
1374642e01fSmrg    /*
1384642e01fSmrg     * Have to check ConnectionInfo to distinguish client requests from
1394642e01fSmrg     * initial root window setup.  Not a great way to do it, I admit.
1404642e01fSmrg     */
1414642e01fSmrg    if (ConnectionInfo)
1424642e01fSmrg	CursorVisible = TRUE;
1434642e01fSmrg
1444642e01fSmrg    if (cs->pCursorHideCounts != NULL || !CursorVisible) {
1454642e01fSmrg        ret = ((*pScreen->RealizeCursor)(pDev, pScreen, pInvisibleCursor) &&
1464642e01fSmrg	       (*pScreen->DisplayCursor) (pDev, pScreen, pInvisibleCursor));
14705b261ecSmrg    } else {
1484642e01fSmrg	ret = (*pScreen->DisplayCursor) (pDev, pScreen, pCursor);
14905b261ecSmrg    }
15005b261ecSmrg
15105b261ecSmrg    if (pCursor != CursorCurrent)
15205b261ecSmrg    {
15305b261ecSmrg	CursorEventPtr	e;
15405b261ecSmrg
15505b261ecSmrg	CursorCurrent = pCursor;
15605b261ecSmrg	for (e = cursorEvents; e; e = e->next)
15705b261ecSmrg	{
15805b261ecSmrg	    if ((e->eventMask & XFixesDisplayCursorNotifyMask) &&
15905b261ecSmrg		!e->pClient->clientGone)
16005b261ecSmrg	    {
16105b261ecSmrg		xXFixesCursorNotifyEvent	ev;
16205b261ecSmrg		ev.type = XFixesEventBase + XFixesCursorNotify;
16305b261ecSmrg		ev.subtype = XFixesDisplayCursorNotify;
16405b261ecSmrg		ev.sequenceNumber = e->pClient->sequence;
16505b261ecSmrg		ev.window = e->pWindow->drawable.id;
16605b261ecSmrg		ev.cursorSerial = pCursor->serialNumber;
16705b261ecSmrg		ev.timestamp = currentTime.milliseconds;
16805b261ecSmrg		ev.name = pCursor->name;
16905b261ecSmrg		WriteEventsToClient (e->pClient, 1, (xEvent *) &ev);
17005b261ecSmrg	    }
17105b261ecSmrg	}
17205b261ecSmrg    }
17305b261ecSmrg    Wrap (cs, pScreen, DisplayCursor, CursorDisplayCursor);
17405b261ecSmrg    return ret;
17505b261ecSmrg}
17605b261ecSmrg
17705b261ecSmrgstatic Bool
17805b261ecSmrgCursorCloseScreen (int index, ScreenPtr pScreen)
17905b261ecSmrg{
18005b261ecSmrg    CursorScreenPtr	cs = GetCursorScreen (pScreen);
18105b261ecSmrg    Bool		ret;
18205b261ecSmrg
18305b261ecSmrg    Unwrap (cs, pScreen, CloseScreen);
18405b261ecSmrg    Unwrap (cs, pScreen, DisplayCursor);
18505b261ecSmrg    deleteCursorHideCountsForScreen(pScreen);
18605b261ecSmrg    ret = (*pScreen->CloseScreen) (index, pScreen);
18705b261ecSmrg    xfree (cs);
18805b261ecSmrg    return ret;
18905b261ecSmrg}
19005b261ecSmrg
19105b261ecSmrg#define CursorAllEvents (XFixesDisplayCursorNotifyMask)
19205b261ecSmrg
19305b261ecSmrgstatic int
19405b261ecSmrgXFixesSelectCursorInput (ClientPtr	pClient,
19505b261ecSmrg			 WindowPtr	pWindow,
19605b261ecSmrg			 CARD32		eventMask)
19705b261ecSmrg{
19805b261ecSmrg    CursorEventPtr	*prev, e;
19905b261ecSmrg
20005b261ecSmrg    for (prev = &cursorEvents; (e = *prev); prev = &e->next)
20105b261ecSmrg    {
20205b261ecSmrg	if (e->pClient == pClient &&
20305b261ecSmrg	    e->pWindow == pWindow)
20405b261ecSmrg	{
20505b261ecSmrg	    break;
20605b261ecSmrg	}
20705b261ecSmrg    }
20805b261ecSmrg    if (!eventMask)
20905b261ecSmrg    {
21005b261ecSmrg	if (e)
21105b261ecSmrg	{
21205b261ecSmrg	    FreeResource (e->clientResource, 0);
21305b261ecSmrg	}
21405b261ecSmrg	return Success;
21505b261ecSmrg    }
21605b261ecSmrg    if (!e)
21705b261ecSmrg    {
21805b261ecSmrg	e = (CursorEventPtr) xalloc (sizeof (CursorEventRec));
21905b261ecSmrg	if (!e)
22005b261ecSmrg	    return BadAlloc;
22105b261ecSmrg
22205b261ecSmrg	e->next = 0;
22305b261ecSmrg	e->pClient = pClient;
22405b261ecSmrg	e->pWindow = pWindow;
22505b261ecSmrg	e->clientResource = FakeClientID(pClient->index);
22605b261ecSmrg
22705b261ecSmrg	/*
22805b261ecSmrg	 * Add a resource hanging from the window to
22905b261ecSmrg	 * catch window destroy
23005b261ecSmrg	 */
23105b261ecSmrg	if (!LookupIDByType(pWindow->drawable.id, CursorWindowType))
23205b261ecSmrg	    if (!AddResource (pWindow->drawable.id, CursorWindowType,
23305b261ecSmrg			      (pointer) pWindow))
23405b261ecSmrg	    {
23505b261ecSmrg		xfree (e);
23605b261ecSmrg		return BadAlloc;
23705b261ecSmrg	    }
23805b261ecSmrg
23905b261ecSmrg	if (!AddResource (e->clientResource, CursorClientType, (pointer) e))
24005b261ecSmrg	    return BadAlloc;
24105b261ecSmrg
24205b261ecSmrg	*prev = e;
24305b261ecSmrg    }
24405b261ecSmrg    e->eventMask = eventMask;
24505b261ecSmrg    return Success;
24605b261ecSmrg}
24705b261ecSmrg
24805b261ecSmrgint
24905b261ecSmrgProcXFixesSelectCursorInput (ClientPtr client)
25005b261ecSmrg{
25105b261ecSmrg    REQUEST (xXFixesSelectCursorInputReq);
25205b261ecSmrg    WindowPtr	pWin;
25305b261ecSmrg    int		rc;
25405b261ecSmrg
25505b261ecSmrg    REQUEST_SIZE_MATCH (xXFixesSelectCursorInputReq);
2564642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
25705b261ecSmrg    if (rc != Success)
25805b261ecSmrg        return rc;
25905b261ecSmrg    if (stuff->eventMask & ~CursorAllEvents)
26005b261ecSmrg    {
26105b261ecSmrg	client->errorValue = stuff->eventMask;
26205b261ecSmrg	return( BadValue );
26305b261ecSmrg    }
26405b261ecSmrg    return XFixesSelectCursorInput (client, pWin, stuff->eventMask);
26505b261ecSmrg}
26605b261ecSmrg
26705b261ecSmrgstatic int
26805b261ecSmrgGetBit (unsigned char *line, int x)
26905b261ecSmrg{
27005b261ecSmrg    unsigned char   mask;
27105b261ecSmrg
27205b261ecSmrg    if (screenInfo.bitmapBitOrder == LSBFirst)
27305b261ecSmrg	mask = (1 << (x & 7));
27405b261ecSmrg    else
27505b261ecSmrg	mask = (0x80 >> (x & 7));
27605b261ecSmrg    /* XXX assumes byte order is host byte order */
27705b261ecSmrg    line += (x >> 3);
27805b261ecSmrg    if (*line & mask)
27905b261ecSmrg	return 1;
28005b261ecSmrg    return 0;
28105b261ecSmrg}
28205b261ecSmrg
28305b261ecSmrgint
28405b261ecSmrgSProcXFixesSelectCursorInput (ClientPtr client)
28505b261ecSmrg{
28605b261ecSmrg    register int n;
28705b261ecSmrg    REQUEST(xXFixesSelectCursorInputReq);
28805b261ecSmrg
28905b261ecSmrg    swaps(&stuff->length, n);
29005b261ecSmrg    swapl(&stuff->window, n);
29105b261ecSmrg    swapl(&stuff->eventMask, n);
29205b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
29305b261ecSmrg}
29405b261ecSmrg
29505b261ecSmrgvoid
29605b261ecSmrgSXFixesCursorNotifyEvent (xXFixesCursorNotifyEvent *from,
29705b261ecSmrg			  xXFixesCursorNotifyEvent *to)
29805b261ecSmrg{
29905b261ecSmrg    to->type = from->type;
30005b261ecSmrg    cpswaps (from->sequenceNumber, to->sequenceNumber);
30105b261ecSmrg    cpswapl (from->window, to->window);
30205b261ecSmrg    cpswapl (from->cursorSerial, to->cursorSerial);
30305b261ecSmrg    cpswapl (from->timestamp, to->timestamp);
30405b261ecSmrg    cpswapl (from->name, to->name);
30505b261ecSmrg}
30605b261ecSmrg
30705b261ecSmrgstatic void
30805b261ecSmrgCopyCursorToImage (CursorPtr pCursor, CARD32 *image)
30905b261ecSmrg{
31005b261ecSmrg    int width = pCursor->bits->width;
31105b261ecSmrg    int height = pCursor->bits->height;
31205b261ecSmrg    int npixels = width * height;
31305b261ecSmrg
31405b261ecSmrg#ifdef ARGB_CURSOR
31505b261ecSmrg    if (pCursor->bits->argb)
31605b261ecSmrg	memcpy (image, pCursor->bits->argb, npixels * sizeof (CARD32));
31705b261ecSmrg    else
31805b261ecSmrg#endif
31905b261ecSmrg    {
32005b261ecSmrg	unsigned char	*srcLine = pCursor->bits->source;
32105b261ecSmrg	unsigned char	*mskLine = pCursor->bits->mask;
32205b261ecSmrg	int		stride = BitmapBytePad (width);
32305b261ecSmrg	int		x, y;
32405b261ecSmrg	CARD32		fg, bg;
32505b261ecSmrg
32605b261ecSmrg	fg = (0xff000000 |
32705b261ecSmrg	      ((pCursor->foreRed & 0xff00) << 8) |
32805b261ecSmrg	      (pCursor->foreGreen & 0xff00) |
32905b261ecSmrg	      (pCursor->foreBlue >> 8));
33005b261ecSmrg	bg = (0xff000000 |
33105b261ecSmrg	      ((pCursor->backRed & 0xff00) << 8) |
33205b261ecSmrg	      (pCursor->backGreen & 0xff00) |
33305b261ecSmrg	      (pCursor->backBlue >> 8));
33405b261ecSmrg	for (y = 0; y < height; y++)
33505b261ecSmrg	{
33605b261ecSmrg	    for (x = 0; x < width; x++)
33705b261ecSmrg	    {
33805b261ecSmrg		if (GetBit (mskLine, x))
33905b261ecSmrg		{
34005b261ecSmrg		    if (GetBit (srcLine, x))
34105b261ecSmrg			*image++ = fg;
34205b261ecSmrg		    else
34305b261ecSmrg			*image++ = bg;
34405b261ecSmrg		}
34505b261ecSmrg		else
34605b261ecSmrg		    *image++ = 0;
34705b261ecSmrg	    }
34805b261ecSmrg	    srcLine += stride;
34905b261ecSmrg	    mskLine += stride;
35005b261ecSmrg	}
35105b261ecSmrg    }
35205b261ecSmrg}
35305b261ecSmrg
35405b261ecSmrgint
35505b261ecSmrgProcXFixesGetCursorImage (ClientPtr client)
35605b261ecSmrg{
35705b261ecSmrg/*    REQUEST(xXFixesGetCursorImageReq); */
35805b261ecSmrg    xXFixesGetCursorImageReply	*rep;
35905b261ecSmrg    CursorPtr			pCursor;
36005b261ecSmrg    CARD32			*image;
3614642e01fSmrg    int				npixels, width, height, rc, x, y;
36205b261ecSmrg
36305b261ecSmrg    REQUEST_SIZE_MATCH(xXFixesGetCursorImageReq);
36405b261ecSmrg    pCursor = CursorCurrent;
36505b261ecSmrg    if (!pCursor)
36605b261ecSmrg	return BadCursor;
3674642e01fSmrg    rc = XaceHook(XACE_RESOURCE_ACCESS, client, pCursor->id, RT_CURSOR,
3684642e01fSmrg		  pCursor, RT_NONE, NULL, DixReadAccess);
3694642e01fSmrg    if (rc != Success)
3704642e01fSmrg	return rc;
3714642e01fSmrg    GetSpritePosition (PickPointer(client), &x, &y);
37205b261ecSmrg    width = pCursor->bits->width;
37305b261ecSmrg    height = pCursor->bits->height;
37405b261ecSmrg    npixels = width * height;
37505b261ecSmrg    rep = xalloc (sizeof (xXFixesGetCursorImageReply) +
37605b261ecSmrg		  npixels * sizeof (CARD32));
37705b261ecSmrg    if (!rep)
37805b261ecSmrg	return BadAlloc;
37905b261ecSmrg
38005b261ecSmrg    rep->type = X_Reply;
38105b261ecSmrg    rep->sequenceNumber = client->sequence;
38205b261ecSmrg    rep->length = npixels;
38305b261ecSmrg    rep->width = width;
38405b261ecSmrg    rep->height = height;
38505b261ecSmrg    rep->x = x;
38605b261ecSmrg    rep->y = y;
38705b261ecSmrg    rep->xhot = pCursor->bits->xhot;
38805b261ecSmrg    rep->yhot = pCursor->bits->yhot;
38905b261ecSmrg    rep->cursorSerial = pCursor->serialNumber;
39005b261ecSmrg
39105b261ecSmrg    image = (CARD32 *) (rep + 1);
39205b261ecSmrg    CopyCursorToImage (pCursor, image);
39305b261ecSmrg    if (client->swapped)
39405b261ecSmrg    {
39505b261ecSmrg	int n;
39605b261ecSmrg	swaps (&rep->sequenceNumber, n);
39705b261ecSmrg	swapl (&rep->length, n);
39805b261ecSmrg	swaps (&rep->x, n);
39905b261ecSmrg	swaps (&rep->y, n);
40005b261ecSmrg	swaps (&rep->width, n);
40105b261ecSmrg	swaps (&rep->height, n);
40205b261ecSmrg	swaps (&rep->xhot, n);
40305b261ecSmrg	swaps (&rep->yhot, n);
40405b261ecSmrg	swapl (&rep->cursorSerial, n);
40505b261ecSmrg	SwapLongs (image, npixels);
40605b261ecSmrg    }
40705b261ecSmrg    (void) WriteToClient(client, sizeof (xXFixesGetCursorImageReply) +
40805b261ecSmrg			 (npixels << 2), (char *) rep);
40905b261ecSmrg    xfree (rep);
41005b261ecSmrg    return client->noClientException;
41105b261ecSmrg}
41205b261ecSmrg
41305b261ecSmrgint
41405b261ecSmrgSProcXFixesGetCursorImage (ClientPtr client)
41505b261ecSmrg{
41605b261ecSmrg    int n;
41705b261ecSmrg    REQUEST(xXFixesGetCursorImageReq);
41805b261ecSmrg    swaps (&stuff->length, n);
41905b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
42005b261ecSmrg}
42105b261ecSmrg
42205b261ecSmrgint
42305b261ecSmrgProcXFixesSetCursorName (ClientPtr client)
42405b261ecSmrg{
42505b261ecSmrg    CursorPtr pCursor;
42605b261ecSmrg    char *tchar;
42705b261ecSmrg    REQUEST(xXFixesSetCursorNameReq);
42805b261ecSmrg    Atom atom;
42905b261ecSmrg
43005b261ecSmrg    REQUEST_AT_LEAST_SIZE(xXFixesSetCursorNameReq);
4314642e01fSmrg    VERIFY_CURSOR(pCursor, stuff->cursor, client, DixSetAttrAccess);
43205b261ecSmrg    tchar = (char *) &stuff[1];
43305b261ecSmrg    atom = MakeAtom (tchar, stuff->nbytes, TRUE);
43405b261ecSmrg    if (atom == BAD_RESOURCE)
43505b261ecSmrg	return BadAlloc;
43605b261ecSmrg
43705b261ecSmrg    pCursor->name = atom;
43805b261ecSmrg    return(client->noClientException);
43905b261ecSmrg}
44005b261ecSmrg
44105b261ecSmrgint
44205b261ecSmrgSProcXFixesSetCursorName (ClientPtr client)
44305b261ecSmrg{
44405b261ecSmrg    int n;
44505b261ecSmrg    REQUEST(xXFixesSetCursorNameReq);
44605b261ecSmrg
44705b261ecSmrg    swaps (&stuff->length, n);
44805b261ecSmrg    REQUEST_AT_LEAST_SIZE(xXFixesSetCursorNameReq);
44905b261ecSmrg    swapl (&stuff->cursor, n);
45005b261ecSmrg    swaps (&stuff->nbytes, n);
45105b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
45205b261ecSmrg}
45305b261ecSmrg
45405b261ecSmrgint
45505b261ecSmrgProcXFixesGetCursorName (ClientPtr client)
45605b261ecSmrg{
45705b261ecSmrg    CursorPtr			pCursor;
45805b261ecSmrg    xXFixesGetCursorNameReply	reply;
45905b261ecSmrg    REQUEST(xXFixesGetCursorNameReq);
46005b261ecSmrg    char *str;
46105b261ecSmrg    int len;
46205b261ecSmrg
46305b261ecSmrg    REQUEST_SIZE_MATCH(xXFixesGetCursorNameReq);
4644642e01fSmrg    VERIFY_CURSOR(pCursor, stuff->cursor, client, DixGetAttrAccess);
46505b261ecSmrg    if (pCursor->name)
46605b261ecSmrg	str = NameForAtom (pCursor->name);
46705b261ecSmrg    else
46805b261ecSmrg	str = "";
46905b261ecSmrg    len = strlen (str);
47005b261ecSmrg
47105b261ecSmrg    reply.type = X_Reply;
47205b261ecSmrg    reply.length = (len + 3) >> 2;
47305b261ecSmrg    reply.sequenceNumber = client->sequence;
47405b261ecSmrg    reply.atom = pCursor->name;
47505b261ecSmrg    reply.nbytes = len;
47605b261ecSmrg    if (client->swapped)
47705b261ecSmrg    {
47805b261ecSmrg	int n;
47905b261ecSmrg	swaps (&reply.sequenceNumber, n);
48005b261ecSmrg	swapl (&reply.length, n);
48105b261ecSmrg	swapl (&reply.atom, n);
48205b261ecSmrg	swaps (&reply.nbytes, n);
48305b261ecSmrg    }
48405b261ecSmrg    WriteReplyToClient(client, sizeof(xXFixesGetCursorNameReply), &reply);
48505b261ecSmrg    (void)WriteToClient(client, len, str);
48605b261ecSmrg
48705b261ecSmrg    return(client->noClientException);
48805b261ecSmrg}
48905b261ecSmrg
49005b261ecSmrgint
49105b261ecSmrgSProcXFixesGetCursorName (ClientPtr client)
49205b261ecSmrg{
49305b261ecSmrg    int n;
49405b261ecSmrg    REQUEST(xXFixesGetCursorNameReq);
49505b261ecSmrg
49605b261ecSmrg    swaps (&stuff->length, n);
49705b261ecSmrg    REQUEST_SIZE_MATCH(xXFixesGetCursorNameReq);
49805b261ecSmrg    swapl (&stuff->cursor, n);
49905b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
50005b261ecSmrg}
50105b261ecSmrg
50205b261ecSmrgint
50305b261ecSmrgProcXFixesGetCursorImageAndName (ClientPtr client)
50405b261ecSmrg{
50505b261ecSmrg/*    REQUEST(xXFixesGetCursorImageAndNameReq); */
50605b261ecSmrg    xXFixesGetCursorImageAndNameReply	*rep;
50705b261ecSmrg    CursorPtr			pCursor;
50805b261ecSmrg    CARD32			*image;
50905b261ecSmrg    int				npixels;
51005b261ecSmrg    char			*name;
51105b261ecSmrg    int				nbytes, nbytesRound;
51205b261ecSmrg    int				width, height;
5134642e01fSmrg    int				rc, x, y;
51405b261ecSmrg
51505b261ecSmrg    REQUEST_SIZE_MATCH(xXFixesGetCursorImageAndNameReq);
51605b261ecSmrg    pCursor = CursorCurrent;
51705b261ecSmrg    if (!pCursor)
51805b261ecSmrg	return BadCursor;
5194642e01fSmrg    rc = XaceHook(XACE_RESOURCE_ACCESS, client, pCursor->id, RT_CURSOR,
5204642e01fSmrg		  pCursor, RT_NONE, NULL, DixReadAccess|DixGetAttrAccess);
5214642e01fSmrg    if (rc != Success)
5224642e01fSmrg	return rc;
5234642e01fSmrg    GetSpritePosition (PickPointer(client), &x, &y);
52405b261ecSmrg    width = pCursor->bits->width;
52505b261ecSmrg    height = pCursor->bits->height;
52605b261ecSmrg    npixels = width * height;
52705b261ecSmrg    name = pCursor->name ? NameForAtom (pCursor->name) : "";
52805b261ecSmrg    nbytes = strlen (name);
52905b261ecSmrg    nbytesRound = (nbytes + 3) & ~3;
53005b261ecSmrg    rep = xalloc (sizeof (xXFixesGetCursorImageAndNameReply) +
53105b261ecSmrg		  npixels * sizeof (CARD32) + nbytesRound);
53205b261ecSmrg    if (!rep)
53305b261ecSmrg	return BadAlloc;
53405b261ecSmrg
53505b261ecSmrg    rep->type = X_Reply;
53605b261ecSmrg    rep->sequenceNumber = client->sequence;
53705b261ecSmrg    rep->length = npixels + (nbytesRound >> 2);
53805b261ecSmrg    rep->width = width;
53905b261ecSmrg    rep->height = height;
54005b261ecSmrg    rep->x = x;
54105b261ecSmrg    rep->y = y;
54205b261ecSmrg    rep->xhot = pCursor->bits->xhot;
54305b261ecSmrg    rep->yhot = pCursor->bits->yhot;
54405b261ecSmrg    rep->cursorSerial = pCursor->serialNumber;
54505b261ecSmrg    rep->cursorName = pCursor->name;
54605b261ecSmrg    rep->nbytes = nbytes;
54705b261ecSmrg
54805b261ecSmrg    image = (CARD32 *) (rep + 1);
54905b261ecSmrg    CopyCursorToImage (pCursor, image);
55005b261ecSmrg    memcpy ((image + npixels), name, nbytes);
55105b261ecSmrg    if (client->swapped)
55205b261ecSmrg    {
55305b261ecSmrg	int n;
55405b261ecSmrg	swaps (&rep->sequenceNumber, n);
55505b261ecSmrg	swapl (&rep->length, n);
55605b261ecSmrg	swaps (&rep->x, n);
55705b261ecSmrg	swaps (&rep->y, n);
55805b261ecSmrg	swaps (&rep->width, n);
55905b261ecSmrg	swaps (&rep->height, n);
56005b261ecSmrg	swaps (&rep->xhot, n);
56105b261ecSmrg	swaps (&rep->yhot, n);
56205b261ecSmrg	swapl (&rep->cursorSerial, n);
56305b261ecSmrg	swapl (&rep->cursorName, n);
56405b261ecSmrg	swaps (&rep->nbytes, n);
56505b261ecSmrg	SwapLongs (image, npixels);
56605b261ecSmrg    }
56705b261ecSmrg    (void) WriteToClient(client, sizeof (xXFixesGetCursorImageAndNameReply) +
56805b261ecSmrg			 (npixels << 2) + nbytesRound, (char *) rep);
56905b261ecSmrg    xfree (rep);
57005b261ecSmrg    return client->noClientException;
57105b261ecSmrg}
57205b261ecSmrg
57305b261ecSmrgint
57405b261ecSmrgSProcXFixesGetCursorImageAndName (ClientPtr client)
57505b261ecSmrg{
57605b261ecSmrg    int n;
57705b261ecSmrg    REQUEST(xXFixesGetCursorImageAndNameReq);
57805b261ecSmrg    swaps (&stuff->length, n);
57905b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
58005b261ecSmrg}
58105b261ecSmrg
58205b261ecSmrg/*
58305b261ecSmrg * Find every cursor reference in the system, ask testCursor
58405b261ecSmrg * whether it should be replaced with a reference to pCursor.
58505b261ecSmrg */
58605b261ecSmrg
58705b261ecSmrgtypedef Bool (*TestCursorFunc) (CursorPtr pOld, pointer closure);
58805b261ecSmrg
58905b261ecSmrgtypedef struct {
59005b261ecSmrg    RESTYPE type;
59105b261ecSmrg    TestCursorFunc testCursor;
59205b261ecSmrg    CursorPtr pNew;
59305b261ecSmrg    pointer closure;
59405b261ecSmrg} ReplaceCursorLookupRec, *ReplaceCursorLookupPtr;
59505b261ecSmrg
59605b261ecSmrgstatic const RESTYPE    CursorRestypes[] = {
59705b261ecSmrg    RT_WINDOW, RT_PASSIVEGRAB, RT_CURSOR
59805b261ecSmrg};
59905b261ecSmrg
60005b261ecSmrg#define NUM_CURSOR_RESTYPES (sizeof (CursorRestypes) / sizeof (CursorRestypes[0]))
60105b261ecSmrg
60205b261ecSmrgstatic Bool
60305b261ecSmrgReplaceCursorLookup (pointer value, XID id, pointer closure)
60405b261ecSmrg{
60505b261ecSmrg    ReplaceCursorLookupPtr  rcl = (ReplaceCursorLookupPtr) closure;
60605b261ecSmrg    WindowPtr		    pWin;
60705b261ecSmrg    GrabPtr		    pGrab;
60805b261ecSmrg    CursorPtr		    pCursor = 0, *pCursorRef = 0;
60905b261ecSmrg    XID			    cursor = 0;
61005b261ecSmrg
61105b261ecSmrg    switch (rcl->type) {
61205b261ecSmrg    case RT_WINDOW:
61305b261ecSmrg	pWin = (WindowPtr) value;
61405b261ecSmrg	if (pWin->optional)
61505b261ecSmrg	{
61605b261ecSmrg	    pCursorRef = &pWin->optional->cursor;
61705b261ecSmrg	    pCursor = *pCursorRef;
61805b261ecSmrg	}
61905b261ecSmrg	break;
62005b261ecSmrg    case RT_PASSIVEGRAB:
62105b261ecSmrg	pGrab = (GrabPtr) value;
62205b261ecSmrg	pCursorRef = &pGrab->cursor;
62305b261ecSmrg	pCursor = *pCursorRef;
62405b261ecSmrg	break;
62505b261ecSmrg    case RT_CURSOR:
62605b261ecSmrg	pCursorRef = 0;
62705b261ecSmrg	pCursor = (CursorPtr) value;
62805b261ecSmrg	cursor = id;
62905b261ecSmrg	break;
63005b261ecSmrg    }
63105b261ecSmrg    if (pCursor && pCursor != rcl->pNew)
63205b261ecSmrg    {
63305b261ecSmrg	if ((*rcl->testCursor) (pCursor, rcl->closure))
63405b261ecSmrg	{
63505b261ecSmrg	    rcl->pNew->refcnt++;
63605b261ecSmrg	    /* either redirect reference or update resource database */
63705b261ecSmrg	    if (pCursorRef)
63805b261ecSmrg		*pCursorRef = rcl->pNew;
63905b261ecSmrg	    else
64005b261ecSmrg		ChangeResourceValue (id, RT_CURSOR, rcl->pNew);
64105b261ecSmrg	    FreeCursor (pCursor, cursor);
64205b261ecSmrg	}
64305b261ecSmrg    }
64405b261ecSmrg    return FALSE;   /* keep walking */
64505b261ecSmrg}
64605b261ecSmrg
64705b261ecSmrgstatic void
64805b261ecSmrgReplaceCursor (CursorPtr pCursor,
64905b261ecSmrg	       TestCursorFunc testCursor,
65005b261ecSmrg	       pointer closure)
65105b261ecSmrg{
65205b261ecSmrg    int	clientIndex;
65305b261ecSmrg    int resIndex;
65405b261ecSmrg    ReplaceCursorLookupRec  rcl;
65505b261ecSmrg
65605b261ecSmrg    /*
65705b261ecSmrg     * Cursors exist only in the resource database, windows and grabs.
65805b261ecSmrg     * All of these are always pointed at by the resource database.  Walk
65905b261ecSmrg     * the whole thing looking for cursors
66005b261ecSmrg     */
66105b261ecSmrg    rcl.testCursor = testCursor;
66205b261ecSmrg    rcl.pNew = pCursor;
66305b261ecSmrg    rcl.closure = closure;
66405b261ecSmrg
66505b261ecSmrg    /* for each client */
66605b261ecSmrg    for (clientIndex = 0; clientIndex < currentMaxClients; clientIndex++)
66705b261ecSmrg    {
66805b261ecSmrg	if (!clients[clientIndex])
66905b261ecSmrg	    continue;
67005b261ecSmrg	for (resIndex = 0; resIndex < NUM_CURSOR_RESTYPES; resIndex++)
67105b261ecSmrg	{
67205b261ecSmrg	    rcl.type = CursorRestypes[resIndex];
67305b261ecSmrg	    /*
67405b261ecSmrg	     * This function walks the entire client resource database
67505b261ecSmrg	     */
67605b261ecSmrg	    LookupClientResourceComplex (clients[clientIndex],
67705b261ecSmrg					 rcl.type,
67805b261ecSmrg					 ReplaceCursorLookup,
67905b261ecSmrg					 (pointer) &rcl);
68005b261ecSmrg	}
68105b261ecSmrg    }
68205b261ecSmrg    /* this "knows" that WindowHasNewCursor doesn't depend on it's argument */
68305b261ecSmrg    WindowHasNewCursor (WindowTable[0]);
68405b261ecSmrg}
68505b261ecSmrg
68605b261ecSmrgstatic Bool
68705b261ecSmrgTestForCursor (CursorPtr pCursor, pointer closure)
68805b261ecSmrg{
68905b261ecSmrg    return (pCursor == (CursorPtr) closure);
69005b261ecSmrg}
69105b261ecSmrg
69205b261ecSmrgint
69305b261ecSmrgProcXFixesChangeCursor (ClientPtr client)
69405b261ecSmrg{
69505b261ecSmrg    CursorPtr	pSource, pDestination;
69605b261ecSmrg    REQUEST(xXFixesChangeCursorReq);
69705b261ecSmrg
69805b261ecSmrg    REQUEST_SIZE_MATCH(xXFixesChangeCursorReq);
6994642e01fSmrg    VERIFY_CURSOR (pSource, stuff->source, client,
7004642e01fSmrg		   DixReadAccess|DixGetAttrAccess);
7014642e01fSmrg    VERIFY_CURSOR (pDestination, stuff->destination, client,
7024642e01fSmrg		   DixWriteAccess|DixSetAttrAccess);
70305b261ecSmrg
70405b261ecSmrg    ReplaceCursor (pSource, TestForCursor, (pointer) pDestination);
70505b261ecSmrg    return (client->noClientException);
70605b261ecSmrg}
70705b261ecSmrg
70805b261ecSmrgint
70905b261ecSmrgSProcXFixesChangeCursor (ClientPtr client)
71005b261ecSmrg{
71105b261ecSmrg    int n;
71205b261ecSmrg    REQUEST(xXFixesChangeCursorReq);
71305b261ecSmrg
71405b261ecSmrg    swaps (&stuff->length, n);
71505b261ecSmrg    REQUEST_SIZE_MATCH(xXFixesChangeCursorReq);
71605b261ecSmrg    swapl (&stuff->source, n);
71705b261ecSmrg    swapl (&stuff->destination, n);
71805b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
71905b261ecSmrg}
72005b261ecSmrg
72105b261ecSmrgstatic Bool
72205b261ecSmrgTestForCursorName (CursorPtr pCursor, pointer closure)
72305b261ecSmrg{
7244642e01fSmrg    Atom *pName = closure;
7254642e01fSmrg    return (pCursor->name == *pName);
72605b261ecSmrg}
72705b261ecSmrg
72805b261ecSmrgint
72905b261ecSmrgProcXFixesChangeCursorByName (ClientPtr client)
73005b261ecSmrg{
73105b261ecSmrg    CursorPtr	pSource;
73205b261ecSmrg    Atom	name;
73305b261ecSmrg    char	*tchar;
73405b261ecSmrg    REQUEST(xXFixesChangeCursorByNameReq);
73505b261ecSmrg
73605b261ecSmrg    REQUEST_FIXED_SIZE(xXFixesChangeCursorByNameReq, stuff->nbytes);
7374642e01fSmrg    VERIFY_CURSOR(pSource, stuff->source, client,
7384642e01fSmrg		  DixReadAccess|DixGetAttrAccess);
73905b261ecSmrg    tchar = (char *) &stuff[1];
74005b261ecSmrg    name = MakeAtom (tchar, stuff->nbytes, FALSE);
74105b261ecSmrg    if (name)
7424642e01fSmrg	ReplaceCursor (pSource, TestForCursorName, &name);
74305b261ecSmrg    return (client->noClientException);
74405b261ecSmrg}
74505b261ecSmrg
74605b261ecSmrgint
74705b261ecSmrgSProcXFixesChangeCursorByName (ClientPtr client)
74805b261ecSmrg{
74905b261ecSmrg    int n;
75005b261ecSmrg    REQUEST(xXFixesChangeCursorByNameReq);
75105b261ecSmrg
75205b261ecSmrg    swaps (&stuff->length, n);
75305b261ecSmrg    REQUEST_AT_LEAST_SIZE (xXFixesChangeCursorByNameReq);
75405b261ecSmrg    swapl (&stuff->source, n);
75505b261ecSmrg    swaps (&stuff->nbytes, n);
75605b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
75705b261ecSmrg}
75805b261ecSmrg
75905b261ecSmrg/*
76005b261ecSmrg * Routines for manipulating the per-screen hide counts list.
76105b261ecSmrg * This list indicates which clients have requested cursor hiding
76205b261ecSmrg * for that screen.
76305b261ecSmrg */
76405b261ecSmrg
76505b261ecSmrg/* Return the screen's hide-counts list element for the given client */
76605b261ecSmrgstatic CursorHideCountPtr
76705b261ecSmrgfindCursorHideCount (ClientPtr pClient, ScreenPtr pScreen)
76805b261ecSmrg{
76905b261ecSmrg    CursorScreenPtr    cs = GetCursorScreen(pScreen);
77005b261ecSmrg    CursorHideCountPtr pChc;
77105b261ecSmrg
77205b261ecSmrg    for (pChc = cs->pCursorHideCounts; pChc != NULL; pChc = pChc->pNext) {
77305b261ecSmrg	if (pChc->pClient == pClient) {
77405b261ecSmrg	    return pChc;
77505b261ecSmrg	}
77605b261ecSmrg    }
77705b261ecSmrg
77805b261ecSmrg    return NULL;
77905b261ecSmrg}
78005b261ecSmrg
78105b261ecSmrgstatic int
78205b261ecSmrgcreateCursorHideCount (ClientPtr pClient, ScreenPtr pScreen)
78305b261ecSmrg{
78405b261ecSmrg    CursorScreenPtr    cs = GetCursorScreen(pScreen);
78505b261ecSmrg    CursorHideCountPtr pChc;
78605b261ecSmrg
78705b261ecSmrg    pChc = (CursorHideCountPtr) xalloc(sizeof(CursorHideCountRec));
78805b261ecSmrg    if (pChc == NULL) {
78905b261ecSmrg	return BadAlloc;
79005b261ecSmrg    }
79105b261ecSmrg    pChc->pClient = pClient;
79205b261ecSmrg    pChc->pScreen = pScreen;
79305b261ecSmrg    pChc->hideCount = 1;
79405b261ecSmrg    pChc->resource = FakeClientID(pClient->index);
79505b261ecSmrg    pChc->pNext = cs->pCursorHideCounts;
79605b261ecSmrg    cs->pCursorHideCounts = pChc;
79705b261ecSmrg
79805b261ecSmrg    /*
79905b261ecSmrg     * Create a resource for this element so it can be deleted
80005b261ecSmrg     * when the client goes away.
80105b261ecSmrg     */
80205b261ecSmrg    if (!AddResource (pChc->resource, CursorHideCountType,
80305b261ecSmrg		      (pointer) pChc)) {
80405b261ecSmrg	xfree(pChc);
80505b261ecSmrg	return BadAlloc;
80605b261ecSmrg    }
80705b261ecSmrg
80805b261ecSmrg    return Success;
80905b261ecSmrg}
81005b261ecSmrg
81105b261ecSmrg/*
81205b261ecSmrg * Delete the given hide-counts list element from its screen list.
81305b261ecSmrg */
81405b261ecSmrgstatic void
81505b261ecSmrgdeleteCursorHideCount (CursorHideCountPtr pChcToDel, ScreenPtr pScreen)
81605b261ecSmrg{
81705b261ecSmrg    CursorScreenPtr    cs = GetCursorScreen(pScreen);
81805b261ecSmrg    CursorHideCountPtr pChc, pNext;
81905b261ecSmrg    CursorHideCountPtr pChcLast = NULL;
82005b261ecSmrg
82105b261ecSmrg    pChc = cs->pCursorHideCounts;
82205b261ecSmrg    while (pChc != NULL) {
82305b261ecSmrg	pNext = pChc->pNext;
82405b261ecSmrg	if (pChc == pChcToDel) {
82505b261ecSmrg	    xfree(pChc);
82605b261ecSmrg	    if (pChcLast == NULL) {
82705b261ecSmrg		cs->pCursorHideCounts = pNext;
82805b261ecSmrg	    } else {
82905b261ecSmrg		pChcLast->pNext = pNext;
83005b261ecSmrg	    }
83105b261ecSmrg	    return;
83205b261ecSmrg	}
83305b261ecSmrg	pChcLast = pChc;
83405b261ecSmrg	pChc = pNext;
83505b261ecSmrg    }
83605b261ecSmrg}
83705b261ecSmrg
83805b261ecSmrg/*
83905b261ecSmrg * Delete all the hide-counts list elements for this screen.
84005b261ecSmrg */
84105b261ecSmrgstatic void
84205b261ecSmrgdeleteCursorHideCountsForScreen (ScreenPtr pScreen)
84305b261ecSmrg{
84405b261ecSmrg    CursorScreenPtr    cs = GetCursorScreen(pScreen);
84505b261ecSmrg    CursorHideCountPtr pChc, pTmp;
84605b261ecSmrg
84705b261ecSmrg    pChc = cs->pCursorHideCounts;
84805b261ecSmrg    while (pChc != NULL) {
84905b261ecSmrg	pTmp = pChc->pNext;
85005b261ecSmrg	FreeResource(pChc->resource, 0);
85105b261ecSmrg	pChc = pTmp;
85205b261ecSmrg    }
85305b261ecSmrg    cs->pCursorHideCounts = NULL;
85405b261ecSmrg}
85505b261ecSmrg
85605b261ecSmrgint
85705b261ecSmrgProcXFixesHideCursor (ClientPtr client)
85805b261ecSmrg{
85905b261ecSmrg    WindowPtr pWin;
86005b261ecSmrg    CursorHideCountPtr pChc;
86105b261ecSmrg    REQUEST(xXFixesHideCursorReq);
86205b261ecSmrg    int ret;
86305b261ecSmrg
86405b261ecSmrg    REQUEST_SIZE_MATCH (xXFixesHideCursorReq);
86505b261ecSmrg
8664642e01fSmrg    ret = dixLookupResource((pointer *)&pWin, stuff->window, RT_WINDOW,
8674642e01fSmrg			    client, DixGetAttrAccess);
8684642e01fSmrg    if (ret != Success) {
86905b261ecSmrg	client->errorValue = stuff->window;
8704642e01fSmrg	return (ret == BadValue) ? BadWindow : ret;
87105b261ecSmrg    }
87205b261ecSmrg
87305b261ecSmrg    /*
87405b261ecSmrg     * Has client hidden the cursor before on this screen?
87505b261ecSmrg     * If so, just increment the count.
87605b261ecSmrg     */
87705b261ecSmrg
87805b261ecSmrg    pChc = findCursorHideCount(client, pWin->drawable.pScreen);
87905b261ecSmrg    if (pChc != NULL) {
88005b261ecSmrg	pChc->hideCount++;
88105b261ecSmrg	return client->noClientException;
88205b261ecSmrg    }
88305b261ecSmrg
88405b261ecSmrg    /*
88505b261ecSmrg     * This is the first time this client has hid the cursor
88605b261ecSmrg     * for this screen.
88705b261ecSmrg     */
8884642e01fSmrg    ret = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen,
8894642e01fSmrg		   DixHideAccess);
8904642e01fSmrg    if (ret != Success)
8914642e01fSmrg	return ret;
8924642e01fSmrg
89305b261ecSmrg    ret = createCursorHideCount(client, pWin->drawable.pScreen);
89405b261ecSmrg
89505b261ecSmrg    if (ret == Success) {
8964642e01fSmrg        (void) CursorDisplayCursor(PickPointer(client), pWin->drawable.pScreen, CursorCurrent);
89705b261ecSmrg    }
89805b261ecSmrg
89905b261ecSmrg    return ret;
90005b261ecSmrg}
90105b261ecSmrg
90205b261ecSmrgint
90305b261ecSmrgSProcXFixesHideCursor (ClientPtr client)
90405b261ecSmrg{
90505b261ecSmrg    int n;
90605b261ecSmrg    REQUEST(xXFixesHideCursorReq);
90705b261ecSmrg
90805b261ecSmrg    swaps (&stuff->length, n);
90905b261ecSmrg    REQUEST_SIZE_MATCH (xXFixesHideCursorReq);
91005b261ecSmrg    swapl (&stuff->window, n);
91105b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
91205b261ecSmrg}
91305b261ecSmrg
91405b261ecSmrgint
91505b261ecSmrgProcXFixesShowCursor (ClientPtr client)
91605b261ecSmrg{
91705b261ecSmrg    WindowPtr pWin;
91805b261ecSmrg    CursorHideCountPtr pChc;
9194642e01fSmrg    int rc;
92005b261ecSmrg    REQUEST(xXFixesShowCursorReq);
92105b261ecSmrg
92205b261ecSmrg    REQUEST_SIZE_MATCH (xXFixesShowCursorReq);
92305b261ecSmrg
9244642e01fSmrg    rc = dixLookupResource((pointer *)&pWin, stuff->window, RT_WINDOW,
9254642e01fSmrg			   client, DixGetAttrAccess);
9264642e01fSmrg    if (rc != Success) {
92705b261ecSmrg	client->errorValue = stuff->window;
9284642e01fSmrg	return (rc == BadValue) ? BadWindow : rc;
92905b261ecSmrg    }
93005b261ecSmrg
93105b261ecSmrg    /*
93205b261ecSmrg     * Has client hidden the cursor on this screen?
93305b261ecSmrg     * If not, generate an error.
93405b261ecSmrg     */
93505b261ecSmrg    pChc = findCursorHideCount(client, pWin->drawable.pScreen);
93605b261ecSmrg    if (pChc == NULL) {
93705b261ecSmrg	return BadMatch;
93805b261ecSmrg    }
93905b261ecSmrg
9404642e01fSmrg    rc = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen,
9414642e01fSmrg		  DixShowAccess);
9424642e01fSmrg    if (rc != Success)
9434642e01fSmrg	return rc;
9444642e01fSmrg
94505b261ecSmrg    pChc->hideCount--;
94605b261ecSmrg    if (pChc->hideCount <= 0) {
94705b261ecSmrg	FreeResource(pChc->resource, 0);
94805b261ecSmrg    }
94905b261ecSmrg
95005b261ecSmrg    return (client->noClientException);
95105b261ecSmrg}
95205b261ecSmrg
95305b261ecSmrgint
95405b261ecSmrgSProcXFixesShowCursor (ClientPtr client)
95505b261ecSmrg{
95605b261ecSmrg    int n;
95705b261ecSmrg    REQUEST(xXFixesShowCursorReq);
95805b261ecSmrg
95905b261ecSmrg    swaps (&stuff->length, n);
96005b261ecSmrg    REQUEST_SIZE_MATCH (xXFixesShowCursorReq);
96105b261ecSmrg    swapl (&stuff->window, n);
96205b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
96305b261ecSmrg}
96405b261ecSmrg
96505b261ecSmrgstatic int
96605b261ecSmrgCursorFreeClient (pointer data, XID id)
96705b261ecSmrg{
96805b261ecSmrg    CursorEventPtr	old = (CursorEventPtr) data;
96905b261ecSmrg    CursorEventPtr	*prev, e;
97005b261ecSmrg
97105b261ecSmrg    for (prev = &cursorEvents; (e = *prev); prev = &e->next)
97205b261ecSmrg    {
97305b261ecSmrg	if (e == old)
97405b261ecSmrg	{
97505b261ecSmrg	    *prev = e->next;
97605b261ecSmrg	    xfree (e);
97705b261ecSmrg	    break;
97805b261ecSmrg	}
97905b261ecSmrg    }
98005b261ecSmrg    return 1;
98105b261ecSmrg}
98205b261ecSmrg
98305b261ecSmrgstatic int
98405b261ecSmrgCursorFreeHideCount (pointer data, XID id)
98505b261ecSmrg{
98605b261ecSmrg    CursorHideCountPtr pChc = (CursorHideCountPtr) data;
98705b261ecSmrg    ScreenPtr pScreen = pChc->pScreen;
98805b261ecSmrg
98905b261ecSmrg    deleteCursorHideCount(pChc, pChc->pScreen);
9904642e01fSmrg    (void) CursorDisplayCursor(inputInfo.pointer, pScreen, CursorCurrent);
99105b261ecSmrg
99205b261ecSmrg    return 1;
99305b261ecSmrg}
99405b261ecSmrg
99505b261ecSmrgstatic int
99605b261ecSmrgCursorFreeWindow (pointer data, XID id)
99705b261ecSmrg{
99805b261ecSmrg    WindowPtr		pWindow = (WindowPtr) data;
99905b261ecSmrg    CursorEventPtr	e, next;
100005b261ecSmrg
100105b261ecSmrg    for (e = cursorEvents; e; e = next)
100205b261ecSmrg    {
100305b261ecSmrg	next = e->next;
100405b261ecSmrg	if (e->pWindow == pWindow)
100505b261ecSmrg	{
100605b261ecSmrg	    FreeResource (e->clientResource, 0);
100705b261ecSmrg	}
100805b261ecSmrg    }
100905b261ecSmrg    return 1;
101005b261ecSmrg}
101105b261ecSmrg
101205b261ecSmrgstatic CursorPtr
101305b261ecSmrgcreateInvisibleCursor (void)
101405b261ecSmrg{
101505b261ecSmrg    CursorPtr pCursor;
101605b261ecSmrg    static unsigned int *psrcbits, *pmaskbits;
101705b261ecSmrg    CursorMetricRec cm;
10184642e01fSmrg    int rc;
101905b261ecSmrg
102005b261ecSmrg    psrcbits = (unsigned int *) xalloc(4);
102105b261ecSmrg    pmaskbits = (unsigned int *) xalloc(4);
102205b261ecSmrg    if (psrcbits == NULL || pmaskbits == NULL) {
102305b261ecSmrg	return NULL;
102405b261ecSmrg    }
102505b261ecSmrg    *psrcbits = 0;
102605b261ecSmrg    *pmaskbits = 0;
102705b261ecSmrg
102805b261ecSmrg    cm.width = 1;
102905b261ecSmrg    cm.height = 1;
103005b261ecSmrg    cm.xhot = 0;
103105b261ecSmrg    cm.yhot = 0;
103205b261ecSmrg
10334642e01fSmrg    rc = AllocARGBCursor(
103405b261ecSmrg	        (unsigned char *)psrcbits,
103505b261ecSmrg		(unsigned char *)pmaskbits,
10364642e01fSmrg		NULL, &cm,
10374642e01fSmrg		0, 0, 0,
103805b261ecSmrg		0, 0, 0,
10394642e01fSmrg		&pCursor, serverClient, (XID)0);
104005b261ecSmrg
104105b261ecSmrg    return pCursor;
104205b261ecSmrg}
104305b261ecSmrg
104405b261ecSmrgBool
104505b261ecSmrgXFixesCursorInit (void)
104605b261ecSmrg{
104705b261ecSmrg    int	i;
10484642e01fSmrg
10494642e01fSmrg    if (party_like_its_1989)
10504642e01fSmrg	CursorVisible = TRUE;
105105b261ecSmrg
105205b261ecSmrg    for (i = 0; i < screenInfo.numScreens; i++)
105305b261ecSmrg    {
105405b261ecSmrg	ScreenPtr	pScreen = screenInfo.screens[i];
105505b261ecSmrg	CursorScreenPtr	cs;
105605b261ecSmrg
105705b261ecSmrg	cs = (CursorScreenPtr) xalloc (sizeof (CursorScreenRec));
105805b261ecSmrg	if (!cs)
105905b261ecSmrg	    return FALSE;
106005b261ecSmrg	Wrap (cs, pScreen, CloseScreen, CursorCloseScreen);
106105b261ecSmrg	Wrap (cs, pScreen, DisplayCursor, CursorDisplayCursor);
106205b261ecSmrg	cs->pCursorHideCounts = NULL;
106305b261ecSmrg	SetCursorScreen (pScreen, cs);
106405b261ecSmrg    }
106505b261ecSmrg    CursorClientType = CreateNewResourceType(CursorFreeClient);
106605b261ecSmrg    CursorHideCountType = CreateNewResourceType(CursorFreeHideCount);
106705b261ecSmrg    CursorWindowType = CreateNewResourceType(CursorFreeWindow);
106805b261ecSmrg
106905b261ecSmrg    if (pInvisibleCursor == NULL) {
107005b261ecSmrg	pInvisibleCursor = createInvisibleCursor();
107105b261ecSmrg	if (pInvisibleCursor == NULL) {
107205b261ecSmrg	    return BadAlloc;
107305b261ecSmrg	}
107405b261ecSmrg    }
107505b261ecSmrg
107605b261ecSmrg    return CursorClientType && CursorWindowType;
107705b261ecSmrg}
107805b261ecSmrg
1079