cursor.c revision 35c4bbdf
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;
6435c4bbdfSmrgstatic CursorPtr CursorCurrent[MAXDEVICES];
6505b261ecSmrg
666747b715Smrgstatic DevPrivateKeyRec CursorScreenPrivateKeyRec;
6735c4bbdfSmrg
686747b715Smrg#define CursorScreenPrivateKey (&CursorScreenPrivateKeyRec)
694642e01fSmrg
7035c4bbdfSmrgstatic void deleteCursorHideCountsForScreen(ScreenPtr pScreen);
7105b261ecSmrg
726747b715Smrg#define VERIFY_CURSOR(pCursor, cursor, client, access)			\
736747b715Smrg    do {								\
746747b715Smrg	int err;							\
7535c4bbdfSmrg	err = dixLookupResourceByType((void **) &pCursor, cursor,	\
766747b715Smrg				      RT_CURSOR, client, access);	\
776747b715Smrg	if (err != Success) {						\
786747b715Smrg	    client->errorValue = cursor;				\
796747b715Smrg	    return err;							\
806747b715Smrg	}								\
816747b715Smrg    } while (0)
824642e01fSmrg
8305b261ecSmrg/*
8405b261ecSmrg * There is a global list of windows selecting for cursor events
8505b261ecSmrg */
8605b261ecSmrg
8705b261ecSmrgtypedef struct _CursorEvent *CursorEventPtr;
8805b261ecSmrg
8905b261ecSmrgtypedef struct _CursorEvent {
9035c4bbdfSmrg    CursorEventPtr next;
9135c4bbdfSmrg    CARD32 eventMask;
9235c4bbdfSmrg    ClientPtr pClient;
9335c4bbdfSmrg    WindowPtr pWindow;
9435c4bbdfSmrg    XID clientResource;
9505b261ecSmrg} CursorEventRec;
9605b261ecSmrg
9735c4bbdfSmrgstatic CursorEventPtr cursorEvents;
9805b261ecSmrg
9905b261ecSmrg/*
10005b261ecSmrg * Each screen has a list of clients which have requested
10105b261ecSmrg * that the cursor be hid, and the number of times each
10205b261ecSmrg * client has requested.
10305b261ecSmrg*/
10405b261ecSmrg
10505b261ecSmrgtypedef struct _CursorHideCountRec *CursorHideCountPtr;
10605b261ecSmrg
10705b261ecSmrgtypedef struct _CursorHideCountRec {
10835c4bbdfSmrg    CursorHideCountPtr pNext;
10935c4bbdfSmrg    ClientPtr pClient;
11035c4bbdfSmrg    ScreenPtr pScreen;
11135c4bbdfSmrg    int hideCount;
11235c4bbdfSmrg    XID resource;
11305b261ecSmrg} CursorHideCountRec;
11405b261ecSmrg
11505b261ecSmrg/*
11605b261ecSmrg * Wrap DisplayCursor to catch cursor change events
11705b261ecSmrg */
11805b261ecSmrg
11905b261ecSmrgtypedef struct _CursorScreen {
12035c4bbdfSmrg    DisplayCursorProcPtr DisplayCursor;
12135c4bbdfSmrg    CloseScreenProcPtr CloseScreen;
12235c4bbdfSmrg    CursorHideCountPtr pCursorHideCounts;
12305b261ecSmrg} CursorScreenRec, *CursorScreenPtr;
12405b261ecSmrg
1254642e01fSmrg#define GetCursorScreen(s) ((CursorScreenPtr)dixLookupPrivate(&(s)->devPrivates, CursorScreenPrivateKey))
1264642e01fSmrg#define GetCursorScreenIfSet(s) GetCursorScreen(s)
1274642e01fSmrg#define SetCursorScreen(s,p) dixSetPrivate(&(s)->devPrivates, CursorScreenPrivateKey, p)
12805b261ecSmrg#define Wrap(as,s,elt,func)	(((as)->elt = (s)->elt), (s)->elt = func)
1296747b715Smrg#define Unwrap(as,s,elt,backup)	(((backup) = (s)->elt), (s)->elt = (as)->elt)
13005b261ecSmrg
1314642e01fSmrg/* The cursor doesn't show up until the first XDefineCursor() */
13235c4bbdfSmrgBool CursorVisible = FALSE;
1336747b715SmrgBool EnableCursor = TRUE;
1346747b715Smrg
13505b261ecSmrgstatic Bool
13635c4bbdfSmrgCursorDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
13705b261ecSmrg{
13835c4bbdfSmrg    CursorScreenPtr cs = GetCursorScreen(pScreen);
13935c4bbdfSmrg    Bool ret;
1406747b715Smrg    DisplayCursorProcPtr backupProc;
14105b261ecSmrg
14235c4bbdfSmrg    Unwrap(cs, pScreen, DisplayCursor, backupProc);
14305b261ecSmrg
14435c4bbdfSmrg    CursorVisible = CursorVisible && EnableCursor;
1454642e01fSmrg
1464642e01fSmrg    if (cs->pCursorHideCounts != NULL || !CursorVisible) {
14735c4bbdfSmrg        ret = (*pScreen->DisplayCursor) (pDev, pScreen, NullCursor);
14835c4bbdfSmrg    }
14935c4bbdfSmrg    else {
15035c4bbdfSmrg        ret = (*pScreen->DisplayCursor) (pDev, pScreen, pCursor);
15105b261ecSmrg    }
15205b261ecSmrg
15335c4bbdfSmrg    if (pCursor != CursorCurrent[pDev->id]) {
15435c4bbdfSmrg        CursorEventPtr e;
15535c4bbdfSmrg
15635c4bbdfSmrg        CursorCurrent[pDev->id] = pCursor;
15735c4bbdfSmrg        for (e = cursorEvents; e; e = e->next) {
15835c4bbdfSmrg            if ((e->eventMask & XFixesDisplayCursorNotifyMask)) {
15935c4bbdfSmrg                xXFixesCursorNotifyEvent ev = {
16035c4bbdfSmrg                    .type = XFixesEventBase + XFixesCursorNotify,
16135c4bbdfSmrg                    .subtype = XFixesDisplayCursorNotify,
16235c4bbdfSmrg                    .window = e->pWindow->drawable.id,
16335c4bbdfSmrg                    .cursorSerial = pCursor ? pCursor->serialNumber : 0,
16435c4bbdfSmrg                    .timestamp = currentTime.milliseconds,
16535c4bbdfSmrg                    .name = pCursor ? pCursor->name : None
16635c4bbdfSmrg                };
16735c4bbdfSmrg                WriteEventsToClient(e->pClient, 1, (xEvent *) &ev);
16835c4bbdfSmrg            }
16935c4bbdfSmrg        }
17005b261ecSmrg    }
17135c4bbdfSmrg    Wrap(cs, pScreen, DisplayCursor, backupProc);
1726747b715Smrg
17305b261ecSmrg    return ret;
17405b261ecSmrg}
17505b261ecSmrg
17605b261ecSmrgstatic Bool
17735c4bbdfSmrgCursorCloseScreen(ScreenPtr pScreen)
17805b261ecSmrg{
17935c4bbdfSmrg    CursorScreenPtr cs = GetCursorScreen(pScreen);
18035c4bbdfSmrg    Bool ret;
18135c4bbdfSmrg    _X_UNUSED CloseScreenProcPtr close_proc;
18235c4bbdfSmrg    _X_UNUSED DisplayCursorProcPtr display_proc;
18305b261ecSmrg
18435c4bbdfSmrg    Unwrap(cs, pScreen, CloseScreen, close_proc);
18535c4bbdfSmrg    Unwrap(cs, pScreen, DisplayCursor, display_proc);
18605b261ecSmrg    deleteCursorHideCountsForScreen(pScreen);
18735c4bbdfSmrg    ret = (*pScreen->CloseScreen) (pScreen);
1886747b715Smrg    free(cs);
18905b261ecSmrg    return ret;
19005b261ecSmrg}
19105b261ecSmrg
19205b261ecSmrg#define CursorAllEvents (XFixesDisplayCursorNotifyMask)
19305b261ecSmrg
19405b261ecSmrgstatic int
19535c4bbdfSmrgXFixesSelectCursorInput(ClientPtr pClient, WindowPtr pWindow, CARD32 eventMask)
19605b261ecSmrg{
19735c4bbdfSmrg    CursorEventPtr *prev, e;
19835c4bbdfSmrg    void *val;
1996747b715Smrg    int rc;
20005b261ecSmrg
20135c4bbdfSmrg    for (prev = &cursorEvents; (e = *prev); prev = &e->next) {
20235c4bbdfSmrg        if (e->pClient == pClient && e->pWindow == pWindow) {
20335c4bbdfSmrg            break;
20435c4bbdfSmrg        }
20505b261ecSmrg    }
20635c4bbdfSmrg    if (!eventMask) {
20735c4bbdfSmrg        if (e) {
20835c4bbdfSmrg            FreeResource(e->clientResource, 0);
20935c4bbdfSmrg        }
21035c4bbdfSmrg        return Success;
21105b261ecSmrg    }
21235c4bbdfSmrg    if (!e) {
21335c4bbdfSmrg        e = (CursorEventPtr) malloc(sizeof(CursorEventRec));
21435c4bbdfSmrg        if (!e)
21535c4bbdfSmrg            return BadAlloc;
21635c4bbdfSmrg
21735c4bbdfSmrg        e->next = 0;
21835c4bbdfSmrg        e->pClient = pClient;
21935c4bbdfSmrg        e->pWindow = pWindow;
22035c4bbdfSmrg        e->clientResource = FakeClientID(pClient->index);
22135c4bbdfSmrg
22235c4bbdfSmrg        /*
22335c4bbdfSmrg         * Add a resource hanging from the window to
22435c4bbdfSmrg         * catch window destroy
22535c4bbdfSmrg         */
22635c4bbdfSmrg        rc = dixLookupResourceByType(&val, pWindow->drawable.id,
22735c4bbdfSmrg                                     CursorWindowType, serverClient,
22835c4bbdfSmrg                                     DixGetAttrAccess);
22935c4bbdfSmrg        if (rc != Success)
23035c4bbdfSmrg            if (!AddResource(pWindow->drawable.id, CursorWindowType,
23135c4bbdfSmrg                             (void *) pWindow)) {
23235c4bbdfSmrg                free(e);
23335c4bbdfSmrg                return BadAlloc;
23435c4bbdfSmrg            }
23535c4bbdfSmrg
23635c4bbdfSmrg        if (!AddResource(e->clientResource, CursorClientType, (void *) e))
23735c4bbdfSmrg            return BadAlloc;
23835c4bbdfSmrg
23935c4bbdfSmrg        *prev = e;
24005b261ecSmrg    }
24105b261ecSmrg    e->eventMask = eventMask;
24205b261ecSmrg    return Success;
24305b261ecSmrg}
24405b261ecSmrg
24505b261ecSmrgint
24635c4bbdfSmrgProcXFixesSelectCursorInput(ClientPtr client)
24705b261ecSmrg{
24835c4bbdfSmrg    REQUEST(xXFixesSelectCursorInputReq);
24935c4bbdfSmrg    WindowPtr pWin;
25035c4bbdfSmrg    int rc;
25105b261ecSmrg
25235c4bbdfSmrg    REQUEST_SIZE_MATCH(xXFixesSelectCursorInputReq);
2534642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
25405b261ecSmrg    if (rc != Success)
25505b261ecSmrg        return rc;
25635c4bbdfSmrg    if (stuff->eventMask & ~CursorAllEvents) {
25735c4bbdfSmrg        client->errorValue = stuff->eventMask;
25835c4bbdfSmrg        return BadValue;
25905b261ecSmrg    }
26035c4bbdfSmrg    return XFixesSelectCursorInput(client, pWin, stuff->eventMask);
26105b261ecSmrg}
26205b261ecSmrg
26305b261ecSmrgstatic int
26435c4bbdfSmrgGetBit(unsigned char *line, int x)
26505b261ecSmrg{
26635c4bbdfSmrg    unsigned char mask;
26735c4bbdfSmrg
26805b261ecSmrg    if (screenInfo.bitmapBitOrder == LSBFirst)
26935c4bbdfSmrg        mask = (1 << (x & 7));
27005b261ecSmrg    else
27135c4bbdfSmrg        mask = (0x80 >> (x & 7));
27205b261ecSmrg    /* XXX assumes byte order is host byte order */
27305b261ecSmrg    line += (x >> 3);
27405b261ecSmrg    if (*line & mask)
27535c4bbdfSmrg        return 1;
27605b261ecSmrg    return 0;
27705b261ecSmrg}
27805b261ecSmrg
27905b261ecSmrgint
28035c4bbdfSmrgSProcXFixesSelectCursorInput(ClientPtr client)
28105b261ecSmrg{
28205b261ecSmrg    REQUEST(xXFixesSelectCursorInputReq);
28305b261ecSmrg
28435c4bbdfSmrg    swaps(&stuff->length);
28535c4bbdfSmrg    swapl(&stuff->window);
28635c4bbdfSmrg    swapl(&stuff->eventMask);
28705b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
28805b261ecSmrg}
28935c4bbdfSmrg
29005b261ecSmrgvoid
29135c4bbdfSmrgSXFixesCursorNotifyEvent(xXFixesCursorNotifyEvent * from,
29235c4bbdfSmrg                         xXFixesCursorNotifyEvent * to)
29305b261ecSmrg{
29405b261ecSmrg    to->type = from->type;
29535c4bbdfSmrg    cpswaps(from->sequenceNumber, to->sequenceNumber);
29635c4bbdfSmrg    cpswapl(from->window, to->window);
29735c4bbdfSmrg    cpswapl(from->cursorSerial, to->cursorSerial);
29835c4bbdfSmrg    cpswapl(from->timestamp, to->timestamp);
29935c4bbdfSmrg    cpswapl(from->name, to->name);
30005b261ecSmrg}
30105b261ecSmrg
30205b261ecSmrgstatic void
30335c4bbdfSmrgCopyCursorToImage(CursorPtr pCursor, CARD32 *image)
30405b261ecSmrg{
30505b261ecSmrg    int width = pCursor->bits->width;
30605b261ecSmrg    int height = pCursor->bits->height;
30705b261ecSmrg    int npixels = width * height;
30835c4bbdfSmrg
30905b261ecSmrg    if (pCursor->bits->argb)
31035c4bbdfSmrg        memcpy(image, pCursor->bits->argb, npixels * sizeof(CARD32));
31105b261ecSmrg    else
31205b261ecSmrg    {
31335c4bbdfSmrg        unsigned char *srcLine = pCursor->bits->source;
31435c4bbdfSmrg        unsigned char *mskLine = pCursor->bits->mask;
31535c4bbdfSmrg        int stride = BitmapBytePad(width);
31635c4bbdfSmrg        int x, y;
31735c4bbdfSmrg        CARD32 fg, bg;
31835c4bbdfSmrg
31935c4bbdfSmrg        fg = (0xff000000 |
32035c4bbdfSmrg              ((pCursor->foreRed & 0xff00) << 8) |
32135c4bbdfSmrg              (pCursor->foreGreen & 0xff00) | (pCursor->foreBlue >> 8));
32235c4bbdfSmrg        bg = (0xff000000 |
32335c4bbdfSmrg              ((pCursor->backRed & 0xff00) << 8) |
32435c4bbdfSmrg              (pCursor->backGreen & 0xff00) | (pCursor->backBlue >> 8));
32535c4bbdfSmrg        for (y = 0; y < height; y++) {
32635c4bbdfSmrg            for (x = 0; x < width; x++) {
32735c4bbdfSmrg                if (GetBit(mskLine, x)) {
32835c4bbdfSmrg                    if (GetBit(srcLine, x))
32935c4bbdfSmrg                        *image++ = fg;
33035c4bbdfSmrg                    else
33135c4bbdfSmrg                        *image++ = bg;
33235c4bbdfSmrg                }
33335c4bbdfSmrg                else
33435c4bbdfSmrg                    *image++ = 0;
33535c4bbdfSmrg            }
33635c4bbdfSmrg            srcLine += stride;
33735c4bbdfSmrg            mskLine += stride;
33835c4bbdfSmrg        }
33905b261ecSmrg    }
34005b261ecSmrg}
34105b261ecSmrg
34205b261ecSmrgint
34335c4bbdfSmrgProcXFixesGetCursorImage(ClientPtr client)
34405b261ecSmrg{
34505b261ecSmrg/*    REQUEST(xXFixesGetCursorImageReq); */
34635c4bbdfSmrg    xXFixesGetCursorImageReply *rep;
34735c4bbdfSmrg    CursorPtr pCursor;
34835c4bbdfSmrg    CARD32 *image;
34935c4bbdfSmrg    int npixels, width, height, rc, x, y;
35005b261ecSmrg
35105b261ecSmrg    REQUEST_SIZE_MATCH(xXFixesGetCursorImageReq);
3526747b715Smrg    pCursor = CursorCurrent[PickPointer(client)->id];
35305b261ecSmrg    if (!pCursor)
35435c4bbdfSmrg        return BadCursor;
3554642e01fSmrg    rc = XaceHook(XACE_RESOURCE_ACCESS, client, pCursor->id, RT_CURSOR,
35635c4bbdfSmrg                  pCursor, RT_NONE, NULL, DixReadAccess);
3574642e01fSmrg    if (rc != Success)
35835c4bbdfSmrg        return rc;
35935c4bbdfSmrg    GetSpritePosition(PickPointer(client), &x, &y);
36005b261ecSmrg    width = pCursor->bits->width;
36105b261ecSmrg    height = pCursor->bits->height;
36205b261ecSmrg    npixels = width * height;
36335c4bbdfSmrg    rep = calloc(sizeof(xXFixesGetCursorImageReply) + npixels * sizeof(CARD32),
36435c4bbdfSmrg                 1);
36505b261ecSmrg    if (!rep)
36635c4bbdfSmrg        return BadAlloc;
36705b261ecSmrg
36805b261ecSmrg    rep->type = X_Reply;
36905b261ecSmrg    rep->sequenceNumber = client->sequence;
37005b261ecSmrg    rep->length = npixels;
37105b261ecSmrg    rep->width = width;
37205b261ecSmrg    rep->height = height;
37305b261ecSmrg    rep->x = x;
37405b261ecSmrg    rep->y = y;
37505b261ecSmrg    rep->xhot = pCursor->bits->xhot;
37635c4bbdfSmrg    rep->yhot = pCursor->bits->yhot;
37705b261ecSmrg    rep->cursorSerial = pCursor->serialNumber;
37805b261ecSmrg
37905b261ecSmrg    image = (CARD32 *) (rep + 1);
38035c4bbdfSmrg    CopyCursorToImage(pCursor, image);
38135c4bbdfSmrg    if (client->swapped) {
38235c4bbdfSmrg        swaps(&rep->sequenceNumber);
38335c4bbdfSmrg        swapl(&rep->length);
38435c4bbdfSmrg        swaps(&rep->x);
38535c4bbdfSmrg        swaps(&rep->y);
38635c4bbdfSmrg        swaps(&rep->width);
38735c4bbdfSmrg        swaps(&rep->height);
38835c4bbdfSmrg        swaps(&rep->xhot);
38935c4bbdfSmrg        swaps(&rep->yhot);
39035c4bbdfSmrg        swapl(&rep->cursorSerial);
39135c4bbdfSmrg        SwapLongs(image, npixels);
39205b261ecSmrg    }
39335c4bbdfSmrg    WriteToClient(client,
39435c4bbdfSmrg                  sizeof(xXFixesGetCursorImageReply) + (npixels << 2), rep);
3956747b715Smrg    free(rep);
3966747b715Smrg    return Success;
39705b261ecSmrg}
39805b261ecSmrg
39905b261ecSmrgint
40035c4bbdfSmrgSProcXFixesGetCursorImage(ClientPtr client)
40105b261ecSmrg{
40205b261ecSmrg    REQUEST(xXFixesGetCursorImageReq);
40335c4bbdfSmrg    swaps(&stuff->length);
40405b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
40505b261ecSmrg}
40605b261ecSmrg
40705b261ecSmrgint
40835c4bbdfSmrgProcXFixesSetCursorName(ClientPtr client)
40905b261ecSmrg{
41005b261ecSmrg    CursorPtr pCursor;
41105b261ecSmrg    char *tchar;
41235c4bbdfSmrg
41305b261ecSmrg    REQUEST(xXFixesSetCursorNameReq);
41405b261ecSmrg    Atom atom;
41505b261ecSmrg
41605b261ecSmrg    REQUEST_AT_LEAST_SIZE(xXFixesSetCursorNameReq);
4174642e01fSmrg    VERIFY_CURSOR(pCursor, stuff->cursor, client, DixSetAttrAccess);
41805b261ecSmrg    tchar = (char *) &stuff[1];
41935c4bbdfSmrg    atom = MakeAtom(tchar, stuff->nbytes, TRUE);
42005b261ecSmrg    if (atom == BAD_RESOURCE)
42135c4bbdfSmrg        return BadAlloc;
42235c4bbdfSmrg
42305b261ecSmrg    pCursor->name = atom;
4246747b715Smrg    return Success;
42505b261ecSmrg}
42605b261ecSmrg
42705b261ecSmrgint
42835c4bbdfSmrgSProcXFixesSetCursorName(ClientPtr client)
42905b261ecSmrg{
43005b261ecSmrg    REQUEST(xXFixesSetCursorNameReq);
43105b261ecSmrg
43235c4bbdfSmrg    swaps(&stuff->length);
43305b261ecSmrg    REQUEST_AT_LEAST_SIZE(xXFixesSetCursorNameReq);
43435c4bbdfSmrg    swapl(&stuff->cursor);
43535c4bbdfSmrg    swaps(&stuff->nbytes);
43605b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
43705b261ecSmrg}
43805b261ecSmrg
43905b261ecSmrgint
44035c4bbdfSmrgProcXFixesGetCursorName(ClientPtr client)
44105b261ecSmrg{
44235c4bbdfSmrg    CursorPtr pCursor;
44335c4bbdfSmrg    xXFixesGetCursorNameReply reply;
44435c4bbdfSmrg
44505b261ecSmrg    REQUEST(xXFixesGetCursorNameReq);
4466747b715Smrg    const char *str;
44705b261ecSmrg    int len;
44805b261ecSmrg
44905b261ecSmrg    REQUEST_SIZE_MATCH(xXFixesGetCursorNameReq);
4504642e01fSmrg    VERIFY_CURSOR(pCursor, stuff->cursor, client, DixGetAttrAccess);
45105b261ecSmrg    if (pCursor->name)
45235c4bbdfSmrg        str = NameForAtom(pCursor->name);
45305b261ecSmrg    else
45435c4bbdfSmrg        str = "";
45535c4bbdfSmrg    len = strlen(str);
45635c4bbdfSmrg
45735c4bbdfSmrg    reply = (xXFixesGetCursorNameReply) {
45835c4bbdfSmrg        .type = X_Reply,
45935c4bbdfSmrg        .sequenceNumber = client->sequence,
46035c4bbdfSmrg        .length = bytes_to_int32(len),
46135c4bbdfSmrg        .atom = pCursor->name,
46235c4bbdfSmrg        .nbytes = len
46335c4bbdfSmrg    };
46435c4bbdfSmrg    if (client->swapped) {
46535c4bbdfSmrg        swaps(&reply.sequenceNumber);
46635c4bbdfSmrg        swapl(&reply.length);
46735c4bbdfSmrg        swapl(&reply.atom);
46835c4bbdfSmrg        swaps(&reply.nbytes);
46905b261ecSmrg    }
47005b261ecSmrg    WriteReplyToClient(client, sizeof(xXFixesGetCursorNameReply), &reply);
4716747b715Smrg    WriteToClient(client, len, str);
47235c4bbdfSmrg
4736747b715Smrg    return Success;
47405b261ecSmrg}
47505b261ecSmrg
47605b261ecSmrgint
47735c4bbdfSmrgSProcXFixesGetCursorName(ClientPtr client)
47805b261ecSmrg{
47905b261ecSmrg    REQUEST(xXFixesGetCursorNameReq);
48005b261ecSmrg
48135c4bbdfSmrg    swaps(&stuff->length);
48205b261ecSmrg    REQUEST_SIZE_MATCH(xXFixesGetCursorNameReq);
48335c4bbdfSmrg    swapl(&stuff->cursor);
48405b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
48505b261ecSmrg}
48605b261ecSmrg
48705b261ecSmrgint
48835c4bbdfSmrgProcXFixesGetCursorImageAndName(ClientPtr client)
48905b261ecSmrg{
49005b261ecSmrg/*    REQUEST(xXFixesGetCursorImageAndNameReq); */
49135c4bbdfSmrg    xXFixesGetCursorImageAndNameReply *rep;
49235c4bbdfSmrg    CursorPtr pCursor;
49335c4bbdfSmrg    CARD32 *image;
49435c4bbdfSmrg    int npixels;
49535c4bbdfSmrg    const char *name;
49635c4bbdfSmrg    int nbytes, nbytesRound;
49735c4bbdfSmrg    int width, height;
49835c4bbdfSmrg    int rc, x, y;
49905b261ecSmrg
50005b261ecSmrg    REQUEST_SIZE_MATCH(xXFixesGetCursorImageAndNameReq);
5016747b715Smrg    pCursor = CursorCurrent[PickPointer(client)->id];
50205b261ecSmrg    if (!pCursor)
50335c4bbdfSmrg        return BadCursor;
5044642e01fSmrg    rc = XaceHook(XACE_RESOURCE_ACCESS, client, pCursor->id, RT_CURSOR,
50535c4bbdfSmrg                  pCursor, RT_NONE, NULL, DixReadAccess | DixGetAttrAccess);
5064642e01fSmrg    if (rc != Success)
50735c4bbdfSmrg        return rc;
50835c4bbdfSmrg    GetSpritePosition(PickPointer(client), &x, &y);
50905b261ecSmrg    width = pCursor->bits->width;
51005b261ecSmrg    height = pCursor->bits->height;
51105b261ecSmrg    npixels = width * height;
51235c4bbdfSmrg    name = pCursor->name ? NameForAtom(pCursor->name) : "";
51335c4bbdfSmrg    nbytes = strlen(name);
5146747b715Smrg    nbytesRound = pad_to_int32(nbytes);
51535c4bbdfSmrg    rep = calloc(sizeof(xXFixesGetCursorImageAndNameReply) +
51635c4bbdfSmrg                 npixels * sizeof(CARD32) + nbytesRound, 1);
51705b261ecSmrg    if (!rep)
51835c4bbdfSmrg        return BadAlloc;
51905b261ecSmrg
52005b261ecSmrg    rep->type = X_Reply;
52105b261ecSmrg    rep->sequenceNumber = client->sequence;
5226747b715Smrg    rep->length = npixels + bytes_to_int32(nbytesRound);
52305b261ecSmrg    rep->width = width;
52405b261ecSmrg    rep->height = height;
52505b261ecSmrg    rep->x = x;
52605b261ecSmrg    rep->y = y;
52705b261ecSmrg    rep->xhot = pCursor->bits->xhot;
52835c4bbdfSmrg    rep->yhot = pCursor->bits->yhot;
52905b261ecSmrg    rep->cursorSerial = pCursor->serialNumber;
53005b261ecSmrg    rep->cursorName = pCursor->name;
53105b261ecSmrg    rep->nbytes = nbytes;
53205b261ecSmrg
53305b261ecSmrg    image = (CARD32 *) (rep + 1);
53435c4bbdfSmrg    CopyCursorToImage(pCursor, image);
53535c4bbdfSmrg    memcpy((image + npixels), name, nbytes);
53635c4bbdfSmrg    if (client->swapped) {
53735c4bbdfSmrg        swaps(&rep->sequenceNumber);
53835c4bbdfSmrg        swapl(&rep->length);
53935c4bbdfSmrg        swaps(&rep->x);
54035c4bbdfSmrg        swaps(&rep->y);
54135c4bbdfSmrg        swaps(&rep->width);
54235c4bbdfSmrg        swaps(&rep->height);
54335c4bbdfSmrg        swaps(&rep->xhot);
54435c4bbdfSmrg        swaps(&rep->yhot);
54535c4bbdfSmrg        swapl(&rep->cursorSerial);
54635c4bbdfSmrg        swapl(&rep->cursorName);
54735c4bbdfSmrg        swaps(&rep->nbytes);
54835c4bbdfSmrg        SwapLongs(image, npixels);
54905b261ecSmrg    }
55035c4bbdfSmrg    WriteToClient(client, sizeof(xXFixesGetCursorImageAndNameReply) +
55135c4bbdfSmrg                  (npixels << 2) + nbytesRound, rep);
5526747b715Smrg    free(rep);
5536747b715Smrg    return Success;
55405b261ecSmrg}
55505b261ecSmrg
55605b261ecSmrgint
55735c4bbdfSmrgSProcXFixesGetCursorImageAndName(ClientPtr client)
55805b261ecSmrg{
55905b261ecSmrg    REQUEST(xXFixesGetCursorImageAndNameReq);
56035c4bbdfSmrg    swaps(&stuff->length);
56105b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
56205b261ecSmrg}
56305b261ecSmrg
56405b261ecSmrg/*
56505b261ecSmrg * Find every cursor reference in the system, ask testCursor
56605b261ecSmrg * whether it should be replaced with a reference to pCursor.
56705b261ecSmrg */
56805b261ecSmrg
56935c4bbdfSmrgtypedef Bool (*TestCursorFunc) (CursorPtr pOld, void *closure);
57005b261ecSmrg
57105b261ecSmrgtypedef struct {
57205b261ecSmrg    RESTYPE type;
57305b261ecSmrg    TestCursorFunc testCursor;
57405b261ecSmrg    CursorPtr pNew;
57535c4bbdfSmrg    void *closure;
57605b261ecSmrg} ReplaceCursorLookupRec, *ReplaceCursorLookupPtr;
57705b261ecSmrg
57835c4bbdfSmrgstatic const RESTYPE CursorRestypes[] = {
57905b261ecSmrg    RT_WINDOW, RT_PASSIVEGRAB, RT_CURSOR
58005b261ecSmrg};
58105b261ecSmrg
58205b261ecSmrg#define NUM_CURSOR_RESTYPES (sizeof (CursorRestypes) / sizeof (CursorRestypes[0]))
58305b261ecSmrg
58405b261ecSmrgstatic Bool
58535c4bbdfSmrgReplaceCursorLookup(void *value, XID id, void *closure)
58605b261ecSmrg{
58735c4bbdfSmrg    ReplaceCursorLookupPtr rcl = (ReplaceCursorLookupPtr) closure;
58835c4bbdfSmrg    WindowPtr pWin;
58935c4bbdfSmrg    GrabPtr pGrab;
59035c4bbdfSmrg    CursorPtr pCursor = 0, *pCursorRef = 0;
59135c4bbdfSmrg    XID cursor = 0;
59205b261ecSmrg
59305b261ecSmrg    switch (rcl->type) {
59405b261ecSmrg    case RT_WINDOW:
59535c4bbdfSmrg        pWin = (WindowPtr) value;
59635c4bbdfSmrg        if (pWin->optional) {
59735c4bbdfSmrg            pCursorRef = &pWin->optional->cursor;
59835c4bbdfSmrg            pCursor = *pCursorRef;
59935c4bbdfSmrg        }
60035c4bbdfSmrg        break;
60105b261ecSmrg    case RT_PASSIVEGRAB:
60235c4bbdfSmrg        pGrab = (GrabPtr) value;
60335c4bbdfSmrg        pCursorRef = &pGrab->cursor;
60435c4bbdfSmrg        pCursor = *pCursorRef;
60535c4bbdfSmrg        break;
60605b261ecSmrg    case RT_CURSOR:
60735c4bbdfSmrg        pCursorRef = 0;
60835c4bbdfSmrg        pCursor = (CursorPtr) value;
60935c4bbdfSmrg        cursor = id;
61035c4bbdfSmrg        break;
61105b261ecSmrg    }
61235c4bbdfSmrg    if (pCursor && pCursor != rcl->pNew) {
61335c4bbdfSmrg        if ((*rcl->testCursor) (pCursor, rcl->closure)) {
61435c4bbdfSmrg            CursorPtr curs = RefCursor(rcl->pNew);
61535c4bbdfSmrg            /* either redirect reference or update resource database */
61635c4bbdfSmrg            if (pCursorRef)
61735c4bbdfSmrg                *pCursorRef = curs;
61835c4bbdfSmrg            else
61935c4bbdfSmrg                ChangeResourceValue(id, RT_CURSOR, curs);
62035c4bbdfSmrg            FreeCursor(pCursor, cursor);
62135c4bbdfSmrg        }
62205b261ecSmrg    }
62335c4bbdfSmrg    return FALSE;               /* keep walking */
62405b261ecSmrg}
62505b261ecSmrg
62605b261ecSmrgstatic void
62735c4bbdfSmrgReplaceCursor(CursorPtr pCursor, TestCursorFunc testCursor, void *closure)
62805b261ecSmrg{
62935c4bbdfSmrg    int clientIndex;
63005b261ecSmrg    int resIndex;
63135c4bbdfSmrg    ReplaceCursorLookupRec rcl;
63235c4bbdfSmrg
63335c4bbdfSmrg    /*
63405b261ecSmrg     * Cursors exist only in the resource database, windows and grabs.
63505b261ecSmrg     * All of these are always pointed at by the resource database.  Walk
63605b261ecSmrg     * the whole thing looking for cursors
63705b261ecSmrg     */
63805b261ecSmrg    rcl.testCursor = testCursor;
63905b261ecSmrg    rcl.pNew = pCursor;
64005b261ecSmrg    rcl.closure = closure;
64105b261ecSmrg
64205b261ecSmrg    /* for each client */
64335c4bbdfSmrg    for (clientIndex = 0; clientIndex < currentMaxClients; clientIndex++) {
64435c4bbdfSmrg        if (!clients[clientIndex])
64535c4bbdfSmrg            continue;
64635c4bbdfSmrg        for (resIndex = 0; resIndex < NUM_CURSOR_RESTYPES; resIndex++) {
64735c4bbdfSmrg            rcl.type = CursorRestypes[resIndex];
64835c4bbdfSmrg            /*
64935c4bbdfSmrg             * This function walks the entire client resource database
65035c4bbdfSmrg             */
65135c4bbdfSmrg            LookupClientResourceComplex(clients[clientIndex],
65235c4bbdfSmrg                                        rcl.type,
65335c4bbdfSmrg                                        ReplaceCursorLookup, (void *) &rcl);
65435c4bbdfSmrg        }
65505b261ecSmrg    }
65605b261ecSmrg    /* this "knows" that WindowHasNewCursor doesn't depend on it's argument */
65735c4bbdfSmrg    WindowHasNewCursor(screenInfo.screens[0]->root);
65805b261ecSmrg}
65905b261ecSmrg
66035c4bbdfSmrgstatic Bool
66135c4bbdfSmrgTestForCursor(CursorPtr pCursor, void *closure)
66205b261ecSmrg{
66305b261ecSmrg    return (pCursor == (CursorPtr) closure);
66405b261ecSmrg}
66505b261ecSmrg
66605b261ecSmrgint
66735c4bbdfSmrgProcXFixesChangeCursor(ClientPtr client)
66805b261ecSmrg{
66935c4bbdfSmrg    CursorPtr pSource, pDestination;
67035c4bbdfSmrg
67105b261ecSmrg    REQUEST(xXFixesChangeCursorReq);
67205b261ecSmrg
67305b261ecSmrg    REQUEST_SIZE_MATCH(xXFixesChangeCursorReq);
67435c4bbdfSmrg    VERIFY_CURSOR(pSource, stuff->source, client,
67535c4bbdfSmrg                  DixReadAccess | DixGetAttrAccess);
67635c4bbdfSmrg    VERIFY_CURSOR(pDestination, stuff->destination, client,
67735c4bbdfSmrg                  DixWriteAccess | DixSetAttrAccess);
67805b261ecSmrg
67935c4bbdfSmrg    ReplaceCursor(pSource, TestForCursor, (void *) pDestination);
6806747b715Smrg    return Success;
68105b261ecSmrg}
68205b261ecSmrg
68305b261ecSmrgint
68435c4bbdfSmrgSProcXFixesChangeCursor(ClientPtr client)
68505b261ecSmrg{
68605b261ecSmrg    REQUEST(xXFixesChangeCursorReq);
68705b261ecSmrg
68835c4bbdfSmrg    swaps(&stuff->length);
68905b261ecSmrg    REQUEST_SIZE_MATCH(xXFixesChangeCursorReq);
69035c4bbdfSmrg    swapl(&stuff->source);
69135c4bbdfSmrg    swapl(&stuff->destination);
69205b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
69305b261ecSmrg}
69405b261ecSmrg
69505b261ecSmrgstatic Bool
69635c4bbdfSmrgTestForCursorName(CursorPtr pCursor, void *closure)
69705b261ecSmrg{
6984642e01fSmrg    Atom *pName = closure;
69935c4bbdfSmrg
7006747b715Smrg    return pCursor->name == *pName;
70105b261ecSmrg}
70205b261ecSmrg
70305b261ecSmrgint
70435c4bbdfSmrgProcXFixesChangeCursorByName(ClientPtr client)
70505b261ecSmrg{
70635c4bbdfSmrg    CursorPtr pSource;
70735c4bbdfSmrg    Atom name;
70835c4bbdfSmrg    char *tchar;
70935c4bbdfSmrg
71005b261ecSmrg    REQUEST(xXFixesChangeCursorByNameReq);
71105b261ecSmrg
71205b261ecSmrg    REQUEST_FIXED_SIZE(xXFixesChangeCursorByNameReq, stuff->nbytes);
7134642e01fSmrg    VERIFY_CURSOR(pSource, stuff->source, client,
71435c4bbdfSmrg                  DixReadAccess | DixGetAttrAccess);
71505b261ecSmrg    tchar = (char *) &stuff[1];
71635c4bbdfSmrg    name = MakeAtom(tchar, stuff->nbytes, FALSE);
71705b261ecSmrg    if (name)
71835c4bbdfSmrg        ReplaceCursor(pSource, TestForCursorName, &name);
7196747b715Smrg    return Success;
72005b261ecSmrg}
72105b261ecSmrg
72205b261ecSmrgint
72335c4bbdfSmrgSProcXFixesChangeCursorByName(ClientPtr client)
72405b261ecSmrg{
72505b261ecSmrg    REQUEST(xXFixesChangeCursorByNameReq);
72605b261ecSmrg
72735c4bbdfSmrg    swaps(&stuff->length);
72835c4bbdfSmrg    REQUEST_AT_LEAST_SIZE(xXFixesChangeCursorByNameReq);
72935c4bbdfSmrg    swapl(&stuff->source);
73035c4bbdfSmrg    swaps(&stuff->nbytes);
73105b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
73205b261ecSmrg}
73305b261ecSmrg
73405b261ecSmrg/*
73505b261ecSmrg * Routines for manipulating the per-screen hide counts list.
73635c4bbdfSmrg * This list indicates which clients have requested cursor hiding
73705b261ecSmrg * for that screen.
73805b261ecSmrg */
73905b261ecSmrg
74005b261ecSmrg/* Return the screen's hide-counts list element for the given client */
74105b261ecSmrgstatic CursorHideCountPtr
74235c4bbdfSmrgfindCursorHideCount(ClientPtr pClient, ScreenPtr pScreen)
74305b261ecSmrg{
74435c4bbdfSmrg    CursorScreenPtr cs = GetCursorScreen(pScreen);
74505b261ecSmrg    CursorHideCountPtr pChc;
74605b261ecSmrg
74705b261ecSmrg    for (pChc = cs->pCursorHideCounts; pChc != NULL; pChc = pChc->pNext) {
74835c4bbdfSmrg        if (pChc->pClient == pClient) {
74935c4bbdfSmrg            return pChc;
75035c4bbdfSmrg        }
75105b261ecSmrg    }
75205b261ecSmrg
75335c4bbdfSmrg    return NULL;
75405b261ecSmrg}
75505b261ecSmrg
75605b261ecSmrgstatic int
75735c4bbdfSmrgcreateCursorHideCount(ClientPtr pClient, ScreenPtr pScreen)
75805b261ecSmrg{
75935c4bbdfSmrg    CursorScreenPtr cs = GetCursorScreen(pScreen);
76005b261ecSmrg    CursorHideCountPtr pChc;
76105b261ecSmrg
7626747b715Smrg    pChc = (CursorHideCountPtr) malloc(sizeof(CursorHideCountRec));
76305b261ecSmrg    if (pChc == NULL) {
76435c4bbdfSmrg        return BadAlloc;
76505b261ecSmrg    }
76605b261ecSmrg    pChc->pClient = pClient;
76705b261ecSmrg    pChc->pScreen = pScreen;
76805b261ecSmrg    pChc->hideCount = 1;
76905b261ecSmrg    pChc->resource = FakeClientID(pClient->index);
77005b261ecSmrg    pChc->pNext = cs->pCursorHideCounts;
77105b261ecSmrg    cs->pCursorHideCounts = pChc;
77235c4bbdfSmrg
77335c4bbdfSmrg    /*
77405b261ecSmrg     * Create a resource for this element so it can be deleted
77505b261ecSmrg     * when the client goes away.
77605b261ecSmrg     */
77735c4bbdfSmrg    if (!AddResource(pChc->resource, CursorHideCountType, (void *) pChc))
77835c4bbdfSmrg        return BadAlloc;
77905b261ecSmrg
78005b261ecSmrg    return Success;
78105b261ecSmrg}
78205b261ecSmrg
78335c4bbdfSmrg/*
78405b261ecSmrg * Delete the given hide-counts list element from its screen list.
78505b261ecSmrg */
78605b261ecSmrgstatic void
78735c4bbdfSmrgdeleteCursorHideCount(CursorHideCountPtr pChcToDel, ScreenPtr pScreen)
78805b261ecSmrg{
78935c4bbdfSmrg    CursorScreenPtr cs = GetCursorScreen(pScreen);
79005b261ecSmrg    CursorHideCountPtr pChc, pNext;
79105b261ecSmrg    CursorHideCountPtr pChcLast = NULL;
79205b261ecSmrg
79305b261ecSmrg    pChc = cs->pCursorHideCounts;
79405b261ecSmrg    while (pChc != NULL) {
79535c4bbdfSmrg        pNext = pChc->pNext;
79635c4bbdfSmrg        if (pChc == pChcToDel) {
79735c4bbdfSmrg            free(pChc);
79835c4bbdfSmrg            if (pChcLast == NULL) {
79935c4bbdfSmrg                cs->pCursorHideCounts = pNext;
80035c4bbdfSmrg            }
80135c4bbdfSmrg            else {
80235c4bbdfSmrg                pChcLast->pNext = pNext;
80335c4bbdfSmrg            }
80435c4bbdfSmrg            return;
80535c4bbdfSmrg        }
80635c4bbdfSmrg        pChcLast = pChc;
80735c4bbdfSmrg        pChc = pNext;
80805b261ecSmrg    }
80905b261ecSmrg}
81005b261ecSmrg
81135c4bbdfSmrg/*
81205b261ecSmrg * Delete all the hide-counts list elements for this screen.
81305b261ecSmrg */
81405b261ecSmrgstatic void
81535c4bbdfSmrgdeleteCursorHideCountsForScreen(ScreenPtr pScreen)
81605b261ecSmrg{
81735c4bbdfSmrg    CursorScreenPtr cs = GetCursorScreen(pScreen);
81805b261ecSmrg    CursorHideCountPtr pChc, pTmp;
81905b261ecSmrg
82005b261ecSmrg    pChc = cs->pCursorHideCounts;
82105b261ecSmrg    while (pChc != NULL) {
82235c4bbdfSmrg        pTmp = pChc->pNext;
82335c4bbdfSmrg        FreeResource(pChc->resource, 0);
82435c4bbdfSmrg        pChc = pTmp;
82505b261ecSmrg    }
82635c4bbdfSmrg    cs->pCursorHideCounts = NULL;
82705b261ecSmrg}
82805b261ecSmrg
82935c4bbdfSmrgint
83035c4bbdfSmrgProcXFixesHideCursor(ClientPtr client)
83105b261ecSmrg{
83205b261ecSmrg    WindowPtr pWin;
83305b261ecSmrg    CursorHideCountPtr pChc;
83435c4bbdfSmrg
83505b261ecSmrg    REQUEST(xXFixesHideCursorReq);
83605b261ecSmrg    int ret;
83705b261ecSmrg
83835c4bbdfSmrg    REQUEST_SIZE_MATCH(xXFixesHideCursorReq);
83905b261ecSmrg
84035c4bbdfSmrg    ret = dixLookupResourceByType((void **) &pWin, stuff->window, RT_WINDOW,
84135c4bbdfSmrg                                  client, DixGetAttrAccess);
8424642e01fSmrg    if (ret != Success) {
84335c4bbdfSmrg        client->errorValue = stuff->window;
84435c4bbdfSmrg        return ret;
84505b261ecSmrg    }
84605b261ecSmrg
84735c4bbdfSmrg    /*
84835c4bbdfSmrg     * Has client hidden the cursor before on this screen?
84935c4bbdfSmrg     * If so, just increment the count.
85005b261ecSmrg     */
85105b261ecSmrg
85205b261ecSmrg    pChc = findCursorHideCount(client, pWin->drawable.pScreen);
85305b261ecSmrg    if (pChc != NULL) {
85435c4bbdfSmrg        pChc->hideCount++;
85535c4bbdfSmrg        return Success;
85605b261ecSmrg    }
85705b261ecSmrg
85835c4bbdfSmrg    /*
85935c4bbdfSmrg     * This is the first time this client has hid the cursor
86005b261ecSmrg     * for this screen.
86105b261ecSmrg     */
8624642e01fSmrg    ret = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen,
86335c4bbdfSmrg                   DixHideAccess);
8644642e01fSmrg    if (ret != Success)
86535c4bbdfSmrg        return ret;
8664642e01fSmrg
86705b261ecSmrg    ret = createCursorHideCount(client, pWin->drawable.pScreen);
86805b261ecSmrg
86905b261ecSmrg    if (ret == Success) {
87035c4bbdfSmrg        DeviceIntPtr dev;
87135c4bbdfSmrg
87235c4bbdfSmrg        for (dev = inputInfo.devices; dev; dev = dev->next) {
87335c4bbdfSmrg            if (IsMaster(dev) && IsPointerDevice(dev))
87435c4bbdfSmrg                CursorDisplayCursor(dev, pWin->drawable.pScreen,
87535c4bbdfSmrg                                    CursorCurrent[dev->id]);
87635c4bbdfSmrg        }
87705b261ecSmrg    }
87805b261ecSmrg
87905b261ecSmrg    return ret;
88005b261ecSmrg}
88105b261ecSmrg
88235c4bbdfSmrgint
88335c4bbdfSmrgSProcXFixesHideCursor(ClientPtr client)
88405b261ecSmrg{
88505b261ecSmrg    REQUEST(xXFixesHideCursorReq);
88605b261ecSmrg
88735c4bbdfSmrg    swaps(&stuff->length);
88835c4bbdfSmrg    REQUEST_SIZE_MATCH(xXFixesHideCursorReq);
88935c4bbdfSmrg    swapl(&stuff->window);
89005b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
89105b261ecSmrg}
89205b261ecSmrg
89335c4bbdfSmrgint
89435c4bbdfSmrgProcXFixesShowCursor(ClientPtr client)
89505b261ecSmrg{
89605b261ecSmrg    WindowPtr pWin;
89705b261ecSmrg    CursorHideCountPtr pChc;
8984642e01fSmrg    int rc;
89935c4bbdfSmrg
90005b261ecSmrg    REQUEST(xXFixesShowCursorReq);
90105b261ecSmrg
90235c4bbdfSmrg    REQUEST_SIZE_MATCH(xXFixesShowCursorReq);
90305b261ecSmrg
90435c4bbdfSmrg    rc = dixLookupResourceByType((void **) &pWin, stuff->window, RT_WINDOW,
90535c4bbdfSmrg                                 client, DixGetAttrAccess);
9064642e01fSmrg    if (rc != Success) {
90735c4bbdfSmrg        client->errorValue = stuff->window;
90835c4bbdfSmrg        return rc;
90905b261ecSmrg    }
91005b261ecSmrg
91135c4bbdfSmrg    /*
91205b261ecSmrg     * Has client hidden the cursor on this screen?
91305b261ecSmrg     * If not, generate an error.
91405b261ecSmrg     */
91505b261ecSmrg    pChc = findCursorHideCount(client, pWin->drawable.pScreen);
91605b261ecSmrg    if (pChc == NULL) {
91735c4bbdfSmrg        return BadMatch;
91805b261ecSmrg    }
91905b261ecSmrg
9204642e01fSmrg    rc = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen,
92135c4bbdfSmrg                  DixShowAccess);
9224642e01fSmrg    if (rc != Success)
92335c4bbdfSmrg        return rc;
9244642e01fSmrg
92505b261ecSmrg    pChc->hideCount--;
92605b261ecSmrg    if (pChc->hideCount <= 0) {
92735c4bbdfSmrg        FreeResource(pChc->resource, 0);
92805b261ecSmrg    }
92905b261ecSmrg
9306747b715Smrg    return Success;
93105b261ecSmrg}
93205b261ecSmrg
93335c4bbdfSmrgint
93435c4bbdfSmrgSProcXFixesShowCursor(ClientPtr client)
93505b261ecSmrg{
93605b261ecSmrg    REQUEST(xXFixesShowCursorReq);
93705b261ecSmrg
93835c4bbdfSmrg    swaps(&stuff->length);
93935c4bbdfSmrg    REQUEST_SIZE_MATCH(xXFixesShowCursorReq);
94035c4bbdfSmrg    swapl(&stuff->window);
94105b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
94205b261ecSmrg}
94305b261ecSmrg
94405b261ecSmrgstatic int
94535c4bbdfSmrgCursorFreeClient(void *data, XID id)
94605b261ecSmrg{
94735c4bbdfSmrg    CursorEventPtr old = (CursorEventPtr) data;
94835c4bbdfSmrg    CursorEventPtr *prev, e;
94935c4bbdfSmrg
95035c4bbdfSmrg    for (prev = &cursorEvents; (e = *prev); prev = &e->next) {
95135c4bbdfSmrg        if (e == old) {
95235c4bbdfSmrg            *prev = e->next;
95335c4bbdfSmrg            free(e);
95435c4bbdfSmrg            break;
95535c4bbdfSmrg        }
95605b261ecSmrg    }
95705b261ecSmrg    return 1;
95805b261ecSmrg}
95905b261ecSmrg
96005b261ecSmrgstatic int
96135c4bbdfSmrgCursorFreeHideCount(void *data, XID id)
96205b261ecSmrg{
96305b261ecSmrg    CursorHideCountPtr pChc = (CursorHideCountPtr) data;
96405b261ecSmrg    ScreenPtr pScreen = pChc->pScreen;
9656747b715Smrg    DeviceIntPtr dev;
96605b261ecSmrg
96705b261ecSmrg    deleteCursorHideCount(pChc, pChc->pScreen);
96835c4bbdfSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
9696747b715Smrg        if (IsMaster(dev) && IsPointerDevice(dev))
9706747b715Smrg            CursorDisplayCursor(dev, pScreen, CursorCurrent[dev->id]);
9716747b715Smrg    }
97205b261ecSmrg
97305b261ecSmrg    return 1;
97405b261ecSmrg}
97505b261ecSmrg
97605b261ecSmrgstatic int
97735c4bbdfSmrgCursorFreeWindow(void *data, XID id)
97805b261ecSmrg{
97935c4bbdfSmrg    WindowPtr pWindow = (WindowPtr) data;
98035c4bbdfSmrg    CursorEventPtr e, next;
98135c4bbdfSmrg
98235c4bbdfSmrg    for (e = cursorEvents; e; e = next) {
98335c4bbdfSmrg        next = e->next;
98435c4bbdfSmrg        if (e->pWindow == pWindow) {
98535c4bbdfSmrg            FreeResource(e->clientResource, 0);
98635c4bbdfSmrg        }
98705b261ecSmrg    }
98805b261ecSmrg    return 1;
98905b261ecSmrg}
99005b261ecSmrg
99135c4bbdfSmrgint
99235c4bbdfSmrgProcXFixesCreatePointerBarrier(ClientPtr client)
99335c4bbdfSmrg{
99435c4bbdfSmrg    REQUEST(xXFixesCreatePointerBarrierReq);
99535c4bbdfSmrg
99635c4bbdfSmrg    REQUEST_FIXED_SIZE(xXFixesCreatePointerBarrierReq, pad_to_int32(stuff->num_devices));
99735c4bbdfSmrg    LEGAL_NEW_RESOURCE(stuff->barrier, client);
99835c4bbdfSmrg
99935c4bbdfSmrg    return XICreatePointerBarrier(client, stuff);
100035c4bbdfSmrg}
100135c4bbdfSmrg
100235c4bbdfSmrgint
100335c4bbdfSmrgSProcXFixesCreatePointerBarrier(ClientPtr client)
100435c4bbdfSmrg{
100535c4bbdfSmrg    REQUEST(xXFixesCreatePointerBarrierReq);
100635c4bbdfSmrg    int i;
100735c4bbdfSmrg    CARD16 *in_devices = (CARD16 *) &stuff[1];
100835c4bbdfSmrg
100935c4bbdfSmrg    swaps(&stuff->length);
101035c4bbdfSmrg    swaps(&stuff->num_devices);
101135c4bbdfSmrg    REQUEST_FIXED_SIZE(xXFixesCreatePointerBarrierReq, pad_to_int32(stuff->num_devices));
101235c4bbdfSmrg
101335c4bbdfSmrg    swapl(&stuff->barrier);
101435c4bbdfSmrg    swapl(&stuff->window);
101535c4bbdfSmrg    swaps(&stuff->x1);
101635c4bbdfSmrg    swaps(&stuff->y1);
101735c4bbdfSmrg    swaps(&stuff->x2);
101835c4bbdfSmrg    swaps(&stuff->y2);
101935c4bbdfSmrg    swapl(&stuff->directions);
102035c4bbdfSmrg    for (i = 0; i < stuff->num_devices; i++) {
102135c4bbdfSmrg        swaps(in_devices + i);
102235c4bbdfSmrg    }
102335c4bbdfSmrg
102435c4bbdfSmrg    return ProcXFixesVector[stuff->xfixesReqType] (client);
102535c4bbdfSmrg}
102635c4bbdfSmrg
102735c4bbdfSmrgint
102835c4bbdfSmrgProcXFixesDestroyPointerBarrier(ClientPtr client)
102935c4bbdfSmrg{
103035c4bbdfSmrg    REQUEST(xXFixesDestroyPointerBarrierReq);
103135c4bbdfSmrg
103235c4bbdfSmrg    REQUEST_SIZE_MATCH(xXFixesDestroyPointerBarrierReq);
103335c4bbdfSmrg
103435c4bbdfSmrg    return XIDestroyPointerBarrier(client, stuff);
103535c4bbdfSmrg}
103635c4bbdfSmrg
103735c4bbdfSmrgint
103835c4bbdfSmrgSProcXFixesDestroyPointerBarrier(ClientPtr client)
103935c4bbdfSmrg{
104035c4bbdfSmrg    REQUEST(xXFixesDestroyPointerBarrierReq);
104135c4bbdfSmrg
104235c4bbdfSmrg    swaps(&stuff->length);
104335c4bbdfSmrg    REQUEST_SIZE_MATCH(xXFixesDestroyPointerBarrierReq);
104435c4bbdfSmrg    swapl(&stuff->barrier);
104535c4bbdfSmrg    return ProcXFixesVector[stuff->xfixesReqType] (client);
104635c4bbdfSmrg}
104735c4bbdfSmrg
104805b261ecSmrgBool
104935c4bbdfSmrgXFixesCursorInit(void)
105005b261ecSmrg{
105135c4bbdfSmrg    int i;
10524642e01fSmrg
10534642e01fSmrg    if (party_like_its_1989)
105435c4bbdfSmrg        CursorVisible = EnableCursor;
105535c4bbdfSmrg    else
105635c4bbdfSmrg        CursorVisible = FALSE;
10576747b715Smrg
105835c4bbdfSmrg    if (!dixRegisterPrivateKey(&CursorScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
105935c4bbdfSmrg        return FALSE;
106035c4bbdfSmrg
106135c4bbdfSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
106235c4bbdfSmrg        ScreenPtr pScreen = screenInfo.screens[i];
106335c4bbdfSmrg        CursorScreenPtr cs;
106435c4bbdfSmrg
106535c4bbdfSmrg        cs = (CursorScreenPtr) calloc(1, sizeof(CursorScreenRec));
106635c4bbdfSmrg        if (!cs)
106735c4bbdfSmrg            return FALSE;
106835c4bbdfSmrg        Wrap(cs, pScreen, CloseScreen, CursorCloseScreen);
106935c4bbdfSmrg        Wrap(cs, pScreen, DisplayCursor, CursorDisplayCursor);
107035c4bbdfSmrg        cs->pCursorHideCounts = NULL;
107135c4bbdfSmrg        SetCursorScreen(pScreen, cs);
107205b261ecSmrg    }
10736747b715Smrg    CursorClientType = CreateNewResourceType(CursorFreeClient,
107435c4bbdfSmrg                                             "XFixesCursorClient");
10756747b715Smrg    CursorHideCountType = CreateNewResourceType(CursorFreeHideCount,
107635c4bbdfSmrg                                                "XFixesCursorHideCount");
10776747b715Smrg    CursorWindowType = CreateNewResourceType(CursorFreeWindow,
107835c4bbdfSmrg                                             "XFixesCursorWindow");
10796747b715Smrg
10806747b715Smrg    return CursorClientType && CursorHideCountType && CursorWindowType;
108105b261ecSmrg}
1082