105b261ecSmrg/*
29ace9065Smrg * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
335c4bbdfSmrg * Copyright 2010 Red Hat, Inc.
405b261ecSmrg *
56747b715Smrg * Permission is hereby granted, free of charge, to any person obtaining a
66747b715Smrg * copy of this software and associated documentation files (the "Software"),
76747b715Smrg * to deal in the Software without restriction, including without limitation
86747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
96747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the
106747b715Smrg * Software is furnished to do so, subject to the following conditions:
1105b261ecSmrg *
126747b715Smrg * The above copyright notice and this permission notice (including the next
136747b715Smrg * paragraph) shall be included in all copies or substantial portions of the
146747b715Smrg * Software.
156747b715Smrg *
166747b715Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
176747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
186747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
196747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
206747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
216747b715Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
226747b715Smrg * DEALINGS IN THE SOFTWARE.
2305b261ecSmrg *
2405b261ecSmrg * Copyright © 2002 Keith Packard
2505b261ecSmrg *
2605b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its
2705b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that
2805b261ecSmrg * the above copyright notice appear in all copies and that both that
2905b261ecSmrg * copyright notice and this permission notice appear in supporting
3005b261ecSmrg * documentation, and that the name of Keith Packard not be used in
3105b261ecSmrg * advertising or publicity pertaining to distribution of the software without
3205b261ecSmrg * specific, written prior permission.  Keith Packard makes no
3305b261ecSmrg * representations about the suitability of this software for any purpose.  It
3405b261ecSmrg * is provided "as is" without express or implied warranty.
3505b261ecSmrg *
3605b261ecSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
3705b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
3805b261ecSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
3905b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
4005b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
4105b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
4205b261ecSmrg * PERFORMANCE OF THIS SOFTWARE.
4305b261ecSmrg */
4405b261ecSmrg
4505b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
4605b261ecSmrg#include <dix-config.h>
4705b261ecSmrg#endif
4805b261ecSmrg
4905b261ecSmrg#include "xfixesint.h"
5005b261ecSmrg#include "scrnintstr.h"
5105b261ecSmrg#include "cursorstr.h"
5205b261ecSmrg#include "dixevents.h"
5305b261ecSmrg#include "servermd.h"
5435c4bbdfSmrg#include "mipointer.h"
5505b261ecSmrg#include "inputstr.h"
5605b261ecSmrg#include "windowstr.h"
574642e01fSmrg#include "xace.h"
5835c4bbdfSmrg#include "list.h"
5935c4bbdfSmrg#include "xibarriers.h"
6005b261ecSmrg
6135c4bbdfSmrgstatic RESTYPE CursorClientType;
6235c4bbdfSmrgstatic RESTYPE CursorHideCountType;
6335c4bbdfSmrgstatic RESTYPE CursorWindowType;
6405b261ecSmrg
656747b715Smrgstatic DevPrivateKeyRec CursorScreenPrivateKeyRec;
6635c4bbdfSmrg
676747b715Smrg#define CursorScreenPrivateKey (&CursorScreenPrivateKeyRec)
684642e01fSmrg
6935c4bbdfSmrgstatic void deleteCursorHideCountsForScreen(ScreenPtr pScreen);
7005b261ecSmrg
716747b715Smrg#define VERIFY_CURSOR(pCursor, cursor, client, access)			\
726747b715Smrg    do {								\
736747b715Smrg	int err;							\
7435c4bbdfSmrg	err = dixLookupResourceByType((void **) &pCursor, cursor,	\
756747b715Smrg				      RT_CURSOR, client, access);	\
766747b715Smrg	if (err != Success) {						\
776747b715Smrg	    client->errorValue = cursor;				\
786747b715Smrg	    return err;							\
796747b715Smrg	}								\
806747b715Smrg    } while (0)
814642e01fSmrg
8205b261ecSmrg/*
8305b261ecSmrg * There is a global list of windows selecting for cursor events
8405b261ecSmrg */
8505b261ecSmrg
8605b261ecSmrgtypedef struct _CursorEvent *CursorEventPtr;
8705b261ecSmrg
8805b261ecSmrgtypedef struct _CursorEvent {
8935c4bbdfSmrg    CursorEventPtr next;
9035c4bbdfSmrg    CARD32 eventMask;
9135c4bbdfSmrg    ClientPtr pClient;
9235c4bbdfSmrg    WindowPtr pWindow;
9335c4bbdfSmrg    XID clientResource;
9405b261ecSmrg} CursorEventRec;
9505b261ecSmrg
9635c4bbdfSmrgstatic CursorEventPtr cursorEvents;
9705b261ecSmrg
9805b261ecSmrg/*
9905b261ecSmrg * Each screen has a list of clients which have requested
10005b261ecSmrg * that the cursor be hid, and the number of times each
10105b261ecSmrg * client has requested.
10205b261ecSmrg*/
10305b261ecSmrg
10405b261ecSmrgtypedef struct _CursorHideCountRec *CursorHideCountPtr;
10505b261ecSmrg
10605b261ecSmrgtypedef struct _CursorHideCountRec {
10735c4bbdfSmrg    CursorHideCountPtr pNext;
10835c4bbdfSmrg    ClientPtr pClient;
10935c4bbdfSmrg    ScreenPtr pScreen;
11035c4bbdfSmrg    int hideCount;
11135c4bbdfSmrg    XID resource;
11205b261ecSmrg} CursorHideCountRec;
11305b261ecSmrg
11405b261ecSmrg/*
11505b261ecSmrg * Wrap DisplayCursor to catch cursor change events
11605b261ecSmrg */
11705b261ecSmrg
11805b261ecSmrgtypedef struct _CursorScreen {
11935c4bbdfSmrg    DisplayCursorProcPtr DisplayCursor;
12035c4bbdfSmrg    CloseScreenProcPtr CloseScreen;
12135c4bbdfSmrg    CursorHideCountPtr pCursorHideCounts;
12205b261ecSmrg} CursorScreenRec, *CursorScreenPtr;
12305b261ecSmrg
1244642e01fSmrg#define GetCursorScreen(s) ((CursorScreenPtr)dixLookupPrivate(&(s)->devPrivates, CursorScreenPrivateKey))
1254642e01fSmrg#define GetCursorScreenIfSet(s) GetCursorScreen(s)
1264642e01fSmrg#define SetCursorScreen(s,p) dixSetPrivate(&(s)->devPrivates, CursorScreenPrivateKey, p)
12705b261ecSmrg#define Wrap(as,s,elt,func)	(((as)->elt = (s)->elt), (s)->elt = func)
1286747b715Smrg#define Unwrap(as,s,elt,backup)	(((backup) = (s)->elt), (s)->elt = (as)->elt)
12905b261ecSmrg
1304642e01fSmrg/* The cursor doesn't show up until the first XDefineCursor() */
13135c4bbdfSmrgBool CursorVisible = FALSE;
1326747b715SmrgBool EnableCursor = TRUE;
1336747b715Smrg
1347e31ba66Smrgstatic CursorPtr
1357e31ba66SmrgCursorForDevice(DeviceIntPtr pDev)
1367e31ba66Smrg{
1377e31ba66Smrg    if (pDev && pDev->spriteInfo && pDev->spriteInfo->sprite) {
1387e31ba66Smrg        if (pDev->spriteInfo->anim.pCursor)
1397e31ba66Smrg            return pDev->spriteInfo->anim.pCursor;
1407e31ba66Smrg        return pDev->spriteInfo->sprite->current;
1417e31ba66Smrg    }
1427e31ba66Smrg
1437e31ba66Smrg    return NULL;
1447e31ba66Smrg}
1457e31ba66Smrg
1467e31ba66Smrgstatic CursorPtr
1477e31ba66SmrgCursorForClient(ClientPtr client)
1487e31ba66Smrg{
1497e31ba66Smrg    return CursorForDevice(PickPointer(client));
1507e31ba66Smrg}
1517e31ba66Smrg
15205b261ecSmrgstatic Bool
15335c4bbdfSmrgCursorDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
15405b261ecSmrg{
15535c4bbdfSmrg    CursorScreenPtr cs = GetCursorScreen(pScreen);
1567e31ba66Smrg    CursorPtr pOldCursor = CursorForDevice(pDev);
15735c4bbdfSmrg    Bool ret;
1586747b715Smrg    DisplayCursorProcPtr backupProc;
15905b261ecSmrg
16035c4bbdfSmrg    Unwrap(cs, pScreen, DisplayCursor, backupProc);
16105b261ecSmrg
16235c4bbdfSmrg    CursorVisible = CursorVisible && EnableCursor;
1634642e01fSmrg
1644642e01fSmrg    if (cs->pCursorHideCounts != NULL || !CursorVisible) {
16535c4bbdfSmrg        ret = (*pScreen->DisplayCursor) (pDev, pScreen, NullCursor);
16635c4bbdfSmrg    }
16735c4bbdfSmrg    else {
16835c4bbdfSmrg        ret = (*pScreen->DisplayCursor) (pDev, pScreen, pCursor);
16905b261ecSmrg    }
17005b261ecSmrg
1717e31ba66Smrg    if (pCursor != pOldCursor) {
17235c4bbdfSmrg        CursorEventPtr e;
17335c4bbdfSmrg
1747e31ba66Smrg        UpdateCurrentTimeIf();
17535c4bbdfSmrg        for (e = cursorEvents; e; e = e->next) {
17635c4bbdfSmrg            if ((e->eventMask & XFixesDisplayCursorNotifyMask)) {
17735c4bbdfSmrg                xXFixesCursorNotifyEvent ev = {
17835c4bbdfSmrg                    .type = XFixesEventBase + XFixesCursorNotify,
17935c4bbdfSmrg                    .subtype = XFixesDisplayCursorNotify,
18035c4bbdfSmrg                    .window = e->pWindow->drawable.id,
18135c4bbdfSmrg                    .cursorSerial = pCursor ? pCursor->serialNumber : 0,
18235c4bbdfSmrg                    .timestamp = currentTime.milliseconds,
18335c4bbdfSmrg                    .name = pCursor ? pCursor->name : None
18435c4bbdfSmrg                };
18535c4bbdfSmrg                WriteEventsToClient(e->pClient, 1, (xEvent *) &ev);
18635c4bbdfSmrg            }
18735c4bbdfSmrg        }
18805b261ecSmrg    }
18935c4bbdfSmrg    Wrap(cs, pScreen, DisplayCursor, backupProc);
1906747b715Smrg
19105b261ecSmrg    return ret;
19205b261ecSmrg}
19305b261ecSmrg
19405b261ecSmrgstatic Bool
19535c4bbdfSmrgCursorCloseScreen(ScreenPtr pScreen)
19605b261ecSmrg{
19735c4bbdfSmrg    CursorScreenPtr cs = GetCursorScreen(pScreen);
19835c4bbdfSmrg    Bool ret;
19935c4bbdfSmrg    _X_UNUSED CloseScreenProcPtr close_proc;
20035c4bbdfSmrg    _X_UNUSED DisplayCursorProcPtr display_proc;
20105b261ecSmrg
20235c4bbdfSmrg    Unwrap(cs, pScreen, CloseScreen, close_proc);
20335c4bbdfSmrg    Unwrap(cs, pScreen, DisplayCursor, display_proc);
20405b261ecSmrg    deleteCursorHideCountsForScreen(pScreen);
20535c4bbdfSmrg    ret = (*pScreen->CloseScreen) (pScreen);
2066747b715Smrg    free(cs);
20705b261ecSmrg    return ret;
20805b261ecSmrg}
20905b261ecSmrg
21005b261ecSmrg#define CursorAllEvents (XFixesDisplayCursorNotifyMask)
21105b261ecSmrg
21205b261ecSmrgstatic int
21335c4bbdfSmrgXFixesSelectCursorInput(ClientPtr pClient, WindowPtr pWindow, CARD32 eventMask)
21405b261ecSmrg{
21535c4bbdfSmrg    CursorEventPtr *prev, e;
21635c4bbdfSmrg    void *val;
2176747b715Smrg    int rc;
21805b261ecSmrg
21935c4bbdfSmrg    for (prev = &cursorEvents; (e = *prev); prev = &e->next) {
22035c4bbdfSmrg        if (e->pClient == pClient && e->pWindow == pWindow) {
22135c4bbdfSmrg            break;
22235c4bbdfSmrg        }
22305b261ecSmrg    }
22435c4bbdfSmrg    if (!eventMask) {
22535c4bbdfSmrg        if (e) {
22635c4bbdfSmrg            FreeResource(e->clientResource, 0);
22735c4bbdfSmrg        }
22835c4bbdfSmrg        return Success;
22905b261ecSmrg    }
23035c4bbdfSmrg    if (!e) {
23135c4bbdfSmrg        e = (CursorEventPtr) malloc(sizeof(CursorEventRec));
23235c4bbdfSmrg        if (!e)
23335c4bbdfSmrg            return BadAlloc;
23435c4bbdfSmrg
23535c4bbdfSmrg        e->next = 0;
23635c4bbdfSmrg        e->pClient = pClient;
23735c4bbdfSmrg        e->pWindow = pWindow;
23835c4bbdfSmrg        e->clientResource = FakeClientID(pClient->index);
23935c4bbdfSmrg
24035c4bbdfSmrg        /*
24135c4bbdfSmrg         * Add a resource hanging from the window to
24235c4bbdfSmrg         * catch window destroy
24335c4bbdfSmrg         */
24435c4bbdfSmrg        rc = dixLookupResourceByType(&val, pWindow->drawable.id,
24535c4bbdfSmrg                                     CursorWindowType, serverClient,
24635c4bbdfSmrg                                     DixGetAttrAccess);
24735c4bbdfSmrg        if (rc != Success)
24835c4bbdfSmrg            if (!AddResource(pWindow->drawable.id, CursorWindowType,
24935c4bbdfSmrg                             (void *) pWindow)) {
25035c4bbdfSmrg                free(e);
25135c4bbdfSmrg                return BadAlloc;
25235c4bbdfSmrg            }
25335c4bbdfSmrg
25435c4bbdfSmrg        if (!AddResource(e->clientResource, CursorClientType, (void *) e))
25535c4bbdfSmrg            return BadAlloc;
25635c4bbdfSmrg
25735c4bbdfSmrg        *prev = e;
25805b261ecSmrg    }
25905b261ecSmrg    e->eventMask = eventMask;
26005b261ecSmrg    return Success;
26105b261ecSmrg}
26205b261ecSmrg
26305b261ecSmrgint
26435c4bbdfSmrgProcXFixesSelectCursorInput(ClientPtr client)
26505b261ecSmrg{
26635c4bbdfSmrg    REQUEST(xXFixesSelectCursorInputReq);
26735c4bbdfSmrg    WindowPtr pWin;
26835c4bbdfSmrg    int rc;
26905b261ecSmrg
27035c4bbdfSmrg    REQUEST_SIZE_MATCH(xXFixesSelectCursorInputReq);
2714642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
27205b261ecSmrg    if (rc != Success)
27305b261ecSmrg        return rc;
27435c4bbdfSmrg    if (stuff->eventMask & ~CursorAllEvents) {
27535c4bbdfSmrg        client->errorValue = stuff->eventMask;
27635c4bbdfSmrg        return BadValue;
27705b261ecSmrg    }
27835c4bbdfSmrg    return XFixesSelectCursorInput(client, pWin, stuff->eventMask);
27905b261ecSmrg}
28005b261ecSmrg
28105b261ecSmrgstatic int
28235c4bbdfSmrgGetBit(unsigned char *line, int x)
28305b261ecSmrg{
28435c4bbdfSmrg    unsigned char mask;
28535c4bbdfSmrg
28605b261ecSmrg    if (screenInfo.bitmapBitOrder == LSBFirst)
28735c4bbdfSmrg        mask = (1 << (x & 7));
28805b261ecSmrg    else
28935c4bbdfSmrg        mask = (0x80 >> (x & 7));
29005b261ecSmrg    /* XXX assumes byte order is host byte order */
29105b261ecSmrg    line += (x >> 3);
29205b261ecSmrg    if (*line & mask)
29335c4bbdfSmrg        return 1;
29405b261ecSmrg    return 0;
29505b261ecSmrg}
29605b261ecSmrg
2977e31ba66Smrgint _X_COLD
29835c4bbdfSmrgSProcXFixesSelectCursorInput(ClientPtr client)
29905b261ecSmrg{
30005b261ecSmrg    REQUEST(xXFixesSelectCursorInputReq);
3016e78d31fSmrg    REQUEST_SIZE_MATCH(xXFixesSelectCursorInputReq);
30205b261ecSmrg
30335c4bbdfSmrg    swaps(&stuff->length);
30435c4bbdfSmrg    swapl(&stuff->window);
30535c4bbdfSmrg    swapl(&stuff->eventMask);
30605b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
30705b261ecSmrg}
30835c4bbdfSmrg
3097e31ba66Smrgvoid _X_COLD
31035c4bbdfSmrgSXFixesCursorNotifyEvent(xXFixesCursorNotifyEvent * from,
31135c4bbdfSmrg                         xXFixesCursorNotifyEvent * to)
31205b261ecSmrg{
31305b261ecSmrg    to->type = from->type;
31435c4bbdfSmrg    cpswaps(from->sequenceNumber, to->sequenceNumber);
31535c4bbdfSmrg    cpswapl(from->window, to->window);
31635c4bbdfSmrg    cpswapl(from->cursorSerial, to->cursorSerial);
31735c4bbdfSmrg    cpswapl(from->timestamp, to->timestamp);
31835c4bbdfSmrg    cpswapl(from->name, to->name);
31905b261ecSmrg}
32005b261ecSmrg
32105b261ecSmrgstatic void
32235c4bbdfSmrgCopyCursorToImage(CursorPtr pCursor, CARD32 *image)
32305b261ecSmrg{
32405b261ecSmrg    int width = pCursor->bits->width;
32505b261ecSmrg    int height = pCursor->bits->height;
32605b261ecSmrg    int npixels = width * height;
32735c4bbdfSmrg
32805b261ecSmrg    if (pCursor->bits->argb)
32935c4bbdfSmrg        memcpy(image, pCursor->bits->argb, npixels * sizeof(CARD32));
33005b261ecSmrg    else
33105b261ecSmrg    {
33235c4bbdfSmrg        unsigned char *srcLine = pCursor->bits->source;
33335c4bbdfSmrg        unsigned char *mskLine = pCursor->bits->mask;
33435c4bbdfSmrg        int stride = BitmapBytePad(width);
33535c4bbdfSmrg        int x, y;
33635c4bbdfSmrg        CARD32 fg, bg;
33735c4bbdfSmrg
33835c4bbdfSmrg        fg = (0xff000000 |
33935c4bbdfSmrg              ((pCursor->foreRed & 0xff00) << 8) |
34035c4bbdfSmrg              (pCursor->foreGreen & 0xff00) | (pCursor->foreBlue >> 8));
34135c4bbdfSmrg        bg = (0xff000000 |
34235c4bbdfSmrg              ((pCursor->backRed & 0xff00) << 8) |
34335c4bbdfSmrg              (pCursor->backGreen & 0xff00) | (pCursor->backBlue >> 8));
34435c4bbdfSmrg        for (y = 0; y < height; y++) {
34535c4bbdfSmrg            for (x = 0; x < width; x++) {
34635c4bbdfSmrg                if (GetBit(mskLine, x)) {
34735c4bbdfSmrg                    if (GetBit(srcLine, x))
34835c4bbdfSmrg                        *image++ = fg;
34935c4bbdfSmrg                    else
35035c4bbdfSmrg                        *image++ = bg;
35135c4bbdfSmrg                }
35235c4bbdfSmrg                else
35335c4bbdfSmrg                    *image++ = 0;
35435c4bbdfSmrg            }
35535c4bbdfSmrg            srcLine += stride;
35635c4bbdfSmrg            mskLine += stride;
35735c4bbdfSmrg        }
35805b261ecSmrg    }
35905b261ecSmrg}
36005b261ecSmrg
36105b261ecSmrgint
36235c4bbdfSmrgProcXFixesGetCursorImage(ClientPtr client)
36305b261ecSmrg{
36405b261ecSmrg/*    REQUEST(xXFixesGetCursorImageReq); */
36535c4bbdfSmrg    xXFixesGetCursorImageReply *rep;
36635c4bbdfSmrg    CursorPtr pCursor;
36735c4bbdfSmrg    CARD32 *image;
36835c4bbdfSmrg    int npixels, width, height, rc, x, y;
36905b261ecSmrg
37005b261ecSmrg    REQUEST_SIZE_MATCH(xXFixesGetCursorImageReq);
3717e31ba66Smrg    pCursor = CursorForClient(client);
37205b261ecSmrg    if (!pCursor)
37335c4bbdfSmrg        return BadCursor;
3744642e01fSmrg    rc = XaceHook(XACE_RESOURCE_ACCESS, client, pCursor->id, RT_CURSOR,
37535c4bbdfSmrg                  pCursor, RT_NONE, NULL, DixReadAccess);
3764642e01fSmrg    if (rc != Success)
37735c4bbdfSmrg        return rc;
37835c4bbdfSmrg    GetSpritePosition(PickPointer(client), &x, &y);
37905b261ecSmrg    width = pCursor->bits->width;
38005b261ecSmrg    height = pCursor->bits->height;
38105b261ecSmrg    npixels = width * height;
38235c4bbdfSmrg    rep = calloc(sizeof(xXFixesGetCursorImageReply) + npixels * sizeof(CARD32),
38335c4bbdfSmrg                 1);
38405b261ecSmrg    if (!rep)
38535c4bbdfSmrg        return BadAlloc;
38605b261ecSmrg
38705b261ecSmrg    rep->type = X_Reply;
38805b261ecSmrg    rep->sequenceNumber = client->sequence;
38905b261ecSmrg    rep->length = npixels;
39005b261ecSmrg    rep->width = width;
39105b261ecSmrg    rep->height = height;
39205b261ecSmrg    rep->x = x;
39305b261ecSmrg    rep->y = y;
39405b261ecSmrg    rep->xhot = pCursor->bits->xhot;
39535c4bbdfSmrg    rep->yhot = pCursor->bits->yhot;
39605b261ecSmrg    rep->cursorSerial = pCursor->serialNumber;
39705b261ecSmrg
39805b261ecSmrg    image = (CARD32 *) (rep + 1);
39935c4bbdfSmrg    CopyCursorToImage(pCursor, image);
40035c4bbdfSmrg    if (client->swapped) {
40135c4bbdfSmrg        swaps(&rep->sequenceNumber);
40235c4bbdfSmrg        swapl(&rep->length);
40335c4bbdfSmrg        swaps(&rep->x);
40435c4bbdfSmrg        swaps(&rep->y);
40535c4bbdfSmrg        swaps(&rep->width);
40635c4bbdfSmrg        swaps(&rep->height);
40735c4bbdfSmrg        swaps(&rep->xhot);
40835c4bbdfSmrg        swaps(&rep->yhot);
40935c4bbdfSmrg        swapl(&rep->cursorSerial);
41035c4bbdfSmrg        SwapLongs(image, npixels);
41105b261ecSmrg    }
41235c4bbdfSmrg    WriteToClient(client,
41335c4bbdfSmrg                  sizeof(xXFixesGetCursorImageReply) + (npixels << 2), rep);
4146747b715Smrg    free(rep);
4156747b715Smrg    return Success;
41605b261ecSmrg}
41705b261ecSmrg
4187e31ba66Smrgint _X_COLD
41935c4bbdfSmrgSProcXFixesGetCursorImage(ClientPtr client)
42005b261ecSmrg{
42105b261ecSmrg    REQUEST(xXFixesGetCursorImageReq);
42235c4bbdfSmrg    swaps(&stuff->length);
42305b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
42405b261ecSmrg}
42505b261ecSmrg
42605b261ecSmrgint
42735c4bbdfSmrgProcXFixesSetCursorName(ClientPtr client)
42805b261ecSmrg{
42905b261ecSmrg    CursorPtr pCursor;
43005b261ecSmrg    char *tchar;
43135c4bbdfSmrg
43205b261ecSmrg    REQUEST(xXFixesSetCursorNameReq);
43305b261ecSmrg    Atom atom;
43405b261ecSmrg
4356e78d31fSmrg    REQUEST_FIXED_SIZE(xXFixesSetCursorNameReq, stuff->nbytes);
4364642e01fSmrg    VERIFY_CURSOR(pCursor, stuff->cursor, client, DixSetAttrAccess);
43705b261ecSmrg    tchar = (char *) &stuff[1];
43835c4bbdfSmrg    atom = MakeAtom(tchar, stuff->nbytes, TRUE);
43905b261ecSmrg    if (atom == BAD_RESOURCE)
44035c4bbdfSmrg        return BadAlloc;
44135c4bbdfSmrg
44205b261ecSmrg    pCursor->name = atom;
4436747b715Smrg    return Success;
44405b261ecSmrg}
44505b261ecSmrg
4467e31ba66Smrgint _X_COLD
44735c4bbdfSmrgSProcXFixesSetCursorName(ClientPtr client)
44805b261ecSmrg{
44905b261ecSmrg    REQUEST(xXFixesSetCursorNameReq);
45005b261ecSmrg
45135c4bbdfSmrg    swaps(&stuff->length);
45205b261ecSmrg    REQUEST_AT_LEAST_SIZE(xXFixesSetCursorNameReq);
45335c4bbdfSmrg    swapl(&stuff->cursor);
45435c4bbdfSmrg    swaps(&stuff->nbytes);
45505b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
45605b261ecSmrg}
45705b261ecSmrg
45805b261ecSmrgint
45935c4bbdfSmrgProcXFixesGetCursorName(ClientPtr client)
46005b261ecSmrg{
46135c4bbdfSmrg    CursorPtr pCursor;
46235c4bbdfSmrg    xXFixesGetCursorNameReply reply;
46335c4bbdfSmrg
46405b261ecSmrg    REQUEST(xXFixesGetCursorNameReq);
4656747b715Smrg    const char *str;
46605b261ecSmrg    int len;
46705b261ecSmrg
46805b261ecSmrg    REQUEST_SIZE_MATCH(xXFixesGetCursorNameReq);
4694642e01fSmrg    VERIFY_CURSOR(pCursor, stuff->cursor, client, DixGetAttrAccess);
47005b261ecSmrg    if (pCursor->name)
47135c4bbdfSmrg        str = NameForAtom(pCursor->name);
47205b261ecSmrg    else
47335c4bbdfSmrg        str = "";
47435c4bbdfSmrg    len = strlen(str);
47535c4bbdfSmrg
47635c4bbdfSmrg    reply = (xXFixesGetCursorNameReply) {
47735c4bbdfSmrg        .type = X_Reply,
47835c4bbdfSmrg        .sequenceNumber = client->sequence,
47935c4bbdfSmrg        .length = bytes_to_int32(len),
48035c4bbdfSmrg        .atom = pCursor->name,
48135c4bbdfSmrg        .nbytes = len
48235c4bbdfSmrg    };
48335c4bbdfSmrg    if (client->swapped) {
48435c4bbdfSmrg        swaps(&reply.sequenceNumber);
48535c4bbdfSmrg        swapl(&reply.length);
48635c4bbdfSmrg        swapl(&reply.atom);
48735c4bbdfSmrg        swaps(&reply.nbytes);
48805b261ecSmrg    }
48905b261ecSmrg    WriteReplyToClient(client, sizeof(xXFixesGetCursorNameReply), &reply);
4906747b715Smrg    WriteToClient(client, len, str);
49135c4bbdfSmrg
4926747b715Smrg    return Success;
49305b261ecSmrg}
49405b261ecSmrg
4957e31ba66Smrgint _X_COLD
49635c4bbdfSmrgSProcXFixesGetCursorName(ClientPtr client)
49705b261ecSmrg{
49805b261ecSmrg    REQUEST(xXFixesGetCursorNameReq);
49905b261ecSmrg
50035c4bbdfSmrg    swaps(&stuff->length);
50105b261ecSmrg    REQUEST_SIZE_MATCH(xXFixesGetCursorNameReq);
50235c4bbdfSmrg    swapl(&stuff->cursor);
50305b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
50405b261ecSmrg}
50505b261ecSmrg
50605b261ecSmrgint
50735c4bbdfSmrgProcXFixesGetCursorImageAndName(ClientPtr client)
50805b261ecSmrg{
50905b261ecSmrg/*    REQUEST(xXFixesGetCursorImageAndNameReq); */
51035c4bbdfSmrg    xXFixesGetCursorImageAndNameReply *rep;
51135c4bbdfSmrg    CursorPtr pCursor;
51235c4bbdfSmrg    CARD32 *image;
51335c4bbdfSmrg    int npixels;
51435c4bbdfSmrg    const char *name;
51535c4bbdfSmrg    int nbytes, nbytesRound;
51635c4bbdfSmrg    int width, height;
51735c4bbdfSmrg    int rc, x, y;
51805b261ecSmrg
51905b261ecSmrg    REQUEST_SIZE_MATCH(xXFixesGetCursorImageAndNameReq);
5207e31ba66Smrg    pCursor = CursorForClient(client);
52105b261ecSmrg    if (!pCursor)
52235c4bbdfSmrg        return BadCursor;
5234642e01fSmrg    rc = XaceHook(XACE_RESOURCE_ACCESS, client, pCursor->id, RT_CURSOR,
52435c4bbdfSmrg                  pCursor, RT_NONE, NULL, DixReadAccess | DixGetAttrAccess);
5254642e01fSmrg    if (rc != Success)
52635c4bbdfSmrg        return rc;
52735c4bbdfSmrg    GetSpritePosition(PickPointer(client), &x, &y);
52805b261ecSmrg    width = pCursor->bits->width;
52905b261ecSmrg    height = pCursor->bits->height;
53005b261ecSmrg    npixels = width * height;
53135c4bbdfSmrg    name = pCursor->name ? NameForAtom(pCursor->name) : "";
53235c4bbdfSmrg    nbytes = strlen(name);
5336747b715Smrg    nbytesRound = pad_to_int32(nbytes);
53435c4bbdfSmrg    rep = calloc(sizeof(xXFixesGetCursorImageAndNameReply) +
53535c4bbdfSmrg                 npixels * sizeof(CARD32) + nbytesRound, 1);
53605b261ecSmrg    if (!rep)
53735c4bbdfSmrg        return BadAlloc;
53805b261ecSmrg
53905b261ecSmrg    rep->type = X_Reply;
54005b261ecSmrg    rep->sequenceNumber = client->sequence;
5416747b715Smrg    rep->length = npixels + bytes_to_int32(nbytesRound);
54205b261ecSmrg    rep->width = width;
54305b261ecSmrg    rep->height = height;
54405b261ecSmrg    rep->x = x;
54505b261ecSmrg    rep->y = y;
54605b261ecSmrg    rep->xhot = pCursor->bits->xhot;
54735c4bbdfSmrg    rep->yhot = pCursor->bits->yhot;
54805b261ecSmrg    rep->cursorSerial = pCursor->serialNumber;
54905b261ecSmrg    rep->cursorName = pCursor->name;
55005b261ecSmrg    rep->nbytes = nbytes;
55105b261ecSmrg
55205b261ecSmrg    image = (CARD32 *) (rep + 1);
55335c4bbdfSmrg    CopyCursorToImage(pCursor, image);
55435c4bbdfSmrg    memcpy((image + npixels), name, nbytes);
55535c4bbdfSmrg    if (client->swapped) {
55635c4bbdfSmrg        swaps(&rep->sequenceNumber);
55735c4bbdfSmrg        swapl(&rep->length);
55835c4bbdfSmrg        swaps(&rep->x);
55935c4bbdfSmrg        swaps(&rep->y);
56035c4bbdfSmrg        swaps(&rep->width);
56135c4bbdfSmrg        swaps(&rep->height);
56235c4bbdfSmrg        swaps(&rep->xhot);
56335c4bbdfSmrg        swaps(&rep->yhot);
56435c4bbdfSmrg        swapl(&rep->cursorSerial);
56535c4bbdfSmrg        swapl(&rep->cursorName);
56635c4bbdfSmrg        swaps(&rep->nbytes);
56735c4bbdfSmrg        SwapLongs(image, npixels);
56805b261ecSmrg    }
56935c4bbdfSmrg    WriteToClient(client, sizeof(xXFixesGetCursorImageAndNameReply) +
57035c4bbdfSmrg                  (npixels << 2) + nbytesRound, rep);
5716747b715Smrg    free(rep);
5726747b715Smrg    return Success;
57305b261ecSmrg}
57405b261ecSmrg
5757e31ba66Smrgint _X_COLD
57635c4bbdfSmrgSProcXFixesGetCursorImageAndName(ClientPtr client)
57705b261ecSmrg{
57805b261ecSmrg    REQUEST(xXFixesGetCursorImageAndNameReq);
57935c4bbdfSmrg    swaps(&stuff->length);
58005b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
58105b261ecSmrg}
58205b261ecSmrg
58305b261ecSmrg/*
58405b261ecSmrg * Find every cursor reference in the system, ask testCursor
58505b261ecSmrg * whether it should be replaced with a reference to pCursor.
58605b261ecSmrg */
58705b261ecSmrg
58835c4bbdfSmrgtypedef Bool (*TestCursorFunc) (CursorPtr pOld, void *closure);
58905b261ecSmrg
59005b261ecSmrgtypedef struct {
59105b261ecSmrg    RESTYPE type;
59205b261ecSmrg    TestCursorFunc testCursor;
59305b261ecSmrg    CursorPtr pNew;
59435c4bbdfSmrg    void *closure;
59505b261ecSmrg} ReplaceCursorLookupRec, *ReplaceCursorLookupPtr;
59605b261ecSmrg
59735c4bbdfSmrgstatic const RESTYPE CursorRestypes[] = {
59805b261ecSmrg    RT_WINDOW, RT_PASSIVEGRAB, RT_CURSOR
59905b261ecSmrg};
60005b261ecSmrg
60105b261ecSmrgstatic Bool
60235c4bbdfSmrgReplaceCursorLookup(void *value, XID id, void *closure)
60305b261ecSmrg{
60435c4bbdfSmrg    ReplaceCursorLookupPtr rcl = (ReplaceCursorLookupPtr) closure;
60535c4bbdfSmrg    WindowPtr pWin;
60635c4bbdfSmrg    GrabPtr pGrab;
60735c4bbdfSmrg    CursorPtr pCursor = 0, *pCursorRef = 0;
60835c4bbdfSmrg    XID cursor = 0;
60905b261ecSmrg
61005b261ecSmrg    switch (rcl->type) {
61105b261ecSmrg    case RT_WINDOW:
61235c4bbdfSmrg        pWin = (WindowPtr) value;
61335c4bbdfSmrg        if (pWin->optional) {
61435c4bbdfSmrg            pCursorRef = &pWin->optional->cursor;
61535c4bbdfSmrg            pCursor = *pCursorRef;
61635c4bbdfSmrg        }
61735c4bbdfSmrg        break;
61805b261ecSmrg    case RT_PASSIVEGRAB:
61935c4bbdfSmrg        pGrab = (GrabPtr) value;
62035c4bbdfSmrg        pCursorRef = &pGrab->cursor;
62135c4bbdfSmrg        pCursor = *pCursorRef;
62235c4bbdfSmrg        break;
62305b261ecSmrg    case RT_CURSOR:
62435c4bbdfSmrg        pCursorRef = 0;
62535c4bbdfSmrg        pCursor = (CursorPtr) value;
62635c4bbdfSmrg        cursor = id;
62735c4bbdfSmrg        break;
62805b261ecSmrg    }
62935c4bbdfSmrg    if (pCursor && pCursor != rcl->pNew) {
63035c4bbdfSmrg        if ((*rcl->testCursor) (pCursor, rcl->closure)) {
63135c4bbdfSmrg            CursorPtr curs = RefCursor(rcl->pNew);
63235c4bbdfSmrg            /* either redirect reference or update resource database */
63335c4bbdfSmrg            if (pCursorRef)
63435c4bbdfSmrg                *pCursorRef = curs;
63535c4bbdfSmrg            else
63635c4bbdfSmrg                ChangeResourceValue(id, RT_CURSOR, curs);
63735c4bbdfSmrg            FreeCursor(pCursor, cursor);
63835c4bbdfSmrg        }
63905b261ecSmrg    }
64035c4bbdfSmrg    return FALSE;               /* keep walking */
64105b261ecSmrg}
64205b261ecSmrg
64305b261ecSmrgstatic void
64435c4bbdfSmrgReplaceCursor(CursorPtr pCursor, TestCursorFunc testCursor, void *closure)
64505b261ecSmrg{
64635c4bbdfSmrg    int clientIndex;
64705b261ecSmrg    int resIndex;
64835c4bbdfSmrg    ReplaceCursorLookupRec rcl;
64935c4bbdfSmrg
65035c4bbdfSmrg    /*
65105b261ecSmrg     * Cursors exist only in the resource database, windows and grabs.
65205b261ecSmrg     * All of these are always pointed at by the resource database.  Walk
65305b261ecSmrg     * the whole thing looking for cursors
65405b261ecSmrg     */
65505b261ecSmrg    rcl.testCursor = testCursor;
65605b261ecSmrg    rcl.pNew = pCursor;
65705b261ecSmrg    rcl.closure = closure;
65805b261ecSmrg
65905b261ecSmrg    /* for each client */
66035c4bbdfSmrg    for (clientIndex = 0; clientIndex < currentMaxClients; clientIndex++) {
66135c4bbdfSmrg        if (!clients[clientIndex])
66235c4bbdfSmrg            continue;
6637e31ba66Smrg        for (resIndex = 0; resIndex < ARRAY_SIZE(CursorRestypes); resIndex++) {
66435c4bbdfSmrg            rcl.type = CursorRestypes[resIndex];
66535c4bbdfSmrg            /*
66635c4bbdfSmrg             * This function walks the entire client resource database
66735c4bbdfSmrg             */
66835c4bbdfSmrg            LookupClientResourceComplex(clients[clientIndex],
66935c4bbdfSmrg                                        rcl.type,
67035c4bbdfSmrg                                        ReplaceCursorLookup, (void *) &rcl);
67135c4bbdfSmrg        }
67205b261ecSmrg    }
6735a112b11Smrg    /* this "knows" that WindowHasNewCursor doesn't depend on its argument */
67435c4bbdfSmrg    WindowHasNewCursor(screenInfo.screens[0]->root);
67505b261ecSmrg}
67605b261ecSmrg
67735c4bbdfSmrgstatic Bool
67835c4bbdfSmrgTestForCursor(CursorPtr pCursor, void *closure)
67905b261ecSmrg{
68005b261ecSmrg    return (pCursor == (CursorPtr) closure);
68105b261ecSmrg}
68205b261ecSmrg
68305b261ecSmrgint
68435c4bbdfSmrgProcXFixesChangeCursor(ClientPtr client)
68505b261ecSmrg{
68635c4bbdfSmrg    CursorPtr pSource, pDestination;
68735c4bbdfSmrg
68805b261ecSmrg    REQUEST(xXFixesChangeCursorReq);
68905b261ecSmrg
69005b261ecSmrg    REQUEST_SIZE_MATCH(xXFixesChangeCursorReq);
69135c4bbdfSmrg    VERIFY_CURSOR(pSource, stuff->source, client,
69235c4bbdfSmrg                  DixReadAccess | DixGetAttrAccess);
69335c4bbdfSmrg    VERIFY_CURSOR(pDestination, stuff->destination, client,
69435c4bbdfSmrg                  DixWriteAccess | DixSetAttrAccess);
69505b261ecSmrg
69635c4bbdfSmrg    ReplaceCursor(pSource, TestForCursor, (void *) pDestination);
6976747b715Smrg    return Success;
69805b261ecSmrg}
69905b261ecSmrg
7007e31ba66Smrgint _X_COLD
70135c4bbdfSmrgSProcXFixesChangeCursor(ClientPtr client)
70205b261ecSmrg{
70305b261ecSmrg    REQUEST(xXFixesChangeCursorReq);
70405b261ecSmrg
70535c4bbdfSmrg    swaps(&stuff->length);
70605b261ecSmrg    REQUEST_SIZE_MATCH(xXFixesChangeCursorReq);
70735c4bbdfSmrg    swapl(&stuff->source);
70835c4bbdfSmrg    swapl(&stuff->destination);
70905b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
71005b261ecSmrg}
71105b261ecSmrg
71205b261ecSmrgstatic Bool
71335c4bbdfSmrgTestForCursorName(CursorPtr pCursor, void *closure)
71405b261ecSmrg{
7154642e01fSmrg    Atom *pName = closure;
71635c4bbdfSmrg
7176747b715Smrg    return pCursor->name == *pName;
71805b261ecSmrg}
71905b261ecSmrg
72005b261ecSmrgint
72135c4bbdfSmrgProcXFixesChangeCursorByName(ClientPtr client)
72205b261ecSmrg{
72335c4bbdfSmrg    CursorPtr pSource;
72435c4bbdfSmrg    Atom name;
72535c4bbdfSmrg    char *tchar;
72635c4bbdfSmrg
72705b261ecSmrg    REQUEST(xXFixesChangeCursorByNameReq);
72805b261ecSmrg
72905b261ecSmrg    REQUEST_FIXED_SIZE(xXFixesChangeCursorByNameReq, stuff->nbytes);
7304642e01fSmrg    VERIFY_CURSOR(pSource, stuff->source, client,
73135c4bbdfSmrg                  DixReadAccess | DixGetAttrAccess);
73205b261ecSmrg    tchar = (char *) &stuff[1];
73335c4bbdfSmrg    name = MakeAtom(tchar, stuff->nbytes, FALSE);
73405b261ecSmrg    if (name)
73535c4bbdfSmrg        ReplaceCursor(pSource, TestForCursorName, &name);
7366747b715Smrg    return Success;
73705b261ecSmrg}
73805b261ecSmrg
7397e31ba66Smrgint _X_COLD
74035c4bbdfSmrgSProcXFixesChangeCursorByName(ClientPtr client)
74105b261ecSmrg{
74205b261ecSmrg    REQUEST(xXFixesChangeCursorByNameReq);
74305b261ecSmrg
74435c4bbdfSmrg    swaps(&stuff->length);
74535c4bbdfSmrg    REQUEST_AT_LEAST_SIZE(xXFixesChangeCursorByNameReq);
74635c4bbdfSmrg    swapl(&stuff->source);
74735c4bbdfSmrg    swaps(&stuff->nbytes);
74805b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
74905b261ecSmrg}
75005b261ecSmrg
75105b261ecSmrg/*
75205b261ecSmrg * Routines for manipulating the per-screen hide counts list.
75335c4bbdfSmrg * This list indicates which clients have requested cursor hiding
75405b261ecSmrg * for that screen.
75505b261ecSmrg */
75605b261ecSmrg
75705b261ecSmrg/* Return the screen's hide-counts list element for the given client */
75805b261ecSmrgstatic CursorHideCountPtr
75935c4bbdfSmrgfindCursorHideCount(ClientPtr pClient, ScreenPtr pScreen)
76005b261ecSmrg{
76135c4bbdfSmrg    CursorScreenPtr cs = GetCursorScreen(pScreen);
76205b261ecSmrg    CursorHideCountPtr pChc;
76305b261ecSmrg
76405b261ecSmrg    for (pChc = cs->pCursorHideCounts; pChc != NULL; pChc = pChc->pNext) {
76535c4bbdfSmrg        if (pChc->pClient == pClient) {
76635c4bbdfSmrg            return pChc;
76735c4bbdfSmrg        }
76805b261ecSmrg    }
76905b261ecSmrg
77035c4bbdfSmrg    return NULL;
77105b261ecSmrg}
77205b261ecSmrg
77305b261ecSmrgstatic int
77435c4bbdfSmrgcreateCursorHideCount(ClientPtr pClient, ScreenPtr pScreen)
77505b261ecSmrg{
77635c4bbdfSmrg    CursorScreenPtr cs = GetCursorScreen(pScreen);
77705b261ecSmrg    CursorHideCountPtr pChc;
77805b261ecSmrg
7796747b715Smrg    pChc = (CursorHideCountPtr) malloc(sizeof(CursorHideCountRec));
78005b261ecSmrg    if (pChc == NULL) {
78135c4bbdfSmrg        return BadAlloc;
78205b261ecSmrg    }
78305b261ecSmrg    pChc->pClient = pClient;
78405b261ecSmrg    pChc->pScreen = pScreen;
78505b261ecSmrg    pChc->hideCount = 1;
78605b261ecSmrg    pChc->resource = FakeClientID(pClient->index);
78705b261ecSmrg    pChc->pNext = cs->pCursorHideCounts;
78805b261ecSmrg    cs->pCursorHideCounts = pChc;
78935c4bbdfSmrg
79035c4bbdfSmrg    /*
79105b261ecSmrg     * Create a resource for this element so it can be deleted
79205b261ecSmrg     * when the client goes away.
79305b261ecSmrg     */
79435c4bbdfSmrg    if (!AddResource(pChc->resource, CursorHideCountType, (void *) pChc))
79535c4bbdfSmrg        return BadAlloc;
79605b261ecSmrg
79705b261ecSmrg    return Success;
79805b261ecSmrg}
79905b261ecSmrg
80035c4bbdfSmrg/*
80105b261ecSmrg * Delete the given hide-counts list element from its screen list.
80205b261ecSmrg */
80305b261ecSmrgstatic void
80435c4bbdfSmrgdeleteCursorHideCount(CursorHideCountPtr pChcToDel, ScreenPtr pScreen)
80505b261ecSmrg{
80635c4bbdfSmrg    CursorScreenPtr cs = GetCursorScreen(pScreen);
80705b261ecSmrg    CursorHideCountPtr pChc, pNext;
80805b261ecSmrg    CursorHideCountPtr pChcLast = NULL;
80905b261ecSmrg
81005b261ecSmrg    pChc = cs->pCursorHideCounts;
81105b261ecSmrg    while (pChc != NULL) {
81235c4bbdfSmrg        pNext = pChc->pNext;
81335c4bbdfSmrg        if (pChc == pChcToDel) {
81435c4bbdfSmrg            free(pChc);
81535c4bbdfSmrg            if (pChcLast == NULL) {
81635c4bbdfSmrg                cs->pCursorHideCounts = pNext;
81735c4bbdfSmrg            }
81835c4bbdfSmrg            else {
81935c4bbdfSmrg                pChcLast->pNext = pNext;
82035c4bbdfSmrg            }
82135c4bbdfSmrg            return;
82235c4bbdfSmrg        }
82335c4bbdfSmrg        pChcLast = pChc;
82435c4bbdfSmrg        pChc = pNext;
82505b261ecSmrg    }
82605b261ecSmrg}
82705b261ecSmrg
82835c4bbdfSmrg/*
82905b261ecSmrg * Delete all the hide-counts list elements for this screen.
83005b261ecSmrg */
83105b261ecSmrgstatic void
83235c4bbdfSmrgdeleteCursorHideCountsForScreen(ScreenPtr pScreen)
83305b261ecSmrg{
83435c4bbdfSmrg    CursorScreenPtr cs = GetCursorScreen(pScreen);
83505b261ecSmrg    CursorHideCountPtr pChc, pTmp;
83605b261ecSmrg
83705b261ecSmrg    pChc = cs->pCursorHideCounts;
83805b261ecSmrg    while (pChc != NULL) {
83935c4bbdfSmrg        pTmp = pChc->pNext;
84035c4bbdfSmrg        FreeResource(pChc->resource, 0);
84135c4bbdfSmrg        pChc = pTmp;
84205b261ecSmrg    }
84335c4bbdfSmrg    cs->pCursorHideCounts = NULL;
84405b261ecSmrg}
84505b261ecSmrg
84635c4bbdfSmrgint
84735c4bbdfSmrgProcXFixesHideCursor(ClientPtr client)
84805b261ecSmrg{
84905b261ecSmrg    WindowPtr pWin;
85005b261ecSmrg    CursorHideCountPtr pChc;
85135c4bbdfSmrg
85205b261ecSmrg    REQUEST(xXFixesHideCursorReq);
85305b261ecSmrg    int ret;
85405b261ecSmrg
85535c4bbdfSmrg    REQUEST_SIZE_MATCH(xXFixesHideCursorReq);
85605b261ecSmrg
85735c4bbdfSmrg    ret = dixLookupResourceByType((void **) &pWin, stuff->window, RT_WINDOW,
85835c4bbdfSmrg                                  client, DixGetAttrAccess);
8594642e01fSmrg    if (ret != Success) {
86035c4bbdfSmrg        client->errorValue = stuff->window;
86135c4bbdfSmrg        return ret;
86205b261ecSmrg    }
86305b261ecSmrg
86435c4bbdfSmrg    /*
86535c4bbdfSmrg     * Has client hidden the cursor before on this screen?
86635c4bbdfSmrg     * If so, just increment the count.
86705b261ecSmrg     */
86805b261ecSmrg
86905b261ecSmrg    pChc = findCursorHideCount(client, pWin->drawable.pScreen);
87005b261ecSmrg    if (pChc != NULL) {
87135c4bbdfSmrg        pChc->hideCount++;
87235c4bbdfSmrg        return Success;
87305b261ecSmrg    }
87405b261ecSmrg
87535c4bbdfSmrg    /*
87635c4bbdfSmrg     * This is the first time this client has hid the cursor
87705b261ecSmrg     * for this screen.
87805b261ecSmrg     */
8794642e01fSmrg    ret = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen,
88035c4bbdfSmrg                   DixHideAccess);
8814642e01fSmrg    if (ret != Success)
88235c4bbdfSmrg        return ret;
8834642e01fSmrg
88405b261ecSmrg    ret = createCursorHideCount(client, pWin->drawable.pScreen);
88505b261ecSmrg
88605b261ecSmrg    if (ret == Success) {
88735c4bbdfSmrg        DeviceIntPtr dev;
88835c4bbdfSmrg
88935c4bbdfSmrg        for (dev = inputInfo.devices; dev; dev = dev->next) {
89035c4bbdfSmrg            if (IsMaster(dev) && IsPointerDevice(dev))
89135c4bbdfSmrg                CursorDisplayCursor(dev, pWin->drawable.pScreen,
8927e31ba66Smrg                                    CursorForDevice(dev));
89335c4bbdfSmrg        }
89405b261ecSmrg    }
89505b261ecSmrg
89605b261ecSmrg    return ret;
89705b261ecSmrg}
89805b261ecSmrg
8997e31ba66Smrgint _X_COLD
90035c4bbdfSmrgSProcXFixesHideCursor(ClientPtr client)
90105b261ecSmrg{
90205b261ecSmrg    REQUEST(xXFixesHideCursorReq);
90305b261ecSmrg
90435c4bbdfSmrg    swaps(&stuff->length);
90535c4bbdfSmrg    REQUEST_SIZE_MATCH(xXFixesHideCursorReq);
90635c4bbdfSmrg    swapl(&stuff->window);
90705b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
90805b261ecSmrg}
90905b261ecSmrg
91035c4bbdfSmrgint
91135c4bbdfSmrgProcXFixesShowCursor(ClientPtr client)
91205b261ecSmrg{
91305b261ecSmrg    WindowPtr pWin;
91405b261ecSmrg    CursorHideCountPtr pChc;
9154642e01fSmrg    int rc;
91635c4bbdfSmrg
91705b261ecSmrg    REQUEST(xXFixesShowCursorReq);
91805b261ecSmrg
91935c4bbdfSmrg    REQUEST_SIZE_MATCH(xXFixesShowCursorReq);
92005b261ecSmrg
92135c4bbdfSmrg    rc = dixLookupResourceByType((void **) &pWin, stuff->window, RT_WINDOW,
92235c4bbdfSmrg                                 client, DixGetAttrAccess);
9234642e01fSmrg    if (rc != Success) {
92435c4bbdfSmrg        client->errorValue = stuff->window;
92535c4bbdfSmrg        return rc;
92605b261ecSmrg    }
92705b261ecSmrg
92835c4bbdfSmrg    /*
92905b261ecSmrg     * Has client hidden the cursor on this screen?
93005b261ecSmrg     * If not, generate an error.
93105b261ecSmrg     */
93205b261ecSmrg    pChc = findCursorHideCount(client, pWin->drawable.pScreen);
93305b261ecSmrg    if (pChc == NULL) {
93435c4bbdfSmrg        return BadMatch;
93505b261ecSmrg    }
93605b261ecSmrg
9374642e01fSmrg    rc = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen,
93835c4bbdfSmrg                  DixShowAccess);
9394642e01fSmrg    if (rc != Success)
94035c4bbdfSmrg        return rc;
9414642e01fSmrg
94205b261ecSmrg    pChc->hideCount--;
94305b261ecSmrg    if (pChc->hideCount <= 0) {
94435c4bbdfSmrg        FreeResource(pChc->resource, 0);
94505b261ecSmrg    }
94605b261ecSmrg
9476747b715Smrg    return Success;
94805b261ecSmrg}
94905b261ecSmrg
9507e31ba66Smrgint _X_COLD
95135c4bbdfSmrgSProcXFixesShowCursor(ClientPtr client)
95205b261ecSmrg{
95305b261ecSmrg    REQUEST(xXFixesShowCursorReq);
95405b261ecSmrg
95535c4bbdfSmrg    swaps(&stuff->length);
95635c4bbdfSmrg    REQUEST_SIZE_MATCH(xXFixesShowCursorReq);
95735c4bbdfSmrg    swapl(&stuff->window);
95805b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
95905b261ecSmrg}
96005b261ecSmrg
96105b261ecSmrgstatic int
96235c4bbdfSmrgCursorFreeClient(void *data, XID id)
96305b261ecSmrg{
96435c4bbdfSmrg    CursorEventPtr old = (CursorEventPtr) data;
96535c4bbdfSmrg    CursorEventPtr *prev, e;
96635c4bbdfSmrg
96735c4bbdfSmrg    for (prev = &cursorEvents; (e = *prev); prev = &e->next) {
96835c4bbdfSmrg        if (e == old) {
96935c4bbdfSmrg            *prev = e->next;
97035c4bbdfSmrg            free(e);
97135c4bbdfSmrg            break;
97235c4bbdfSmrg        }
97305b261ecSmrg    }
97405b261ecSmrg    return 1;
97505b261ecSmrg}
97605b261ecSmrg
97705b261ecSmrgstatic int
97835c4bbdfSmrgCursorFreeHideCount(void *data, XID id)
97905b261ecSmrg{
98005b261ecSmrg    CursorHideCountPtr pChc = (CursorHideCountPtr) data;
98105b261ecSmrg    ScreenPtr pScreen = pChc->pScreen;
9826747b715Smrg    DeviceIntPtr dev;
98305b261ecSmrg
98405b261ecSmrg    deleteCursorHideCount(pChc, pChc->pScreen);
98535c4bbdfSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
9866747b715Smrg        if (IsMaster(dev) && IsPointerDevice(dev))
9877e31ba66Smrg            CursorDisplayCursor(dev, pScreen, CursorForDevice(dev));
9886747b715Smrg    }
98905b261ecSmrg
99005b261ecSmrg    return 1;
99105b261ecSmrg}
99205b261ecSmrg
99305b261ecSmrgstatic int
99435c4bbdfSmrgCursorFreeWindow(void *data, XID id)
99505b261ecSmrg{
99635c4bbdfSmrg    WindowPtr pWindow = (WindowPtr) data;
99735c4bbdfSmrg    CursorEventPtr e, next;
99835c4bbdfSmrg
99935c4bbdfSmrg    for (e = cursorEvents; e; e = next) {
100035c4bbdfSmrg        next = e->next;
100135c4bbdfSmrg        if (e->pWindow == pWindow) {
100235c4bbdfSmrg            FreeResource(e->clientResource, 0);
100335c4bbdfSmrg        }
100405b261ecSmrg    }
100505b261ecSmrg    return 1;
100605b261ecSmrg}
100705b261ecSmrg
100835c4bbdfSmrgint
100935c4bbdfSmrgProcXFixesCreatePointerBarrier(ClientPtr client)
101035c4bbdfSmrg{
101135c4bbdfSmrg    REQUEST(xXFixesCreatePointerBarrierReq);
101235c4bbdfSmrg
10135a112b11Smrg    REQUEST_FIXED_SIZE(xXFixesCreatePointerBarrierReq,
10145a112b11Smrg                       pad_to_int32(stuff->num_devices * sizeof(CARD16)));
101535c4bbdfSmrg    LEGAL_NEW_RESOURCE(stuff->barrier, client);
101635c4bbdfSmrg
101735c4bbdfSmrg    return XICreatePointerBarrier(client, stuff);
101835c4bbdfSmrg}
101935c4bbdfSmrg
10207e31ba66Smrgint _X_COLD
102135c4bbdfSmrgSProcXFixesCreatePointerBarrier(ClientPtr client)
102235c4bbdfSmrg{
102335c4bbdfSmrg    REQUEST(xXFixesCreatePointerBarrierReq);
102435c4bbdfSmrg    int i;
102535c4bbdfSmrg    CARD16 *in_devices = (CARD16 *) &stuff[1];
102635c4bbdfSmrg
10276e78d31fSmrg    REQUEST_AT_LEAST_SIZE(xXFixesCreatePointerBarrierReq);
10286e78d31fSmrg
102935c4bbdfSmrg    swaps(&stuff->length);
103035c4bbdfSmrg    swaps(&stuff->num_devices);
10315a112b11Smrg    REQUEST_FIXED_SIZE(xXFixesCreatePointerBarrierReq,
10325a112b11Smrg                       pad_to_int32(stuff->num_devices * sizeof(CARD16)));
103335c4bbdfSmrg
103435c4bbdfSmrg    swapl(&stuff->barrier);
103535c4bbdfSmrg    swapl(&stuff->window);
103635c4bbdfSmrg    swaps(&stuff->x1);
103735c4bbdfSmrg    swaps(&stuff->y1);
103835c4bbdfSmrg    swaps(&stuff->x2);
103935c4bbdfSmrg    swaps(&stuff->y2);
104035c4bbdfSmrg    swapl(&stuff->directions);
104135c4bbdfSmrg    for (i = 0; i < stuff->num_devices; i++) {
104235c4bbdfSmrg        swaps(in_devices + i);
104335c4bbdfSmrg    }
104435c4bbdfSmrg
104535c4bbdfSmrg    return ProcXFixesVector[stuff->xfixesReqType] (client);
104635c4bbdfSmrg}
104735c4bbdfSmrg
104835c4bbdfSmrgint
104935c4bbdfSmrgProcXFixesDestroyPointerBarrier(ClientPtr client)
105035c4bbdfSmrg{
105135c4bbdfSmrg    REQUEST(xXFixesDestroyPointerBarrierReq);
105235c4bbdfSmrg
105335c4bbdfSmrg    REQUEST_SIZE_MATCH(xXFixesDestroyPointerBarrierReq);
105435c4bbdfSmrg
105535c4bbdfSmrg    return XIDestroyPointerBarrier(client, stuff);
105635c4bbdfSmrg}
105735c4bbdfSmrg
10587e31ba66Smrgint _X_COLD
105935c4bbdfSmrgSProcXFixesDestroyPointerBarrier(ClientPtr client)
106035c4bbdfSmrg{
106135c4bbdfSmrg    REQUEST(xXFixesDestroyPointerBarrierReq);
106235c4bbdfSmrg
106335c4bbdfSmrg    swaps(&stuff->length);
106435c4bbdfSmrg    REQUEST_SIZE_MATCH(xXFixesDestroyPointerBarrierReq);
106535c4bbdfSmrg    swapl(&stuff->barrier);
106635c4bbdfSmrg    return ProcXFixesVector[stuff->xfixesReqType] (client);
106735c4bbdfSmrg}
106835c4bbdfSmrg
106905b261ecSmrgBool
107035c4bbdfSmrgXFixesCursorInit(void)
107105b261ecSmrg{
107235c4bbdfSmrg    int i;
10734642e01fSmrg
10744642e01fSmrg    if (party_like_its_1989)
107535c4bbdfSmrg        CursorVisible = EnableCursor;
107635c4bbdfSmrg    else
107735c4bbdfSmrg        CursorVisible = FALSE;
10786747b715Smrg
107935c4bbdfSmrg    if (!dixRegisterPrivateKey(&CursorScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
108035c4bbdfSmrg        return FALSE;
108135c4bbdfSmrg
108235c4bbdfSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
108335c4bbdfSmrg        ScreenPtr pScreen = screenInfo.screens[i];
108435c4bbdfSmrg        CursorScreenPtr cs;
108535c4bbdfSmrg
108635c4bbdfSmrg        cs = (CursorScreenPtr) calloc(1, sizeof(CursorScreenRec));
108735c4bbdfSmrg        if (!cs)
108835c4bbdfSmrg            return FALSE;
108935c4bbdfSmrg        Wrap(cs, pScreen, CloseScreen, CursorCloseScreen);
109035c4bbdfSmrg        Wrap(cs, pScreen, DisplayCursor, CursorDisplayCursor);
109135c4bbdfSmrg        cs->pCursorHideCounts = NULL;
109235c4bbdfSmrg        SetCursorScreen(pScreen, cs);
109305b261ecSmrg    }
10946747b715Smrg    CursorClientType = CreateNewResourceType(CursorFreeClient,
109535c4bbdfSmrg                                             "XFixesCursorClient");
10966747b715Smrg    CursorHideCountType = CreateNewResourceType(CursorFreeHideCount,
109735c4bbdfSmrg                                                "XFixesCursorHideCount");
10986747b715Smrg    CursorWindowType = CreateNewResourceType(CursorFreeWindow,
109935c4bbdfSmrg                                             "XFixesCursorWindow");
11006747b715Smrg
11016747b715Smrg    return CursorClientType && CursorHideCountType && CursorWindowType;
110205b261ecSmrg}
1103