cursor.c revision 4642e01f
105b261ecSmrg/***********************************************************
205b261ecSmrg
305b261ecSmrgCopyright 1987, 1998  The Open Group
405b261ecSmrg
505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its
605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that
705b261ecSmrgthe above copyright notice appear in all copies and that both that
805b261ecSmrgcopyright notice and this permission notice appear in supporting
905b261ecSmrgdocumentation.
1005b261ecSmrg
1105b261ecSmrgThe above copyright notice and this permission notice shall be included in
1205b261ecSmrgall copies or substantial portions of the Software.
1305b261ecSmrg
1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1505b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1605b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1705b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1805b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1905b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2005b261ecSmrg
2105b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be
2205b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings
2305b261ecSmrgin this Software without prior written authorization from The Open Group.
2405b261ecSmrg
2505b261ecSmrg
2605b261ecSmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
2705b261ecSmrg
2805b261ecSmrg                        All Rights Reserved
2905b261ecSmrg
3005b261ecSmrgPermission to use, copy, modify, and distribute this software and its
3105b261ecSmrgdocumentation for any purpose and without fee is hereby granted,
3205b261ecSmrgprovided that the above copyright notice appear in all copies and that
3305b261ecSmrgboth that copyright notice and this permission notice appear in
3405b261ecSmrgsupporting documentation, and that the name of Digital not be
3505b261ecSmrgused in advertising or publicity pertaining to distribution of the
3605b261ecSmrgsoftware without specific, written prior permission.
3705b261ecSmrg
3805b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
3905b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
4005b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
4105b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
4205b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
4305b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
4405b261ecSmrgSOFTWARE.
4505b261ecSmrg
4605b261ecSmrg******************************************************************/
4705b261ecSmrg
4805b261ecSmrg
4905b261ecSmrg
5005b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
5105b261ecSmrg#include <dix-config.h>
5205b261ecSmrg#endif
5305b261ecSmrg
5405b261ecSmrg#include <X11/X.h>
5505b261ecSmrg#include <X11/Xmd.h>
5605b261ecSmrg#include "servermd.h"
5705b261ecSmrg#include "scrnintstr.h"
5805b261ecSmrg#include "dixstruct.h"
5905b261ecSmrg#include "cursorstr.h"
6005b261ecSmrg#include "dixfontstr.h"
6105b261ecSmrg#include "opaque.h"
624642e01fSmrg#include "inputstr.h"
634642e01fSmrg#include "xace.h"
6405b261ecSmrg
6505b261ecSmrgtypedef struct _GlyphShare {
6605b261ecSmrg    FontPtr font;
6705b261ecSmrg    unsigned short sourceChar;
6805b261ecSmrg    unsigned short maskChar;
6905b261ecSmrg    CursorBitsPtr bits;
7005b261ecSmrg    struct _GlyphShare *next;
7105b261ecSmrg} GlyphShare, *GlyphSharePtr;
7205b261ecSmrg
7305b261ecSmrgstatic GlyphSharePtr sharedGlyphs = (GlyphSharePtr)NULL;
7405b261ecSmrg
7505b261ecSmrg#ifdef XFIXES
7605b261ecSmrgstatic CARD32	cursorSerial;
7705b261ecSmrg#endif
7805b261ecSmrg
7905b261ecSmrgstatic void
8005b261ecSmrgFreeCursorBits(CursorBitsPtr bits)
8105b261ecSmrg{
8205b261ecSmrg    if (--bits->refcnt > 0)
8305b261ecSmrg	return;
8405b261ecSmrg    xfree(bits->source);
8505b261ecSmrg    xfree(bits->mask);
8605b261ecSmrg#ifdef ARGB_CURSOR
8705b261ecSmrg    xfree(bits->argb);
8805b261ecSmrg#endif
8905b261ecSmrg    if (bits->refcnt == 0)
9005b261ecSmrg    {
9105b261ecSmrg	GlyphSharePtr *prev, this;
9205b261ecSmrg
9305b261ecSmrg	for (prev = &sharedGlyphs;
9405b261ecSmrg	     (this = *prev) && (this->bits != bits);
9505b261ecSmrg	     prev = &this->next)
9605b261ecSmrg	    ;
9705b261ecSmrg	if (this)
9805b261ecSmrg	{
9905b261ecSmrg	    *prev = this->next;
10005b261ecSmrg	    CloseFont(this->font, (Font)0);
10105b261ecSmrg	    xfree(this);
10205b261ecSmrg	}
1034642e01fSmrg	dixFreePrivates(bits->devPrivates);
10405b261ecSmrg	xfree(bits);
10505b261ecSmrg    }
10605b261ecSmrg}
10705b261ecSmrg
10805b261ecSmrg/**
10905b261ecSmrg * To be called indirectly by DeleteResource; must use exactly two args.
11005b261ecSmrg *
11105b261ecSmrg *  \param value must conform to DeleteType
11205b261ecSmrg */
11305b261ecSmrg_X_EXPORT int
11405b261ecSmrgFreeCursor(pointer value, XID cid)
11505b261ecSmrg{
11605b261ecSmrg    int		nscr;
11705b261ecSmrg    CursorPtr 	pCurs = (CursorPtr)value;
11805b261ecSmrg
11905b261ecSmrg    ScreenPtr	pscr;
1204642e01fSmrg    DeviceIntPtr pDev = NULL; /* unused anyway */
12105b261ecSmrg
1224642e01fSmrg    if ( --pCurs->refcnt != 0)
12305b261ecSmrg	return(Success);
12405b261ecSmrg
12505b261ecSmrg    for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
12605b261ecSmrg    {
12705b261ecSmrg	pscr = screenInfo.screens[nscr];
1284642e01fSmrg        (void)( *pscr->UnrealizeCursor)(pDev, pscr, pCurs);
12905b261ecSmrg    }
1304642e01fSmrg    dixFreePrivates(pCurs->devPrivates);
13105b261ecSmrg    FreeCursorBits(pCurs->bits);
13205b261ecSmrg    xfree( pCurs);
13305b261ecSmrg    return(Success);
13405b261ecSmrg}
13505b261ecSmrg
13605b261ecSmrg
13705b261ecSmrg/*
13805b261ecSmrg * We check for empty cursors so that we won't have to display them
13905b261ecSmrg */
14005b261ecSmrgstatic void
14105b261ecSmrgCheckForEmptyMask(CursorBitsPtr bits)
14205b261ecSmrg{
14305b261ecSmrg    unsigned char *msk = bits->mask;
14405b261ecSmrg    int n = BitmapBytePad(bits->width) * bits->height;
14505b261ecSmrg
14605b261ecSmrg    bits->emptyMask = FALSE;
14705b261ecSmrg    while(n--)
14805b261ecSmrg	if(*(msk++) != 0) return;
14905b261ecSmrg#ifdef ARGB_CURSOR
15005b261ecSmrg    if (bits->argb)
15105b261ecSmrg    {
15205b261ecSmrg	CARD32 *argb = bits->argb;
15305b261ecSmrg	int n = bits->width * bits->height;
15405b261ecSmrg	while (n--)
15505b261ecSmrg	    if (*argb++ & 0xff000000) return;
15605b261ecSmrg    }
15705b261ecSmrg#endif
15805b261ecSmrg    bits->emptyMask = TRUE;
15905b261ecSmrg}
16005b261ecSmrg
16105b261ecSmrg/**
16205b261ecSmrg * does nothing about the resource table, just creates the data structure.
16305b261ecSmrg * does not copy the src and mask bits
16405b261ecSmrg *
16505b261ecSmrg *  \param psrcbits  server-defined padding
16605b261ecSmrg *  \param pmaskbits server-defined padding
16705b261ecSmrg *  \param argb      no padding
16805b261ecSmrg */
1694642e01fSmrgint
1704642e01fSmrgAllocARGBCursor(unsigned char *psrcbits, unsigned char *pmaskbits,
1714642e01fSmrg		CARD32 *argb, CursorMetricPtr cm,
1724642e01fSmrg		unsigned foreRed, unsigned foreGreen, unsigned foreBlue,
1734642e01fSmrg		unsigned backRed, unsigned backGreen, unsigned backBlue,
1744642e01fSmrg		CursorPtr *ppCurs, ClientPtr client, XID cid)
17505b261ecSmrg{
17605b261ecSmrg    CursorBitsPtr  bits;
17705b261ecSmrg    CursorPtr 	pCurs;
1784642e01fSmrg    int		rc, nscr;
17905b261ecSmrg    ScreenPtr 	pscr;
1804642e01fSmrg    DeviceIntPtr pDev;
18105b261ecSmrg
1824642e01fSmrg    *ppCurs = NULL;
1834642e01fSmrg    pCurs = (CursorPtr)xcalloc(sizeof(CursorRec) + sizeof(CursorBits), 1);
18405b261ecSmrg    if (!pCurs)
18505b261ecSmrg    {
18605b261ecSmrg	xfree(psrcbits);
18705b261ecSmrg	xfree(pmaskbits);
1884642e01fSmrg	return BadAlloc;
18905b261ecSmrg    }
19005b261ecSmrg    bits = (CursorBitsPtr)((char *)pCurs + sizeof(CursorRec));
19105b261ecSmrg    bits->source = psrcbits;
19205b261ecSmrg    bits->mask = pmaskbits;
19305b261ecSmrg#ifdef ARGB_CURSOR
19405b261ecSmrg    bits->argb = argb;
19505b261ecSmrg#endif
19605b261ecSmrg    bits->width = cm->width;
19705b261ecSmrg    bits->height = cm->height;
19805b261ecSmrg    bits->xhot = cm->xhot;
19905b261ecSmrg    bits->yhot = cm->yhot;
2004642e01fSmrg    pCurs->refcnt = 1;
2014642e01fSmrg    bits->devPrivates = NULL;
20205b261ecSmrg    bits->refcnt = -1;
20305b261ecSmrg    CheckForEmptyMask(bits);
20405b261ecSmrg    pCurs->bits = bits;
20505b261ecSmrg#ifdef XFIXES
20605b261ecSmrg    pCurs->serialNumber = ++cursorSerial;
20705b261ecSmrg    pCurs->name = None;
20805b261ecSmrg#endif
20905b261ecSmrg
21005b261ecSmrg    pCurs->foreRed = foreRed;
21105b261ecSmrg    pCurs->foreGreen = foreGreen;
21205b261ecSmrg    pCurs->foreBlue = foreBlue;
21305b261ecSmrg
21405b261ecSmrg    pCurs->backRed = backRed;
21505b261ecSmrg    pCurs->backGreen = backGreen;
21605b261ecSmrg    pCurs->backBlue = backBlue;
21705b261ecSmrg
2184642e01fSmrg    pCurs->id = cid;
2194642e01fSmrg    pCurs->devPrivates = NULL;
2204642e01fSmrg
2214642e01fSmrg    /* security creation/labeling check */
2224642e01fSmrg    rc = XaceHook(XACE_RESOURCE_ACCESS, client, cid, RT_CURSOR,
2234642e01fSmrg		  pCurs, RT_NONE, NULL, DixCreateAccess);
2244642e01fSmrg    if (rc != Success) {
2254642e01fSmrg	dixFreePrivates(pCurs->devPrivates);
2264642e01fSmrg	FreeCursorBits(bits);
2274642e01fSmrg	xfree(pCurs);
2284642e01fSmrg	return rc;
2294642e01fSmrg    }
2304642e01fSmrg
23105b261ecSmrg    /*
23205b261ecSmrg     * realize the cursor for every screen
2334642e01fSmrg     * Do not change the refcnt, this will be changed when ChangeToCursor
2344642e01fSmrg     * actually changes the sprite.
23505b261ecSmrg     */
23605b261ecSmrg    for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
23705b261ecSmrg    {
2384642e01fSmrg        pscr = screenInfo.screens[nscr];
2394642e01fSmrg        for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
2404642e01fSmrg        {
2414642e01fSmrg            if (DevHasCursor(pDev))
2424642e01fSmrg            {
2434642e01fSmrg                if (!( *pscr->RealizeCursor)(pDev, pscr, pCurs))
2444642e01fSmrg                {
2454642e01fSmrg                    /* Realize failed for device pDev on screen pscr.
2464642e01fSmrg                     * We have to assume that for all devices before, realize
2474642e01fSmrg                     * worked. We need to rollback all devices so far on the
2484642e01fSmrg                     * current screen and then all devices on previous
2494642e01fSmrg                     * screens.
2504642e01fSmrg                     */
2514642e01fSmrg                    DeviceIntPtr pDevIt = inputInfo.devices; /*dev iterator*/
2524642e01fSmrg                    while(pDevIt && pDevIt != pDev)
2534642e01fSmrg                    {
2544642e01fSmrg                        if (DevHasCursor(pDevIt))
2554642e01fSmrg                            ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs);
2564642e01fSmrg                        pDevIt = pDevIt->next;
2574642e01fSmrg                    }
2584642e01fSmrg                    while (--nscr >= 0)
2594642e01fSmrg                    {
2604642e01fSmrg                        pscr = screenInfo.screens[nscr];
2614642e01fSmrg                        /* now unrealize all devices on previous screens */
2624642e01fSmrg                        pDevIt = inputInfo.devices;
2634642e01fSmrg                        while (pDevIt)
2644642e01fSmrg                        {
2654642e01fSmrg                            if (DevHasCursor(pDevIt))
2664642e01fSmrg                                ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs);
2674642e01fSmrg                            pDevIt = pDevIt->next;
2684642e01fSmrg                        }
2694642e01fSmrg                        ( *pscr->UnrealizeCursor)(pDev, pscr, pCurs);
2704642e01fSmrg                    }
2714642e01fSmrg                    dixFreePrivates(pCurs->devPrivates);
2724642e01fSmrg                    FreeCursorBits(bits);
2734642e01fSmrg                    xfree(pCurs);
2744642e01fSmrg                    return BadAlloc;
2754642e01fSmrg                }
2764642e01fSmrg            }
2774642e01fSmrg        }
27805b261ecSmrg    }
2794642e01fSmrg    *ppCurs = pCurs;
2804642e01fSmrg    return rc;
28105b261ecSmrg}
28205b261ecSmrg
28305b261ecSmrgint
28405b261ecSmrgAllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
28505b261ecSmrg                unsigned foreRed, unsigned foreGreen, unsigned foreBlue,
28605b261ecSmrg                unsigned backRed, unsigned backGreen, unsigned backBlue,
2874642e01fSmrg		CursorPtr *ppCurs, ClientPtr client, XID cid)
28805b261ecSmrg{
28905b261ecSmrg    FontPtr  sourcefont, maskfont;
29005b261ecSmrg    unsigned char   *srcbits;
29105b261ecSmrg    unsigned char   *mskbits;
29205b261ecSmrg    CursorMetricRec cm;
2934642e01fSmrg    int rc;
29405b261ecSmrg    CursorBitsPtr  bits;
29505b261ecSmrg    CursorPtr 	pCurs;
29605b261ecSmrg    int		nscr;
29705b261ecSmrg    ScreenPtr 	pscr;
29805b261ecSmrg    GlyphSharePtr pShare;
2994642e01fSmrg    DeviceIntPtr pDev;
30005b261ecSmrg
3014642e01fSmrg    rc = dixLookupResource((pointer *)&sourcefont, source, RT_FONT, client,
3024642e01fSmrg			   DixUseAccess);
3034642e01fSmrg    if (rc != Success)
30405b261ecSmrg    {
30505b261ecSmrg	client->errorValue = source;
3064642e01fSmrg	return (rc == BadValue) ? BadFont : rc;
30705b261ecSmrg    }
3084642e01fSmrg    rc = dixLookupResource((pointer *)&maskfont, mask, RT_FONT, client,
3094642e01fSmrg			   DixUseAccess);
3104642e01fSmrg    if (rc != Success && mask != None)
31105b261ecSmrg    {
31205b261ecSmrg	client->errorValue = mask;
3134642e01fSmrg	return (rc == BadValue) ? BadFont : rc;
31405b261ecSmrg    }
31505b261ecSmrg    if (sourcefont != maskfont)
31605b261ecSmrg	pShare = (GlyphSharePtr)NULL;
31705b261ecSmrg    else
31805b261ecSmrg    {
31905b261ecSmrg	for (pShare = sharedGlyphs;
32005b261ecSmrg	     pShare &&
32105b261ecSmrg	     ((pShare->font != sourcefont) ||
32205b261ecSmrg	      (pShare->sourceChar != sourceChar) ||
32305b261ecSmrg	      (pShare->maskChar != maskChar));
32405b261ecSmrg	     pShare = pShare->next)
32505b261ecSmrg	    ;
32605b261ecSmrg    }
32705b261ecSmrg    if (pShare)
32805b261ecSmrg    {
3294642e01fSmrg	pCurs = (CursorPtr)xcalloc(sizeof(CursorRec), 1);
33005b261ecSmrg	if (!pCurs)
33105b261ecSmrg	    return BadAlloc;
33205b261ecSmrg	bits = pShare->bits;
33305b261ecSmrg	bits->refcnt++;
33405b261ecSmrg    }
33505b261ecSmrg    else
33605b261ecSmrg    {
33705b261ecSmrg	if (!CursorMetricsFromGlyph(sourcefont, sourceChar, &cm))
33805b261ecSmrg	{
33905b261ecSmrg	    client->errorValue = sourceChar;
34005b261ecSmrg	    return BadValue;
34105b261ecSmrg	}
34205b261ecSmrg	if (!maskfont)
34305b261ecSmrg	{
34405b261ecSmrg	    long n;
34505b261ecSmrg	    unsigned char *mskptr;
34605b261ecSmrg
34705b261ecSmrg	    n = BitmapBytePad(cm.width)*(long)cm.height;
34805b261ecSmrg	    mskptr = mskbits = (unsigned char *)xalloc(n);
34905b261ecSmrg	    if (!mskptr)
35005b261ecSmrg		return BadAlloc;
35105b261ecSmrg	    while (--n >= 0)
35205b261ecSmrg		*mskptr++ = ~0;
35305b261ecSmrg	}
35405b261ecSmrg	else
35505b261ecSmrg	{
35605b261ecSmrg	    if (!CursorMetricsFromGlyph(maskfont, maskChar, &cm))
35705b261ecSmrg	    {
35805b261ecSmrg		client->errorValue = maskChar;
35905b261ecSmrg		return BadValue;
36005b261ecSmrg	    }
3614642e01fSmrg	    if ((rc = ServerBitsFromGlyph(maskfont, maskChar, &cm, &mskbits)))
3624642e01fSmrg		return rc;
36305b261ecSmrg	}
3644642e01fSmrg	if ((rc = ServerBitsFromGlyph(sourcefont, sourceChar, &cm, &srcbits)))
36505b261ecSmrg	{
36605b261ecSmrg	    xfree(mskbits);
3674642e01fSmrg	    return rc;
36805b261ecSmrg	}
36905b261ecSmrg	if (sourcefont != maskfont)
37005b261ecSmrg	{
3714642e01fSmrg	    pCurs =
3724642e01fSmrg                (CursorPtr)xcalloc(sizeof(CursorRec) + sizeof(CursorBits), 1);
37305b261ecSmrg	    if (pCurs)
37405b261ecSmrg		bits = (CursorBitsPtr)((char *)pCurs + sizeof(CursorRec));
37505b261ecSmrg	    else
37605b261ecSmrg		bits = (CursorBitsPtr)NULL;
37705b261ecSmrg	}
37805b261ecSmrg	else
37905b261ecSmrg	{
3804642e01fSmrg	    pCurs = (CursorPtr)xcalloc(sizeof(CursorRec), 1);
38105b261ecSmrg	    if (pCurs)
3824642e01fSmrg		bits = (CursorBitsPtr)xcalloc(sizeof(CursorBits), 1);
38305b261ecSmrg	    else
38405b261ecSmrg		bits = (CursorBitsPtr)NULL;
38505b261ecSmrg	}
38605b261ecSmrg	if (!bits)
38705b261ecSmrg	{
38805b261ecSmrg	    xfree(pCurs);
38905b261ecSmrg	    xfree(mskbits);
39005b261ecSmrg	    xfree(srcbits);
39105b261ecSmrg	    return BadAlloc;
39205b261ecSmrg	}
39305b261ecSmrg	bits->source = srcbits;
39405b261ecSmrg	bits->mask = mskbits;
39505b261ecSmrg#ifdef ARGB_CURSOR
39605b261ecSmrg	bits->argb = 0;
39705b261ecSmrg#endif
39805b261ecSmrg	bits->width = cm.width;
39905b261ecSmrg	bits->height = cm.height;
40005b261ecSmrg	bits->xhot = cm.xhot;
40105b261ecSmrg	bits->yhot = cm.yhot;
4024642e01fSmrg	bits->devPrivates = NULL;
40305b261ecSmrg	if (sourcefont != maskfont)
40405b261ecSmrg	    bits->refcnt = -1;
40505b261ecSmrg	else
40605b261ecSmrg	{
40705b261ecSmrg	    bits->refcnt = 1;
40805b261ecSmrg	    pShare = (GlyphSharePtr)xalloc(sizeof(GlyphShare));
40905b261ecSmrg	    if (!pShare)
41005b261ecSmrg	    {
41105b261ecSmrg		FreeCursorBits(bits);
41205b261ecSmrg		return BadAlloc;
41305b261ecSmrg	    }
41405b261ecSmrg	    pShare->font = sourcefont;
41505b261ecSmrg	    sourcefont->refcnt++;
41605b261ecSmrg	    pShare->sourceChar = sourceChar;
41705b261ecSmrg	    pShare->maskChar = maskChar;
41805b261ecSmrg	    pShare->bits = bits;
41905b261ecSmrg	    pShare->next = sharedGlyphs;
42005b261ecSmrg	    sharedGlyphs = pShare;
42105b261ecSmrg	}
42205b261ecSmrg    }
4234642e01fSmrg
42405b261ecSmrg    CheckForEmptyMask(bits);
42505b261ecSmrg    pCurs->bits = bits;
42605b261ecSmrg    pCurs->refcnt = 1;
42705b261ecSmrg#ifdef XFIXES
42805b261ecSmrg    pCurs->serialNumber = ++cursorSerial;
42905b261ecSmrg    pCurs->name = None;
43005b261ecSmrg#endif
43105b261ecSmrg
43205b261ecSmrg    pCurs->foreRed = foreRed;
43305b261ecSmrg    pCurs->foreGreen = foreGreen;
43405b261ecSmrg    pCurs->foreBlue = foreBlue;
43505b261ecSmrg
43605b261ecSmrg    pCurs->backRed = backRed;
43705b261ecSmrg    pCurs->backGreen = backGreen;
43805b261ecSmrg    pCurs->backBlue = backBlue;
43905b261ecSmrg
4404642e01fSmrg    pCurs->id = cid;
4414642e01fSmrg    pCurs->devPrivates = NULL;
4424642e01fSmrg
4434642e01fSmrg    /* security creation/labeling check */
4444642e01fSmrg    rc = XaceHook(XACE_RESOURCE_ACCESS, client, cid, RT_CURSOR,
4454642e01fSmrg		  pCurs, RT_NONE, NULL, DixCreateAccess);
4464642e01fSmrg    if (rc != Success) {
4474642e01fSmrg	dixFreePrivates(pCurs->devPrivates);
4484642e01fSmrg	FreeCursorBits(bits);
4494642e01fSmrg	xfree(pCurs);
4504642e01fSmrg	return rc;
4514642e01fSmrg    }
4524642e01fSmrg
45305b261ecSmrg    /*
45405b261ecSmrg     * realize the cursor for every screen
45505b261ecSmrg     */
45605b261ecSmrg    for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
45705b261ecSmrg    {
4584642e01fSmrg        pscr = screenInfo.screens[nscr];
4594642e01fSmrg
4604642e01fSmrg        for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
4614642e01fSmrg        {
4624642e01fSmrg            if (DevHasCursor(pDev))
4634642e01fSmrg            {
4644642e01fSmrg                if (!( *pscr->RealizeCursor)(pDev, pscr, pCurs))
4654642e01fSmrg                {
4664642e01fSmrg                    /* Realize failed for device pDev on screen pscr.
4674642e01fSmrg                     * We have to assume that for all devices before, realize
4684642e01fSmrg                     * worked. We need to rollback all devices so far on the
4694642e01fSmrg                     * current screen and then all devices on previous
4704642e01fSmrg                     * screens.
4714642e01fSmrg                     */
4724642e01fSmrg                    DeviceIntPtr pDevIt = inputInfo.devices; /*dev iterator*/
4734642e01fSmrg                    while(pDevIt && pDevIt != pDev)
4744642e01fSmrg                    {
4754642e01fSmrg                        if (DevHasCursor(pDevIt))
4764642e01fSmrg                            ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs);
4774642e01fSmrg                        pDevIt = pDevIt->next;
4784642e01fSmrg                    }
4794642e01fSmrg
4804642e01fSmrg                    (*pscr->UnrealizeCursor)(inputInfo.pointer, pscr, pCurs);
4814642e01fSmrg
4824642e01fSmrg                    while (--nscr >= 0)
4834642e01fSmrg                    {
4844642e01fSmrg                        pscr = screenInfo.screens[nscr];
4854642e01fSmrg                        /* now unrealize all devices on previous screens */
4864642e01fSmrg                        ( *pscr->UnrealizeCursor)(inputInfo.pointer, pscr, pCurs);
4874642e01fSmrg
4884642e01fSmrg                        pDevIt = inputInfo.devices;
4894642e01fSmrg                        while (pDevIt)
4904642e01fSmrg                        {
4914642e01fSmrg                            if (DevHasCursor(pDevIt))
4924642e01fSmrg                                ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs);
4934642e01fSmrg                            pDevIt = pDevIt->next;
4944642e01fSmrg                        }
4954642e01fSmrg                        ( *pscr->UnrealizeCursor)(pDev, pscr, pCurs);
4964642e01fSmrg                    }
4974642e01fSmrg                    dixFreePrivates(pCurs->devPrivates);
4984642e01fSmrg                    FreeCursorBits(bits);
4994642e01fSmrg                    xfree(pCurs);
5004642e01fSmrg                    return BadAlloc;
5014642e01fSmrg                }
5024642e01fSmrg            }
5034642e01fSmrg        }
50405b261ecSmrg    }
50505b261ecSmrg    *ppCurs = pCurs;
50605b261ecSmrg    return Success;
50705b261ecSmrg}
50805b261ecSmrg
50905b261ecSmrg/** CreateRootCursor
51005b261ecSmrg *
51105b261ecSmrg * look up the name of a font
51205b261ecSmrg * open the font
51305b261ecSmrg * add the font to the resource table
51405b261ecSmrg * make a cursor from the glyphs
51505b261ecSmrg * add the cursor to the resource table
51605b261ecSmrg *************************************************************/
51705b261ecSmrg
51805b261ecSmrgCursorPtr
51905b261ecSmrgCreateRootCursor(char *unused1, unsigned int unused2)
52005b261ecSmrg{
52105b261ecSmrg    CursorPtr 	curs;
52205b261ecSmrg#ifdef NULL_ROOT_CURSOR
52305b261ecSmrg    CursorMetricRec cm;
52405b261ecSmrg#else
52505b261ecSmrg    FontPtr 	cursorfont;
52605b261ecSmrg    int	err;
52705b261ecSmrg    XID		fontID;
52805b261ecSmrg#endif
52905b261ecSmrg
53005b261ecSmrg#ifdef NULL_ROOT_CURSOR
53105b261ecSmrg    cm.width = 0;
53205b261ecSmrg    cm.height = 0;
53305b261ecSmrg    cm.xhot = 0;
53405b261ecSmrg    cm.yhot = 0;
53505b261ecSmrg
5364642e01fSmrg    AllocARGBCursor(NULL, NULL, NULL, &cm, 0, 0, 0, 0, 0, 0,
5374642e01fSmrg		    &curs, serverClient, (XID)0);
53805b261ecSmrg
53905b261ecSmrg    if (curs == NullCursor)
54005b261ecSmrg        return NullCursor;
54105b261ecSmrg#else
54205b261ecSmrg    fontID = FakeClientID(0);
54305b261ecSmrg    err = OpenFont(serverClient, fontID, FontLoadAll | FontOpenSync,
54405b261ecSmrg	(unsigned)strlen(defaultCursorFont), defaultCursorFont);
54505b261ecSmrg    if (err != Success)
54605b261ecSmrg	return NullCursor;
54705b261ecSmrg
54805b261ecSmrg    cursorfont = (FontPtr)LookupIDByType(fontID, RT_FONT);
54905b261ecSmrg    if (!cursorfont)
55005b261ecSmrg	return NullCursor;
5514642e01fSmrg    if (AllocGlyphCursor(fontID, 0, fontID, 1, 0, 0, 0, ~0, ~0, ~0,
5524642e01fSmrg			 &curs, serverClient, (XID)0) != Success)
55305b261ecSmrg	return NullCursor;
55405b261ecSmrg#endif
55505b261ecSmrg
55605b261ecSmrg    if (!AddResource(FakeClientID(0), RT_CURSOR, (pointer)curs))
55705b261ecSmrg	return NullCursor;
55805b261ecSmrg
55905b261ecSmrg    return curs;
56005b261ecSmrg}
561