cursor.c revision 6e78d31f
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);
2836e78d31fSmrg    REQUEST_SIZE_MATCH(xXFixesSelectCursorInputReq);
28405b261ecSmrg
28535c4bbdfSmrg    swaps(&stuff->length);
28635c4bbdfSmrg    swapl(&stuff->window);
28735c4bbdfSmrg    swapl(&stuff->eventMask);
28805b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
28905b261ecSmrg}
29035c4bbdfSmrg
29105b261ecSmrgvoid
29235c4bbdfSmrgSXFixesCursorNotifyEvent(xXFixesCursorNotifyEvent * from,
29335c4bbdfSmrg                         xXFixesCursorNotifyEvent * to)
29405b261ecSmrg{
29505b261ecSmrg    to->type = from->type;
29635c4bbdfSmrg    cpswaps(from->sequenceNumber, to->sequenceNumber);
29735c4bbdfSmrg    cpswapl(from->window, to->window);
29835c4bbdfSmrg    cpswapl(from->cursorSerial, to->cursorSerial);
29935c4bbdfSmrg    cpswapl(from->timestamp, to->timestamp);
30035c4bbdfSmrg    cpswapl(from->name, to->name);
30105b261ecSmrg}
30205b261ecSmrg
30305b261ecSmrgstatic void
30435c4bbdfSmrgCopyCursorToImage(CursorPtr pCursor, CARD32 *image)
30505b261ecSmrg{
30605b261ecSmrg    int width = pCursor->bits->width;
30705b261ecSmrg    int height = pCursor->bits->height;
30805b261ecSmrg    int npixels = width * height;
30935c4bbdfSmrg
31005b261ecSmrg    if (pCursor->bits->argb)
31135c4bbdfSmrg        memcpy(image, pCursor->bits->argb, npixels * sizeof(CARD32));
31205b261ecSmrg    else
31305b261ecSmrg    {
31435c4bbdfSmrg        unsigned char *srcLine = pCursor->bits->source;
31535c4bbdfSmrg        unsigned char *mskLine = pCursor->bits->mask;
31635c4bbdfSmrg        int stride = BitmapBytePad(width);
31735c4bbdfSmrg        int x, y;
31835c4bbdfSmrg        CARD32 fg, bg;
31935c4bbdfSmrg
32035c4bbdfSmrg        fg = (0xff000000 |
32135c4bbdfSmrg              ((pCursor->foreRed & 0xff00) << 8) |
32235c4bbdfSmrg              (pCursor->foreGreen & 0xff00) | (pCursor->foreBlue >> 8));
32335c4bbdfSmrg        bg = (0xff000000 |
32435c4bbdfSmrg              ((pCursor->backRed & 0xff00) << 8) |
32535c4bbdfSmrg              (pCursor->backGreen & 0xff00) | (pCursor->backBlue >> 8));
32635c4bbdfSmrg        for (y = 0; y < height; y++) {
32735c4bbdfSmrg            for (x = 0; x < width; x++) {
32835c4bbdfSmrg                if (GetBit(mskLine, x)) {
32935c4bbdfSmrg                    if (GetBit(srcLine, x))
33035c4bbdfSmrg                        *image++ = fg;
33135c4bbdfSmrg                    else
33235c4bbdfSmrg                        *image++ = bg;
33335c4bbdfSmrg                }
33435c4bbdfSmrg                else
33535c4bbdfSmrg                    *image++ = 0;
33635c4bbdfSmrg            }
33735c4bbdfSmrg            srcLine += stride;
33835c4bbdfSmrg            mskLine += stride;
33935c4bbdfSmrg        }
34005b261ecSmrg    }
34105b261ecSmrg}
34205b261ecSmrg
34305b261ecSmrgint
34435c4bbdfSmrgProcXFixesGetCursorImage(ClientPtr client)
34505b261ecSmrg{
34605b261ecSmrg/*    REQUEST(xXFixesGetCursorImageReq); */
34735c4bbdfSmrg    xXFixesGetCursorImageReply *rep;
34835c4bbdfSmrg    CursorPtr pCursor;
34935c4bbdfSmrg    CARD32 *image;
35035c4bbdfSmrg    int npixels, width, height, rc, x, y;
35105b261ecSmrg
35205b261ecSmrg    REQUEST_SIZE_MATCH(xXFixesGetCursorImageReq);
3536747b715Smrg    pCursor = CursorCurrent[PickPointer(client)->id];
35405b261ecSmrg    if (!pCursor)
35535c4bbdfSmrg        return BadCursor;
3564642e01fSmrg    rc = XaceHook(XACE_RESOURCE_ACCESS, client, pCursor->id, RT_CURSOR,
35735c4bbdfSmrg                  pCursor, RT_NONE, NULL, DixReadAccess);
3584642e01fSmrg    if (rc != Success)
35935c4bbdfSmrg        return rc;
36035c4bbdfSmrg    GetSpritePosition(PickPointer(client), &x, &y);
36105b261ecSmrg    width = pCursor->bits->width;
36205b261ecSmrg    height = pCursor->bits->height;
36305b261ecSmrg    npixels = width * height;
36435c4bbdfSmrg    rep = calloc(sizeof(xXFixesGetCursorImageReply) + npixels * sizeof(CARD32),
36535c4bbdfSmrg                 1);
36605b261ecSmrg    if (!rep)
36735c4bbdfSmrg        return BadAlloc;
36805b261ecSmrg
36905b261ecSmrg    rep->type = X_Reply;
37005b261ecSmrg    rep->sequenceNumber = client->sequence;
37105b261ecSmrg    rep->length = npixels;
37205b261ecSmrg    rep->width = width;
37305b261ecSmrg    rep->height = height;
37405b261ecSmrg    rep->x = x;
37505b261ecSmrg    rep->y = y;
37605b261ecSmrg    rep->xhot = pCursor->bits->xhot;
37735c4bbdfSmrg    rep->yhot = pCursor->bits->yhot;
37805b261ecSmrg    rep->cursorSerial = pCursor->serialNumber;
37905b261ecSmrg
38005b261ecSmrg    image = (CARD32 *) (rep + 1);
38135c4bbdfSmrg    CopyCursorToImage(pCursor, image);
38235c4bbdfSmrg    if (client->swapped) {
38335c4bbdfSmrg        swaps(&rep->sequenceNumber);
38435c4bbdfSmrg        swapl(&rep->length);
38535c4bbdfSmrg        swaps(&rep->x);
38635c4bbdfSmrg        swaps(&rep->y);
38735c4bbdfSmrg        swaps(&rep->width);
38835c4bbdfSmrg        swaps(&rep->height);
38935c4bbdfSmrg        swaps(&rep->xhot);
39035c4bbdfSmrg        swaps(&rep->yhot);
39135c4bbdfSmrg        swapl(&rep->cursorSerial);
39235c4bbdfSmrg        SwapLongs(image, npixels);
39305b261ecSmrg    }
39435c4bbdfSmrg    WriteToClient(client,
39535c4bbdfSmrg                  sizeof(xXFixesGetCursorImageReply) + (npixels << 2), rep);
3966747b715Smrg    free(rep);
3976747b715Smrg    return Success;
39805b261ecSmrg}
39905b261ecSmrg
40005b261ecSmrgint
40135c4bbdfSmrgSProcXFixesGetCursorImage(ClientPtr client)
40205b261ecSmrg{
40305b261ecSmrg    REQUEST(xXFixesGetCursorImageReq);
40435c4bbdfSmrg    swaps(&stuff->length);
40505b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
40605b261ecSmrg}
40705b261ecSmrg
40805b261ecSmrgint
40935c4bbdfSmrgProcXFixesSetCursorName(ClientPtr client)
41005b261ecSmrg{
41105b261ecSmrg    CursorPtr pCursor;
41205b261ecSmrg    char *tchar;
41335c4bbdfSmrg
41405b261ecSmrg    REQUEST(xXFixesSetCursorNameReq);
41505b261ecSmrg    Atom atom;
41605b261ecSmrg
4176e78d31fSmrg    REQUEST_FIXED_SIZE(xXFixesSetCursorNameReq, stuff->nbytes);
4184642e01fSmrg    VERIFY_CURSOR(pCursor, stuff->cursor, client, DixSetAttrAccess);
41905b261ecSmrg    tchar = (char *) &stuff[1];
42035c4bbdfSmrg    atom = MakeAtom(tchar, stuff->nbytes, TRUE);
42105b261ecSmrg    if (atom == BAD_RESOURCE)
42235c4bbdfSmrg        return BadAlloc;
42335c4bbdfSmrg
42405b261ecSmrg    pCursor->name = atom;
4256747b715Smrg    return Success;
42605b261ecSmrg}
42705b261ecSmrg
42805b261ecSmrgint
42935c4bbdfSmrgSProcXFixesSetCursorName(ClientPtr client)
43005b261ecSmrg{
43105b261ecSmrg    REQUEST(xXFixesSetCursorNameReq);
43205b261ecSmrg
43335c4bbdfSmrg    swaps(&stuff->length);
43405b261ecSmrg    REQUEST_AT_LEAST_SIZE(xXFixesSetCursorNameReq);
43535c4bbdfSmrg    swapl(&stuff->cursor);
43635c4bbdfSmrg    swaps(&stuff->nbytes);
43705b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
43805b261ecSmrg}
43905b261ecSmrg
44005b261ecSmrgint
44135c4bbdfSmrgProcXFixesGetCursorName(ClientPtr client)
44205b261ecSmrg{
44335c4bbdfSmrg    CursorPtr pCursor;
44435c4bbdfSmrg    xXFixesGetCursorNameReply reply;
44535c4bbdfSmrg
44605b261ecSmrg    REQUEST(xXFixesGetCursorNameReq);
4476747b715Smrg    const char *str;
44805b261ecSmrg    int len;
44905b261ecSmrg
45005b261ecSmrg    REQUEST_SIZE_MATCH(xXFixesGetCursorNameReq);
4514642e01fSmrg    VERIFY_CURSOR(pCursor, stuff->cursor, client, DixGetAttrAccess);
45205b261ecSmrg    if (pCursor->name)
45335c4bbdfSmrg        str = NameForAtom(pCursor->name);
45405b261ecSmrg    else
45535c4bbdfSmrg        str = "";
45635c4bbdfSmrg    len = strlen(str);
45735c4bbdfSmrg
45835c4bbdfSmrg    reply = (xXFixesGetCursorNameReply) {
45935c4bbdfSmrg        .type = X_Reply,
46035c4bbdfSmrg        .sequenceNumber = client->sequence,
46135c4bbdfSmrg        .length = bytes_to_int32(len),
46235c4bbdfSmrg        .atom = pCursor->name,
46335c4bbdfSmrg        .nbytes = len
46435c4bbdfSmrg    };
46535c4bbdfSmrg    if (client->swapped) {
46635c4bbdfSmrg        swaps(&reply.sequenceNumber);
46735c4bbdfSmrg        swapl(&reply.length);
46835c4bbdfSmrg        swapl(&reply.atom);
46935c4bbdfSmrg        swaps(&reply.nbytes);
47005b261ecSmrg    }
47105b261ecSmrg    WriteReplyToClient(client, sizeof(xXFixesGetCursorNameReply), &reply);
4726747b715Smrg    WriteToClient(client, len, str);
47335c4bbdfSmrg
4746747b715Smrg    return Success;
47505b261ecSmrg}
47605b261ecSmrg
47705b261ecSmrgint
47835c4bbdfSmrgSProcXFixesGetCursorName(ClientPtr client)
47905b261ecSmrg{
48005b261ecSmrg    REQUEST(xXFixesGetCursorNameReq);
48105b261ecSmrg
48235c4bbdfSmrg    swaps(&stuff->length);
48305b261ecSmrg    REQUEST_SIZE_MATCH(xXFixesGetCursorNameReq);
48435c4bbdfSmrg    swapl(&stuff->cursor);
48505b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
48605b261ecSmrg}
48705b261ecSmrg
48805b261ecSmrgint
48935c4bbdfSmrgProcXFixesGetCursorImageAndName(ClientPtr client)
49005b261ecSmrg{
49105b261ecSmrg/*    REQUEST(xXFixesGetCursorImageAndNameReq); */
49235c4bbdfSmrg    xXFixesGetCursorImageAndNameReply *rep;
49335c4bbdfSmrg    CursorPtr pCursor;
49435c4bbdfSmrg    CARD32 *image;
49535c4bbdfSmrg    int npixels;
49635c4bbdfSmrg    const char *name;
49735c4bbdfSmrg    int nbytes, nbytesRound;
49835c4bbdfSmrg    int width, height;
49935c4bbdfSmrg    int rc, x, y;
50005b261ecSmrg
50105b261ecSmrg    REQUEST_SIZE_MATCH(xXFixesGetCursorImageAndNameReq);
5026747b715Smrg    pCursor = CursorCurrent[PickPointer(client)->id];
50305b261ecSmrg    if (!pCursor)
50435c4bbdfSmrg        return BadCursor;
5054642e01fSmrg    rc = XaceHook(XACE_RESOURCE_ACCESS, client, pCursor->id, RT_CURSOR,
50635c4bbdfSmrg                  pCursor, RT_NONE, NULL, DixReadAccess | DixGetAttrAccess);
5074642e01fSmrg    if (rc != Success)
50835c4bbdfSmrg        return rc;
50935c4bbdfSmrg    GetSpritePosition(PickPointer(client), &x, &y);
51005b261ecSmrg    width = pCursor->bits->width;
51105b261ecSmrg    height = pCursor->bits->height;
51205b261ecSmrg    npixels = width * height;
51335c4bbdfSmrg    name = pCursor->name ? NameForAtom(pCursor->name) : "";
51435c4bbdfSmrg    nbytes = strlen(name);
5156747b715Smrg    nbytesRound = pad_to_int32(nbytes);
51635c4bbdfSmrg    rep = calloc(sizeof(xXFixesGetCursorImageAndNameReply) +
51735c4bbdfSmrg                 npixels * sizeof(CARD32) + nbytesRound, 1);
51805b261ecSmrg    if (!rep)
51935c4bbdfSmrg        return BadAlloc;
52005b261ecSmrg
52105b261ecSmrg    rep->type = X_Reply;
52205b261ecSmrg    rep->sequenceNumber = client->sequence;
5236747b715Smrg    rep->length = npixels + bytes_to_int32(nbytesRound);
52405b261ecSmrg    rep->width = width;
52505b261ecSmrg    rep->height = height;
52605b261ecSmrg    rep->x = x;
52705b261ecSmrg    rep->y = y;
52805b261ecSmrg    rep->xhot = pCursor->bits->xhot;
52935c4bbdfSmrg    rep->yhot = pCursor->bits->yhot;
53005b261ecSmrg    rep->cursorSerial = pCursor->serialNumber;
53105b261ecSmrg    rep->cursorName = pCursor->name;
53205b261ecSmrg    rep->nbytes = nbytes;
53305b261ecSmrg
53405b261ecSmrg    image = (CARD32 *) (rep + 1);
53535c4bbdfSmrg    CopyCursorToImage(pCursor, image);
53635c4bbdfSmrg    memcpy((image + npixels), name, nbytes);
53735c4bbdfSmrg    if (client->swapped) {
53835c4bbdfSmrg        swaps(&rep->sequenceNumber);
53935c4bbdfSmrg        swapl(&rep->length);
54035c4bbdfSmrg        swaps(&rep->x);
54135c4bbdfSmrg        swaps(&rep->y);
54235c4bbdfSmrg        swaps(&rep->width);
54335c4bbdfSmrg        swaps(&rep->height);
54435c4bbdfSmrg        swaps(&rep->xhot);
54535c4bbdfSmrg        swaps(&rep->yhot);
54635c4bbdfSmrg        swapl(&rep->cursorSerial);
54735c4bbdfSmrg        swapl(&rep->cursorName);
54835c4bbdfSmrg        swaps(&rep->nbytes);
54935c4bbdfSmrg        SwapLongs(image, npixels);
55005b261ecSmrg    }
55135c4bbdfSmrg    WriteToClient(client, sizeof(xXFixesGetCursorImageAndNameReply) +
55235c4bbdfSmrg                  (npixels << 2) + nbytesRound, rep);
5536747b715Smrg    free(rep);
5546747b715Smrg    return Success;
55505b261ecSmrg}
55605b261ecSmrg
55705b261ecSmrgint
55835c4bbdfSmrgSProcXFixesGetCursorImageAndName(ClientPtr client)
55905b261ecSmrg{
56005b261ecSmrg    REQUEST(xXFixesGetCursorImageAndNameReq);
56135c4bbdfSmrg    swaps(&stuff->length);
56205b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
56305b261ecSmrg}
56405b261ecSmrg
56505b261ecSmrg/*
56605b261ecSmrg * Find every cursor reference in the system, ask testCursor
56705b261ecSmrg * whether it should be replaced with a reference to pCursor.
56805b261ecSmrg */
56905b261ecSmrg
57035c4bbdfSmrgtypedef Bool (*TestCursorFunc) (CursorPtr pOld, void *closure);
57105b261ecSmrg
57205b261ecSmrgtypedef struct {
57305b261ecSmrg    RESTYPE type;
57405b261ecSmrg    TestCursorFunc testCursor;
57505b261ecSmrg    CursorPtr pNew;
57635c4bbdfSmrg    void *closure;
57705b261ecSmrg} ReplaceCursorLookupRec, *ReplaceCursorLookupPtr;
57805b261ecSmrg
57935c4bbdfSmrgstatic const RESTYPE CursorRestypes[] = {
58005b261ecSmrg    RT_WINDOW, RT_PASSIVEGRAB, RT_CURSOR
58105b261ecSmrg};
58205b261ecSmrg
58305b261ecSmrg#define NUM_CURSOR_RESTYPES (sizeof (CursorRestypes) / sizeof (CursorRestypes[0]))
58405b261ecSmrg
58505b261ecSmrgstatic Bool
58635c4bbdfSmrgReplaceCursorLookup(void *value, XID id, void *closure)
58705b261ecSmrg{
58835c4bbdfSmrg    ReplaceCursorLookupPtr rcl = (ReplaceCursorLookupPtr) closure;
58935c4bbdfSmrg    WindowPtr pWin;
59035c4bbdfSmrg    GrabPtr pGrab;
59135c4bbdfSmrg    CursorPtr pCursor = 0, *pCursorRef = 0;
59235c4bbdfSmrg    XID cursor = 0;
59305b261ecSmrg
59405b261ecSmrg    switch (rcl->type) {
59505b261ecSmrg    case RT_WINDOW:
59635c4bbdfSmrg        pWin = (WindowPtr) value;
59735c4bbdfSmrg        if (pWin->optional) {
59835c4bbdfSmrg            pCursorRef = &pWin->optional->cursor;
59935c4bbdfSmrg            pCursor = *pCursorRef;
60035c4bbdfSmrg        }
60135c4bbdfSmrg        break;
60205b261ecSmrg    case RT_PASSIVEGRAB:
60335c4bbdfSmrg        pGrab = (GrabPtr) value;
60435c4bbdfSmrg        pCursorRef = &pGrab->cursor;
60535c4bbdfSmrg        pCursor = *pCursorRef;
60635c4bbdfSmrg        break;
60705b261ecSmrg    case RT_CURSOR:
60835c4bbdfSmrg        pCursorRef = 0;
60935c4bbdfSmrg        pCursor = (CursorPtr) value;
61035c4bbdfSmrg        cursor = id;
61135c4bbdfSmrg        break;
61205b261ecSmrg    }
61335c4bbdfSmrg    if (pCursor && pCursor != rcl->pNew) {
61435c4bbdfSmrg        if ((*rcl->testCursor) (pCursor, rcl->closure)) {
61535c4bbdfSmrg            CursorPtr curs = RefCursor(rcl->pNew);
61635c4bbdfSmrg            /* either redirect reference or update resource database */
61735c4bbdfSmrg            if (pCursorRef)
61835c4bbdfSmrg                *pCursorRef = curs;
61935c4bbdfSmrg            else
62035c4bbdfSmrg                ChangeResourceValue(id, RT_CURSOR, curs);
62135c4bbdfSmrg            FreeCursor(pCursor, cursor);
62235c4bbdfSmrg        }
62305b261ecSmrg    }
62435c4bbdfSmrg    return FALSE;               /* keep walking */
62505b261ecSmrg}
62605b261ecSmrg
62705b261ecSmrgstatic void
62835c4bbdfSmrgReplaceCursor(CursorPtr pCursor, TestCursorFunc testCursor, void *closure)
62905b261ecSmrg{
63035c4bbdfSmrg    int clientIndex;
63105b261ecSmrg    int resIndex;
63235c4bbdfSmrg    ReplaceCursorLookupRec rcl;
63335c4bbdfSmrg
63435c4bbdfSmrg    /*
63505b261ecSmrg     * Cursors exist only in the resource database, windows and grabs.
63605b261ecSmrg     * All of these are always pointed at by the resource database.  Walk
63705b261ecSmrg     * the whole thing looking for cursors
63805b261ecSmrg     */
63905b261ecSmrg    rcl.testCursor = testCursor;
64005b261ecSmrg    rcl.pNew = pCursor;
64105b261ecSmrg    rcl.closure = closure;
64205b261ecSmrg
64305b261ecSmrg    /* for each client */
64435c4bbdfSmrg    for (clientIndex = 0; clientIndex < currentMaxClients; clientIndex++) {
64535c4bbdfSmrg        if (!clients[clientIndex])
64635c4bbdfSmrg            continue;
64735c4bbdfSmrg        for (resIndex = 0; resIndex < NUM_CURSOR_RESTYPES; resIndex++) {
64835c4bbdfSmrg            rcl.type = CursorRestypes[resIndex];
64935c4bbdfSmrg            /*
65035c4bbdfSmrg             * This function walks the entire client resource database
65135c4bbdfSmrg             */
65235c4bbdfSmrg            LookupClientResourceComplex(clients[clientIndex],
65335c4bbdfSmrg                                        rcl.type,
65435c4bbdfSmrg                                        ReplaceCursorLookup, (void *) &rcl);
65535c4bbdfSmrg        }
65605b261ecSmrg    }
65705b261ecSmrg    /* this "knows" that WindowHasNewCursor doesn't depend on it's argument */
65835c4bbdfSmrg    WindowHasNewCursor(screenInfo.screens[0]->root);
65905b261ecSmrg}
66005b261ecSmrg
66135c4bbdfSmrgstatic Bool
66235c4bbdfSmrgTestForCursor(CursorPtr pCursor, void *closure)
66305b261ecSmrg{
66405b261ecSmrg    return (pCursor == (CursorPtr) closure);
66505b261ecSmrg}
66605b261ecSmrg
66705b261ecSmrgint
66835c4bbdfSmrgProcXFixesChangeCursor(ClientPtr client)
66905b261ecSmrg{
67035c4bbdfSmrg    CursorPtr pSource, pDestination;
67135c4bbdfSmrg
67205b261ecSmrg    REQUEST(xXFixesChangeCursorReq);
67305b261ecSmrg
67405b261ecSmrg    REQUEST_SIZE_MATCH(xXFixesChangeCursorReq);
67535c4bbdfSmrg    VERIFY_CURSOR(pSource, stuff->source, client,
67635c4bbdfSmrg                  DixReadAccess | DixGetAttrAccess);
67735c4bbdfSmrg    VERIFY_CURSOR(pDestination, stuff->destination, client,
67835c4bbdfSmrg                  DixWriteAccess | DixSetAttrAccess);
67905b261ecSmrg
68035c4bbdfSmrg    ReplaceCursor(pSource, TestForCursor, (void *) pDestination);
6816747b715Smrg    return Success;
68205b261ecSmrg}
68305b261ecSmrg
68405b261ecSmrgint
68535c4bbdfSmrgSProcXFixesChangeCursor(ClientPtr client)
68605b261ecSmrg{
68705b261ecSmrg    REQUEST(xXFixesChangeCursorReq);
68805b261ecSmrg
68935c4bbdfSmrg    swaps(&stuff->length);
69005b261ecSmrg    REQUEST_SIZE_MATCH(xXFixesChangeCursorReq);
69135c4bbdfSmrg    swapl(&stuff->source);
69235c4bbdfSmrg    swapl(&stuff->destination);
69305b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
69405b261ecSmrg}
69505b261ecSmrg
69605b261ecSmrgstatic Bool
69735c4bbdfSmrgTestForCursorName(CursorPtr pCursor, void *closure)
69805b261ecSmrg{
6994642e01fSmrg    Atom *pName = closure;
70035c4bbdfSmrg
7016747b715Smrg    return pCursor->name == *pName;
70205b261ecSmrg}
70305b261ecSmrg
70405b261ecSmrgint
70535c4bbdfSmrgProcXFixesChangeCursorByName(ClientPtr client)
70605b261ecSmrg{
70735c4bbdfSmrg    CursorPtr pSource;
70835c4bbdfSmrg    Atom name;
70935c4bbdfSmrg    char *tchar;
71035c4bbdfSmrg
71105b261ecSmrg    REQUEST(xXFixesChangeCursorByNameReq);
71205b261ecSmrg
71305b261ecSmrg    REQUEST_FIXED_SIZE(xXFixesChangeCursorByNameReq, stuff->nbytes);
7144642e01fSmrg    VERIFY_CURSOR(pSource, stuff->source, client,
71535c4bbdfSmrg                  DixReadAccess | DixGetAttrAccess);
71605b261ecSmrg    tchar = (char *) &stuff[1];
71735c4bbdfSmrg    name = MakeAtom(tchar, stuff->nbytes, FALSE);
71805b261ecSmrg    if (name)
71935c4bbdfSmrg        ReplaceCursor(pSource, TestForCursorName, &name);
7206747b715Smrg    return Success;
72105b261ecSmrg}
72205b261ecSmrg
72305b261ecSmrgint
72435c4bbdfSmrgSProcXFixesChangeCursorByName(ClientPtr client)
72505b261ecSmrg{
72605b261ecSmrg    REQUEST(xXFixesChangeCursorByNameReq);
72705b261ecSmrg
72835c4bbdfSmrg    swaps(&stuff->length);
72935c4bbdfSmrg    REQUEST_AT_LEAST_SIZE(xXFixesChangeCursorByNameReq);
73035c4bbdfSmrg    swapl(&stuff->source);
73135c4bbdfSmrg    swaps(&stuff->nbytes);
73205b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
73305b261ecSmrg}
73405b261ecSmrg
73505b261ecSmrg/*
73605b261ecSmrg * Routines for manipulating the per-screen hide counts list.
73735c4bbdfSmrg * This list indicates which clients have requested cursor hiding
73805b261ecSmrg * for that screen.
73905b261ecSmrg */
74005b261ecSmrg
74105b261ecSmrg/* Return the screen's hide-counts list element for the given client */
74205b261ecSmrgstatic CursorHideCountPtr
74335c4bbdfSmrgfindCursorHideCount(ClientPtr pClient, ScreenPtr pScreen)
74405b261ecSmrg{
74535c4bbdfSmrg    CursorScreenPtr cs = GetCursorScreen(pScreen);
74605b261ecSmrg    CursorHideCountPtr pChc;
74705b261ecSmrg
74805b261ecSmrg    for (pChc = cs->pCursorHideCounts; pChc != NULL; pChc = pChc->pNext) {
74935c4bbdfSmrg        if (pChc->pClient == pClient) {
75035c4bbdfSmrg            return pChc;
75135c4bbdfSmrg        }
75205b261ecSmrg    }
75305b261ecSmrg
75435c4bbdfSmrg    return NULL;
75505b261ecSmrg}
75605b261ecSmrg
75705b261ecSmrgstatic int
75835c4bbdfSmrgcreateCursorHideCount(ClientPtr pClient, ScreenPtr pScreen)
75905b261ecSmrg{
76035c4bbdfSmrg    CursorScreenPtr cs = GetCursorScreen(pScreen);
76105b261ecSmrg    CursorHideCountPtr pChc;
76205b261ecSmrg
7636747b715Smrg    pChc = (CursorHideCountPtr) malloc(sizeof(CursorHideCountRec));
76405b261ecSmrg    if (pChc == NULL) {
76535c4bbdfSmrg        return BadAlloc;
76605b261ecSmrg    }
76705b261ecSmrg    pChc->pClient = pClient;
76805b261ecSmrg    pChc->pScreen = pScreen;
76905b261ecSmrg    pChc->hideCount = 1;
77005b261ecSmrg    pChc->resource = FakeClientID(pClient->index);
77105b261ecSmrg    pChc->pNext = cs->pCursorHideCounts;
77205b261ecSmrg    cs->pCursorHideCounts = pChc;
77335c4bbdfSmrg
77435c4bbdfSmrg    /*
77505b261ecSmrg     * Create a resource for this element so it can be deleted
77605b261ecSmrg     * when the client goes away.
77705b261ecSmrg     */
77835c4bbdfSmrg    if (!AddResource(pChc->resource, CursorHideCountType, (void *) pChc))
77935c4bbdfSmrg        return BadAlloc;
78005b261ecSmrg
78105b261ecSmrg    return Success;
78205b261ecSmrg}
78305b261ecSmrg
78435c4bbdfSmrg/*
78505b261ecSmrg * Delete the given hide-counts list element from its screen list.
78605b261ecSmrg */
78705b261ecSmrgstatic void
78835c4bbdfSmrgdeleteCursorHideCount(CursorHideCountPtr pChcToDel, ScreenPtr pScreen)
78905b261ecSmrg{
79035c4bbdfSmrg    CursorScreenPtr cs = GetCursorScreen(pScreen);
79105b261ecSmrg    CursorHideCountPtr pChc, pNext;
79205b261ecSmrg    CursorHideCountPtr pChcLast = NULL;
79305b261ecSmrg
79405b261ecSmrg    pChc = cs->pCursorHideCounts;
79505b261ecSmrg    while (pChc != NULL) {
79635c4bbdfSmrg        pNext = pChc->pNext;
79735c4bbdfSmrg        if (pChc == pChcToDel) {
79835c4bbdfSmrg            free(pChc);
79935c4bbdfSmrg            if (pChcLast == NULL) {
80035c4bbdfSmrg                cs->pCursorHideCounts = pNext;
80135c4bbdfSmrg            }
80235c4bbdfSmrg            else {
80335c4bbdfSmrg                pChcLast->pNext = pNext;
80435c4bbdfSmrg            }
80535c4bbdfSmrg            return;
80635c4bbdfSmrg        }
80735c4bbdfSmrg        pChcLast = pChc;
80835c4bbdfSmrg        pChc = pNext;
80905b261ecSmrg    }
81005b261ecSmrg}
81105b261ecSmrg
81235c4bbdfSmrg/*
81305b261ecSmrg * Delete all the hide-counts list elements for this screen.
81405b261ecSmrg */
81505b261ecSmrgstatic void
81635c4bbdfSmrgdeleteCursorHideCountsForScreen(ScreenPtr pScreen)
81705b261ecSmrg{
81835c4bbdfSmrg    CursorScreenPtr cs = GetCursorScreen(pScreen);
81905b261ecSmrg    CursorHideCountPtr pChc, pTmp;
82005b261ecSmrg
82105b261ecSmrg    pChc = cs->pCursorHideCounts;
82205b261ecSmrg    while (pChc != NULL) {
82335c4bbdfSmrg        pTmp = pChc->pNext;
82435c4bbdfSmrg        FreeResource(pChc->resource, 0);
82535c4bbdfSmrg        pChc = pTmp;
82605b261ecSmrg    }
82735c4bbdfSmrg    cs->pCursorHideCounts = NULL;
82805b261ecSmrg}
82905b261ecSmrg
83035c4bbdfSmrgint
83135c4bbdfSmrgProcXFixesHideCursor(ClientPtr client)
83205b261ecSmrg{
83305b261ecSmrg    WindowPtr pWin;
83405b261ecSmrg    CursorHideCountPtr pChc;
83535c4bbdfSmrg
83605b261ecSmrg    REQUEST(xXFixesHideCursorReq);
83705b261ecSmrg    int ret;
83805b261ecSmrg
83935c4bbdfSmrg    REQUEST_SIZE_MATCH(xXFixesHideCursorReq);
84005b261ecSmrg
84135c4bbdfSmrg    ret = dixLookupResourceByType((void **) &pWin, stuff->window, RT_WINDOW,
84235c4bbdfSmrg                                  client, DixGetAttrAccess);
8434642e01fSmrg    if (ret != Success) {
84435c4bbdfSmrg        client->errorValue = stuff->window;
84535c4bbdfSmrg        return ret;
84605b261ecSmrg    }
84705b261ecSmrg
84835c4bbdfSmrg    /*
84935c4bbdfSmrg     * Has client hidden the cursor before on this screen?
85035c4bbdfSmrg     * If so, just increment the count.
85105b261ecSmrg     */
85205b261ecSmrg
85305b261ecSmrg    pChc = findCursorHideCount(client, pWin->drawable.pScreen);
85405b261ecSmrg    if (pChc != NULL) {
85535c4bbdfSmrg        pChc->hideCount++;
85635c4bbdfSmrg        return Success;
85705b261ecSmrg    }
85805b261ecSmrg
85935c4bbdfSmrg    /*
86035c4bbdfSmrg     * This is the first time this client has hid the cursor
86105b261ecSmrg     * for this screen.
86205b261ecSmrg     */
8634642e01fSmrg    ret = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen,
86435c4bbdfSmrg                   DixHideAccess);
8654642e01fSmrg    if (ret != Success)
86635c4bbdfSmrg        return ret;
8674642e01fSmrg
86805b261ecSmrg    ret = createCursorHideCount(client, pWin->drawable.pScreen);
86905b261ecSmrg
87005b261ecSmrg    if (ret == Success) {
87135c4bbdfSmrg        DeviceIntPtr dev;
87235c4bbdfSmrg
87335c4bbdfSmrg        for (dev = inputInfo.devices; dev; dev = dev->next) {
87435c4bbdfSmrg            if (IsMaster(dev) && IsPointerDevice(dev))
87535c4bbdfSmrg                CursorDisplayCursor(dev, pWin->drawable.pScreen,
87635c4bbdfSmrg                                    CursorCurrent[dev->id]);
87735c4bbdfSmrg        }
87805b261ecSmrg    }
87905b261ecSmrg
88005b261ecSmrg    return ret;
88105b261ecSmrg}
88205b261ecSmrg
88335c4bbdfSmrgint
88435c4bbdfSmrgSProcXFixesHideCursor(ClientPtr client)
88505b261ecSmrg{
88605b261ecSmrg    REQUEST(xXFixesHideCursorReq);
88705b261ecSmrg
88835c4bbdfSmrg    swaps(&stuff->length);
88935c4bbdfSmrg    REQUEST_SIZE_MATCH(xXFixesHideCursorReq);
89035c4bbdfSmrg    swapl(&stuff->window);
89105b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
89205b261ecSmrg}
89305b261ecSmrg
89435c4bbdfSmrgint
89535c4bbdfSmrgProcXFixesShowCursor(ClientPtr client)
89605b261ecSmrg{
89705b261ecSmrg    WindowPtr pWin;
89805b261ecSmrg    CursorHideCountPtr pChc;
8994642e01fSmrg    int rc;
90035c4bbdfSmrg
90105b261ecSmrg    REQUEST(xXFixesShowCursorReq);
90205b261ecSmrg
90335c4bbdfSmrg    REQUEST_SIZE_MATCH(xXFixesShowCursorReq);
90405b261ecSmrg
90535c4bbdfSmrg    rc = dixLookupResourceByType((void **) &pWin, stuff->window, RT_WINDOW,
90635c4bbdfSmrg                                 client, DixGetAttrAccess);
9074642e01fSmrg    if (rc != Success) {
90835c4bbdfSmrg        client->errorValue = stuff->window;
90935c4bbdfSmrg        return rc;
91005b261ecSmrg    }
91105b261ecSmrg
91235c4bbdfSmrg    /*
91305b261ecSmrg     * Has client hidden the cursor on this screen?
91405b261ecSmrg     * If not, generate an error.
91505b261ecSmrg     */
91605b261ecSmrg    pChc = findCursorHideCount(client, pWin->drawable.pScreen);
91705b261ecSmrg    if (pChc == NULL) {
91835c4bbdfSmrg        return BadMatch;
91905b261ecSmrg    }
92005b261ecSmrg
9214642e01fSmrg    rc = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen,
92235c4bbdfSmrg                  DixShowAccess);
9234642e01fSmrg    if (rc != Success)
92435c4bbdfSmrg        return rc;
9254642e01fSmrg
92605b261ecSmrg    pChc->hideCount--;
92705b261ecSmrg    if (pChc->hideCount <= 0) {
92835c4bbdfSmrg        FreeResource(pChc->resource, 0);
92905b261ecSmrg    }
93005b261ecSmrg
9316747b715Smrg    return Success;
93205b261ecSmrg}
93305b261ecSmrg
93435c4bbdfSmrgint
93535c4bbdfSmrgSProcXFixesShowCursor(ClientPtr client)
93605b261ecSmrg{
93705b261ecSmrg    REQUEST(xXFixesShowCursorReq);
93805b261ecSmrg
93935c4bbdfSmrg    swaps(&stuff->length);
94035c4bbdfSmrg    REQUEST_SIZE_MATCH(xXFixesShowCursorReq);
94135c4bbdfSmrg    swapl(&stuff->window);
94205b261ecSmrg    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
94305b261ecSmrg}
94405b261ecSmrg
94505b261ecSmrgstatic int
94635c4bbdfSmrgCursorFreeClient(void *data, XID id)
94705b261ecSmrg{
94835c4bbdfSmrg    CursorEventPtr old = (CursorEventPtr) data;
94935c4bbdfSmrg    CursorEventPtr *prev, e;
95035c4bbdfSmrg
95135c4bbdfSmrg    for (prev = &cursorEvents; (e = *prev); prev = &e->next) {
95235c4bbdfSmrg        if (e == old) {
95335c4bbdfSmrg            *prev = e->next;
95435c4bbdfSmrg            free(e);
95535c4bbdfSmrg            break;
95635c4bbdfSmrg        }
95705b261ecSmrg    }
95805b261ecSmrg    return 1;
95905b261ecSmrg}
96005b261ecSmrg
96105b261ecSmrgstatic int
96235c4bbdfSmrgCursorFreeHideCount(void *data, XID id)
96305b261ecSmrg{
96405b261ecSmrg    CursorHideCountPtr pChc = (CursorHideCountPtr) data;
96505b261ecSmrg    ScreenPtr pScreen = pChc->pScreen;
9666747b715Smrg    DeviceIntPtr dev;
96705b261ecSmrg
96805b261ecSmrg    deleteCursorHideCount(pChc, pChc->pScreen);
96935c4bbdfSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
9706747b715Smrg        if (IsMaster(dev) && IsPointerDevice(dev))
9716747b715Smrg            CursorDisplayCursor(dev, pScreen, CursorCurrent[dev->id]);
9726747b715Smrg    }
97305b261ecSmrg
97405b261ecSmrg    return 1;
97505b261ecSmrg}
97605b261ecSmrg
97705b261ecSmrgstatic int
97835c4bbdfSmrgCursorFreeWindow(void *data, XID id)
97905b261ecSmrg{
98035c4bbdfSmrg    WindowPtr pWindow = (WindowPtr) data;
98135c4bbdfSmrg    CursorEventPtr e, next;
98235c4bbdfSmrg
98335c4bbdfSmrg    for (e = cursorEvents; e; e = next) {
98435c4bbdfSmrg        next = e->next;
98535c4bbdfSmrg        if (e->pWindow == pWindow) {
98635c4bbdfSmrg            FreeResource(e->clientResource, 0);
98735c4bbdfSmrg        }
98805b261ecSmrg    }
98905b261ecSmrg    return 1;
99005b261ecSmrg}
99105b261ecSmrg
99235c4bbdfSmrgint
99335c4bbdfSmrgProcXFixesCreatePointerBarrier(ClientPtr client)
99435c4bbdfSmrg{
99535c4bbdfSmrg    REQUEST(xXFixesCreatePointerBarrierReq);
99635c4bbdfSmrg
99735c4bbdfSmrg    REQUEST_FIXED_SIZE(xXFixesCreatePointerBarrierReq, pad_to_int32(stuff->num_devices));
99835c4bbdfSmrg    LEGAL_NEW_RESOURCE(stuff->barrier, client);
99935c4bbdfSmrg
100035c4bbdfSmrg    return XICreatePointerBarrier(client, stuff);
100135c4bbdfSmrg}
100235c4bbdfSmrg
100335c4bbdfSmrgint
100435c4bbdfSmrgSProcXFixesCreatePointerBarrier(ClientPtr client)
100535c4bbdfSmrg{
100635c4bbdfSmrg    REQUEST(xXFixesCreatePointerBarrierReq);
100735c4bbdfSmrg    int i;
100835c4bbdfSmrg    CARD16 *in_devices = (CARD16 *) &stuff[1];
100935c4bbdfSmrg
10106e78d31fSmrg    REQUEST_AT_LEAST_SIZE(xXFixesCreatePointerBarrierReq);
10116e78d31fSmrg
101235c4bbdfSmrg    swaps(&stuff->length);
101335c4bbdfSmrg    swaps(&stuff->num_devices);
101435c4bbdfSmrg    REQUEST_FIXED_SIZE(xXFixesCreatePointerBarrierReq, pad_to_int32(stuff->num_devices));
101535c4bbdfSmrg
101635c4bbdfSmrg    swapl(&stuff->barrier);
101735c4bbdfSmrg    swapl(&stuff->window);
101835c4bbdfSmrg    swaps(&stuff->x1);
101935c4bbdfSmrg    swaps(&stuff->y1);
102035c4bbdfSmrg    swaps(&stuff->x2);
102135c4bbdfSmrg    swaps(&stuff->y2);
102235c4bbdfSmrg    swapl(&stuff->directions);
102335c4bbdfSmrg    for (i = 0; i < stuff->num_devices; i++) {
102435c4bbdfSmrg        swaps(in_devices + i);
102535c4bbdfSmrg    }
102635c4bbdfSmrg
102735c4bbdfSmrg    return ProcXFixesVector[stuff->xfixesReqType] (client);
102835c4bbdfSmrg}
102935c4bbdfSmrg
103035c4bbdfSmrgint
103135c4bbdfSmrgProcXFixesDestroyPointerBarrier(ClientPtr client)
103235c4bbdfSmrg{
103335c4bbdfSmrg    REQUEST(xXFixesDestroyPointerBarrierReq);
103435c4bbdfSmrg
103535c4bbdfSmrg    REQUEST_SIZE_MATCH(xXFixesDestroyPointerBarrierReq);
103635c4bbdfSmrg
103735c4bbdfSmrg    return XIDestroyPointerBarrier(client, stuff);
103835c4bbdfSmrg}
103935c4bbdfSmrg
104035c4bbdfSmrgint
104135c4bbdfSmrgSProcXFixesDestroyPointerBarrier(ClientPtr client)
104235c4bbdfSmrg{
104335c4bbdfSmrg    REQUEST(xXFixesDestroyPointerBarrierReq);
104435c4bbdfSmrg
104535c4bbdfSmrg    swaps(&stuff->length);
104635c4bbdfSmrg    REQUEST_SIZE_MATCH(xXFixesDestroyPointerBarrierReq);
104735c4bbdfSmrg    swapl(&stuff->barrier);
104835c4bbdfSmrg    return ProcXFixesVector[stuff->xfixesReqType] (client);
104935c4bbdfSmrg}
105035c4bbdfSmrg
105105b261ecSmrgBool
105235c4bbdfSmrgXFixesCursorInit(void)
105305b261ecSmrg{
105435c4bbdfSmrg    int i;
10554642e01fSmrg
10564642e01fSmrg    if (party_like_its_1989)
105735c4bbdfSmrg        CursorVisible = EnableCursor;
105835c4bbdfSmrg    else
105935c4bbdfSmrg        CursorVisible = FALSE;
10606747b715Smrg
106135c4bbdfSmrg    if (!dixRegisterPrivateKey(&CursorScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
106235c4bbdfSmrg        return FALSE;
106335c4bbdfSmrg
106435c4bbdfSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
106535c4bbdfSmrg        ScreenPtr pScreen = screenInfo.screens[i];
106635c4bbdfSmrg        CursorScreenPtr cs;
106735c4bbdfSmrg
106835c4bbdfSmrg        cs = (CursorScreenPtr) calloc(1, sizeof(CursorScreenRec));
106935c4bbdfSmrg        if (!cs)
107035c4bbdfSmrg            return FALSE;
107135c4bbdfSmrg        Wrap(cs, pScreen, CloseScreen, CursorCloseScreen);
107235c4bbdfSmrg        Wrap(cs, pScreen, DisplayCursor, CursorDisplayCursor);
107335c4bbdfSmrg        cs->pCursorHideCounts = NULL;
107435c4bbdfSmrg        SetCursorScreen(pScreen, cs);
107505b261ecSmrg    }
10766747b715Smrg    CursorClientType = CreateNewResourceType(CursorFreeClient,
107735c4bbdfSmrg                                             "XFixesCursorClient");
10786747b715Smrg    CursorHideCountType = CreateNewResourceType(CursorFreeHideCount,
107935c4bbdfSmrg                                                "XFixesCursorHideCount");
10806747b715Smrg    CursorWindowType = CreateNewResourceType(CursorFreeWindow,
108135c4bbdfSmrg                                             "XFixesCursorWindow");
10826747b715Smrg
10836747b715Smrg    return CursorClientType && CursorHideCountType && CursorWindowType;
108405b261ecSmrg}
1085