xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

cursor.c (30876B)


      1 /*
      2  * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
      3  * Copyright 2010 Red Hat, Inc.
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining a
      6  * copy of this software and associated documentation files (the "Software"),
      7  * to deal in the Software without restriction, including without limitation
      8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      9  * and/or sell copies of the Software, and to permit persons to whom the
     10  * Software is furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice and this permission notice (including the next
     13  * paragraph) shall be included in all copies or substantial portions of the
     14  * Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     22  * DEALINGS IN THE SOFTWARE.
     23  *
     24  * Copyright © 2002 Keith Packard
     25  *
     26  * Permission to use, copy, modify, distribute, and sell this software and its
     27  * documentation for any purpose is hereby granted without fee, provided that
     28  * the above copyright notice appear in all copies and that both that
     29  * copyright notice and this permission notice appear in supporting
     30  * documentation, and that the name of Keith Packard not be used in
     31  * advertising or publicity pertaining to distribution of the software without
     32  * specific, written prior permission.  Keith Packard makes no
     33  * representations about the suitability of this software for any purpose.  It
     34  * is provided "as is" without express or implied warranty.
     35  *
     36  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     37  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     38  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     39  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     40  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     41  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     42  * PERFORMANCE OF THIS SOFTWARE.
     43  */
     44 
     45 #ifdef HAVE_DIX_CONFIG_H
     46 #include <dix-config.h>
     47 #endif
     48 
     49 #include "xfixesint.h"
     50 #include "scrnintstr.h"
     51 #include "cursorstr.h"
     52 #include "dixevents.h"
     53 #include "servermd.h"
     54 #include "mipointer.h"
     55 #include "inputstr.h"
     56 #include "windowstr.h"
     57 #include "xace.h"
     58 #include "list.h"
     59 #include "xibarriers.h"
     60 
     61 static RESTYPE CursorClientType;
     62 static RESTYPE CursorHideCountType;
     63 static RESTYPE CursorWindowType;
     64 
     65 static DevPrivateKeyRec CursorScreenPrivateKeyRec;
     66 
     67 #define CursorScreenPrivateKey (&CursorScreenPrivateKeyRec)
     68 
     69 static void deleteCursorHideCountsForScreen(ScreenPtr pScreen);
     70 
     71 #define VERIFY_CURSOR(pCursor, cursor, client, access)			\
     72     do {								\
     73 	int err;							\
     74 	err = dixLookupResourceByType((void **) &pCursor, cursor,	\
     75 				      RT_CURSOR, client, access);	\
     76 	if (err != Success) {						\
     77 	    client->errorValue = cursor;				\
     78 	    return err;							\
     79 	}								\
     80     } while (0)
     81 
     82 /*
     83  * There is a global list of windows selecting for cursor events
     84  */
     85 
     86 typedef struct _CursorEvent *CursorEventPtr;
     87 
     88 typedef struct _CursorEvent {
     89     CursorEventPtr next;
     90     CARD32 eventMask;
     91     ClientPtr pClient;
     92     WindowPtr pWindow;
     93     XID clientResource;
     94 } CursorEventRec;
     95 
     96 static CursorEventPtr cursorEvents;
     97 
     98 /*
     99  * Each screen has a list of clients which have requested
    100  * that the cursor be hid, and the number of times each
    101  * client has requested.
    102 */
    103 
    104 typedef struct _CursorHideCountRec *CursorHideCountPtr;
    105 
    106 typedef struct _CursorHideCountRec {
    107     CursorHideCountPtr pNext;
    108     ClientPtr pClient;
    109     ScreenPtr pScreen;
    110     int hideCount;
    111     XID resource;
    112 } CursorHideCountRec;
    113 
    114 /*
    115  * Wrap DisplayCursor to catch cursor change events
    116  */
    117 
    118 typedef struct _CursorScreen {
    119     DisplayCursorProcPtr DisplayCursor;
    120     CloseScreenProcPtr CloseScreen;
    121     CursorHideCountPtr pCursorHideCounts;
    122 } CursorScreenRec, *CursorScreenPtr;
    123 
    124 #define GetCursorScreen(s) ((CursorScreenPtr)dixLookupPrivate(&(s)->devPrivates, CursorScreenPrivateKey))
    125 #define GetCursorScreenIfSet(s) GetCursorScreen(s)
    126 #define SetCursorScreen(s,p) dixSetPrivate(&(s)->devPrivates, CursorScreenPrivateKey, p)
    127 #define Wrap(as,s,elt,func)	(((as)->elt = (s)->elt), (s)->elt = func)
    128 #define Unwrap(as,s,elt,backup)	(((backup) = (s)->elt), (s)->elt = (as)->elt)
    129 
    130 /* The cursor doesn't show up until the first XDefineCursor() */
    131 Bool CursorVisible = FALSE;
    132 Bool EnableCursor = TRUE;
    133 
    134 static CursorPtr
    135 CursorForDevice(DeviceIntPtr pDev)
    136 {
    137     if (pDev && pDev->spriteInfo && pDev->spriteInfo->sprite) {
    138         if (pDev->spriteInfo->anim.pCursor)
    139             return pDev->spriteInfo->anim.pCursor;
    140         return pDev->spriteInfo->sprite->current;
    141     }
    142 
    143     return NULL;
    144 }
    145 
    146 static CursorPtr
    147 CursorForClient(ClientPtr client)
    148 {
    149     return CursorForDevice(PickPointer(client));
    150 }
    151 
    152 static Bool
    153 CursorDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
    154 {
    155     CursorScreenPtr cs = GetCursorScreen(pScreen);
    156     CursorPtr pOldCursor = CursorForDevice(pDev);
    157     Bool ret;
    158     DisplayCursorProcPtr backupProc;
    159 
    160     Unwrap(cs, pScreen, DisplayCursor, backupProc);
    161 
    162     CursorVisible = CursorVisible && EnableCursor;
    163 
    164     if (cs->pCursorHideCounts != NULL || !CursorVisible) {
    165         ret = (*pScreen->DisplayCursor) (pDev, pScreen, NullCursor);
    166     }
    167     else {
    168         ret = (*pScreen->DisplayCursor) (pDev, pScreen, pCursor);
    169     }
    170 
    171     if (pCursor != pOldCursor) {
    172         CursorEventPtr e;
    173 
    174         UpdateCurrentTimeIf();
    175         for (e = cursorEvents; e; e = e->next) {
    176             if ((e->eventMask & XFixesDisplayCursorNotifyMask)) {
    177                 xXFixesCursorNotifyEvent ev = {
    178                     .type = XFixesEventBase + XFixesCursorNotify,
    179                     .subtype = XFixesDisplayCursorNotify,
    180                     .window = e->pWindow->drawable.id,
    181                     .cursorSerial = pCursor ? pCursor->serialNumber : 0,
    182                     .timestamp = currentTime.milliseconds,
    183                     .name = pCursor ? pCursor->name : None
    184                 };
    185                 WriteEventsToClient(e->pClient, 1, (xEvent *) &ev);
    186             }
    187         }
    188     }
    189     Wrap(cs, pScreen, DisplayCursor, backupProc);
    190 
    191     return ret;
    192 }
    193 
    194 static Bool
    195 CursorCloseScreen(ScreenPtr pScreen)
    196 {
    197     CursorScreenPtr cs = GetCursorScreen(pScreen);
    198     Bool ret;
    199     _X_UNUSED CloseScreenProcPtr close_proc;
    200     _X_UNUSED DisplayCursorProcPtr display_proc;
    201 
    202     Unwrap(cs, pScreen, CloseScreen, close_proc);
    203     Unwrap(cs, pScreen, DisplayCursor, display_proc);
    204     deleteCursorHideCountsForScreen(pScreen);
    205     ret = (*pScreen->CloseScreen) (pScreen);
    206     free(cs);
    207     return ret;
    208 }
    209 
    210 #define CursorAllEvents (XFixesDisplayCursorNotifyMask)
    211 
    212 static int
    213 XFixesSelectCursorInput(ClientPtr pClient, WindowPtr pWindow, CARD32 eventMask)
    214 {
    215     CursorEventPtr *prev, e;
    216     void *val;
    217     int rc;
    218 
    219     for (prev = &cursorEvents; (e = *prev); prev = &e->next) {
    220         if (e->pClient == pClient && e->pWindow == pWindow) {
    221             break;
    222         }
    223     }
    224     if (!eventMask) {
    225         if (e) {
    226             FreeResource(e->clientResource, 0);
    227         }
    228         return Success;
    229     }
    230     if (!e) {
    231         e = (CursorEventPtr) malloc(sizeof(CursorEventRec));
    232         if (!e)
    233             return BadAlloc;
    234 
    235         e->next = 0;
    236         e->pClient = pClient;
    237         e->pWindow = pWindow;
    238         e->clientResource = FakeClientID(pClient->index);
    239 
    240         /*
    241          * Add a resource hanging from the window to
    242          * catch window destroy
    243          */
    244         rc = dixLookupResourceByType(&val, pWindow->drawable.id,
    245                                      CursorWindowType, serverClient,
    246                                      DixGetAttrAccess);
    247         if (rc != Success)
    248             if (!AddResource(pWindow->drawable.id, CursorWindowType,
    249                              (void *) pWindow)) {
    250                 free(e);
    251                 return BadAlloc;
    252             }
    253 
    254         if (!AddResource(e->clientResource, CursorClientType, (void *) e))
    255             return BadAlloc;
    256 
    257         *prev = e;
    258     }
    259     e->eventMask = eventMask;
    260     return Success;
    261 }
    262 
    263 int
    264 ProcXFixesSelectCursorInput(ClientPtr client)
    265 {
    266     REQUEST(xXFixesSelectCursorInputReq);
    267     WindowPtr pWin;
    268     int rc;
    269 
    270     REQUEST_SIZE_MATCH(xXFixesSelectCursorInputReq);
    271     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
    272     if (rc != Success)
    273         return rc;
    274     if (stuff->eventMask & ~CursorAllEvents) {
    275         client->errorValue = stuff->eventMask;
    276         return BadValue;
    277     }
    278     return XFixesSelectCursorInput(client, pWin, stuff->eventMask);
    279 }
    280 
    281 static int
    282 GetBit(unsigned char *line, int x)
    283 {
    284     unsigned char mask;
    285 
    286     if (screenInfo.bitmapBitOrder == LSBFirst)
    287         mask = (1 << (x & 7));
    288     else
    289         mask = (0x80 >> (x & 7));
    290     /* XXX assumes byte order is host byte order */
    291     line += (x >> 3);
    292     if (*line & mask)
    293         return 1;
    294     return 0;
    295 }
    296 
    297 int _X_COLD
    298 SProcXFixesSelectCursorInput(ClientPtr client)
    299 {
    300     REQUEST(xXFixesSelectCursorInputReq);
    301     REQUEST_SIZE_MATCH(xXFixesSelectCursorInputReq);
    302 
    303     swaps(&stuff->length);
    304     swapl(&stuff->window);
    305     swapl(&stuff->eventMask);
    306     return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
    307 }
    308 
    309 void _X_COLD
    310 SXFixesCursorNotifyEvent(xXFixesCursorNotifyEvent * from,
    311                          xXFixesCursorNotifyEvent * to)
    312 {
    313     to->type = from->type;
    314     cpswaps(from->sequenceNumber, to->sequenceNumber);
    315     cpswapl(from->window, to->window);
    316     cpswapl(from->cursorSerial, to->cursorSerial);
    317     cpswapl(from->timestamp, to->timestamp);
    318     cpswapl(from->name, to->name);
    319 }
    320 
    321 static void
    322 CopyCursorToImage(CursorPtr pCursor, CARD32 *image)
    323 {
    324     int width = pCursor->bits->width;
    325     int height = pCursor->bits->height;
    326     int npixels = width * height;
    327 
    328     if (pCursor->bits->argb)
    329         memcpy(image, pCursor->bits->argb, npixels * sizeof(CARD32));
    330     else
    331     {
    332         unsigned char *srcLine = pCursor->bits->source;
    333         unsigned char *mskLine = pCursor->bits->mask;
    334         int stride = BitmapBytePad(width);
    335         int x, y;
    336         CARD32 fg, bg;
    337 
    338         fg = (0xff000000 |
    339               ((pCursor->foreRed & 0xff00) << 8) |
    340               (pCursor->foreGreen & 0xff00) | (pCursor->foreBlue >> 8));
    341         bg = (0xff000000 |
    342               ((pCursor->backRed & 0xff00) << 8) |
    343               (pCursor->backGreen & 0xff00) | (pCursor->backBlue >> 8));
    344         for (y = 0; y < height; y++) {
    345             for (x = 0; x < width; x++) {
    346                 if (GetBit(mskLine, x)) {
    347                     if (GetBit(srcLine, x))
    348                         *image++ = fg;
    349                     else
    350                         *image++ = bg;
    351                 }
    352                 else
    353                     *image++ = 0;
    354             }
    355             srcLine += stride;
    356             mskLine += stride;
    357         }
    358     }
    359 }
    360 
    361 int
    362 ProcXFixesGetCursorImage(ClientPtr client)
    363 {
    364 /*    REQUEST(xXFixesGetCursorImageReq); */
    365     xXFixesGetCursorImageReply *rep;
    366     CursorPtr pCursor;
    367     CARD32 *image;
    368     int npixels, width, height, rc, x, y;
    369 
    370     REQUEST_SIZE_MATCH(xXFixesGetCursorImageReq);
    371     pCursor = CursorForClient(client);
    372     if (!pCursor)
    373         return BadCursor;
    374     rc = XaceHook(XACE_RESOURCE_ACCESS, client, pCursor->id, RT_CURSOR,
    375                   pCursor, RT_NONE, NULL, DixReadAccess);
    376     if (rc != Success)
    377         return rc;
    378     GetSpritePosition(PickPointer(client), &x, &y);
    379     width = pCursor->bits->width;
    380     height = pCursor->bits->height;
    381     npixels = width * height;
    382     rep = calloc(sizeof(xXFixesGetCursorImageReply) + npixels * sizeof(CARD32),
    383                  1);
    384     if (!rep)
    385         return BadAlloc;
    386 
    387     rep->type = X_Reply;
    388     rep->sequenceNumber = client->sequence;
    389     rep->length = npixels;
    390     rep->width = width;
    391     rep->height = height;
    392     rep->x = x;
    393     rep->y = y;
    394     rep->xhot = pCursor->bits->xhot;
    395     rep->yhot = pCursor->bits->yhot;
    396     rep->cursorSerial = pCursor->serialNumber;
    397 
    398     image = (CARD32 *) (rep + 1);
    399     CopyCursorToImage(pCursor, image);
    400     if (client->swapped) {
    401         swaps(&rep->sequenceNumber);
    402         swapl(&rep->length);
    403         swaps(&rep->x);
    404         swaps(&rep->y);
    405         swaps(&rep->width);
    406         swaps(&rep->height);
    407         swaps(&rep->xhot);
    408         swaps(&rep->yhot);
    409         swapl(&rep->cursorSerial);
    410         SwapLongs(image, npixels);
    411     }
    412     WriteToClient(client,
    413                   sizeof(xXFixesGetCursorImageReply) + (npixels << 2), rep);
    414     free(rep);
    415     return Success;
    416 }
    417 
    418 int _X_COLD
    419 SProcXFixesGetCursorImage(ClientPtr client)
    420 {
    421     REQUEST(xXFixesGetCursorImageReq);
    422     swaps(&stuff->length);
    423     return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
    424 }
    425 
    426 int
    427 ProcXFixesSetCursorName(ClientPtr client)
    428 {
    429     CursorPtr pCursor;
    430     char *tchar;
    431 
    432     REQUEST(xXFixesSetCursorNameReq);
    433     Atom atom;
    434 
    435     REQUEST_FIXED_SIZE(xXFixesSetCursorNameReq, stuff->nbytes);
    436     VERIFY_CURSOR(pCursor, stuff->cursor, client, DixSetAttrAccess);
    437     tchar = (char *) &stuff[1];
    438     atom = MakeAtom(tchar, stuff->nbytes, TRUE);
    439     if (atom == BAD_RESOURCE)
    440         return BadAlloc;
    441 
    442     pCursor->name = atom;
    443     return Success;
    444 }
    445 
    446 int _X_COLD
    447 SProcXFixesSetCursorName(ClientPtr client)
    448 {
    449     REQUEST(xXFixesSetCursorNameReq);
    450 
    451     swaps(&stuff->length);
    452     REQUEST_AT_LEAST_SIZE(xXFixesSetCursorNameReq);
    453     swapl(&stuff->cursor);
    454     swaps(&stuff->nbytes);
    455     return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
    456 }
    457 
    458 int
    459 ProcXFixesGetCursorName(ClientPtr client)
    460 {
    461     CursorPtr pCursor;
    462     xXFixesGetCursorNameReply reply;
    463 
    464     REQUEST(xXFixesGetCursorNameReq);
    465     const char *str;
    466     int len;
    467 
    468     REQUEST_SIZE_MATCH(xXFixesGetCursorNameReq);
    469     VERIFY_CURSOR(pCursor, stuff->cursor, client, DixGetAttrAccess);
    470     if (pCursor->name)
    471         str = NameForAtom(pCursor->name);
    472     else
    473         str = "";
    474     len = strlen(str);
    475 
    476     reply = (xXFixesGetCursorNameReply) {
    477         .type = X_Reply,
    478         .sequenceNumber = client->sequence,
    479         .length = bytes_to_int32(len),
    480         .atom = pCursor->name,
    481         .nbytes = len
    482     };
    483     if (client->swapped) {
    484         swaps(&reply.sequenceNumber);
    485         swapl(&reply.length);
    486         swapl(&reply.atom);
    487         swaps(&reply.nbytes);
    488     }
    489     WriteReplyToClient(client, sizeof(xXFixesGetCursorNameReply), &reply);
    490     WriteToClient(client, len, str);
    491 
    492     return Success;
    493 }
    494 
    495 int _X_COLD
    496 SProcXFixesGetCursorName(ClientPtr client)
    497 {
    498     REQUEST(xXFixesGetCursorNameReq);
    499 
    500     swaps(&stuff->length);
    501     REQUEST_SIZE_MATCH(xXFixesGetCursorNameReq);
    502     swapl(&stuff->cursor);
    503     return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
    504 }
    505 
    506 int
    507 ProcXFixesGetCursorImageAndName(ClientPtr client)
    508 {
    509 /*    REQUEST(xXFixesGetCursorImageAndNameReq); */
    510     xXFixesGetCursorImageAndNameReply *rep;
    511     CursorPtr pCursor;
    512     CARD32 *image;
    513     int npixels;
    514     const char *name;
    515     int nbytes, nbytesRound;
    516     int width, height;
    517     int rc, x, y;
    518 
    519     REQUEST_SIZE_MATCH(xXFixesGetCursorImageAndNameReq);
    520     pCursor = CursorForClient(client);
    521     if (!pCursor)
    522         return BadCursor;
    523     rc = XaceHook(XACE_RESOURCE_ACCESS, client, pCursor->id, RT_CURSOR,
    524                   pCursor, RT_NONE, NULL, DixReadAccess | DixGetAttrAccess);
    525     if (rc != Success)
    526         return rc;
    527     GetSpritePosition(PickPointer(client), &x, &y);
    528     width = pCursor->bits->width;
    529     height = pCursor->bits->height;
    530     npixels = width * height;
    531     name = pCursor->name ? NameForAtom(pCursor->name) : "";
    532     nbytes = strlen(name);
    533     nbytesRound = pad_to_int32(nbytes);
    534     rep = calloc(sizeof(xXFixesGetCursorImageAndNameReply) +
    535                  npixels * sizeof(CARD32) + nbytesRound, 1);
    536     if (!rep)
    537         return BadAlloc;
    538 
    539     rep->type = X_Reply;
    540     rep->sequenceNumber = client->sequence;
    541     rep->length = npixels + bytes_to_int32(nbytesRound);
    542     rep->width = width;
    543     rep->height = height;
    544     rep->x = x;
    545     rep->y = y;
    546     rep->xhot = pCursor->bits->xhot;
    547     rep->yhot = pCursor->bits->yhot;
    548     rep->cursorSerial = pCursor->serialNumber;
    549     rep->cursorName = pCursor->name;
    550     rep->nbytes = nbytes;
    551 
    552     image = (CARD32 *) (rep + 1);
    553     CopyCursorToImage(pCursor, image);
    554     memcpy((image + npixels), name, nbytes);
    555     if (client->swapped) {
    556         swaps(&rep->sequenceNumber);
    557         swapl(&rep->length);
    558         swaps(&rep->x);
    559         swaps(&rep->y);
    560         swaps(&rep->width);
    561         swaps(&rep->height);
    562         swaps(&rep->xhot);
    563         swaps(&rep->yhot);
    564         swapl(&rep->cursorSerial);
    565         swapl(&rep->cursorName);
    566         swaps(&rep->nbytes);
    567         SwapLongs(image, npixels);
    568     }
    569     WriteToClient(client, sizeof(xXFixesGetCursorImageAndNameReply) +
    570                   (npixels << 2) + nbytesRound, rep);
    571     free(rep);
    572     return Success;
    573 }
    574 
    575 int _X_COLD
    576 SProcXFixesGetCursorImageAndName(ClientPtr client)
    577 {
    578     REQUEST(xXFixesGetCursorImageAndNameReq);
    579     swaps(&stuff->length);
    580     return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
    581 }
    582 
    583 /*
    584  * Find every cursor reference in the system, ask testCursor
    585  * whether it should be replaced with a reference to pCursor.
    586  */
    587 
    588 typedef Bool (*TestCursorFunc) (CursorPtr pOld, void *closure);
    589 
    590 typedef struct {
    591     RESTYPE type;
    592     TestCursorFunc testCursor;
    593     CursorPtr pNew;
    594     void *closure;
    595 } ReplaceCursorLookupRec, *ReplaceCursorLookupPtr;
    596 
    597 static const RESTYPE CursorRestypes[] = {
    598     RT_WINDOW, RT_PASSIVEGRAB, RT_CURSOR
    599 };
    600 
    601 static Bool
    602 ReplaceCursorLookup(void *value, XID id, void *closure)
    603 {
    604     ReplaceCursorLookupPtr rcl = (ReplaceCursorLookupPtr) closure;
    605     WindowPtr pWin;
    606     GrabPtr pGrab;
    607     CursorPtr pCursor = 0, *pCursorRef = 0;
    608     XID cursor = 0;
    609 
    610     switch (rcl->type) {
    611     case RT_WINDOW:
    612         pWin = (WindowPtr) value;
    613         if (pWin->optional) {
    614             pCursorRef = &pWin->optional->cursor;
    615             pCursor = *pCursorRef;
    616         }
    617         break;
    618     case RT_PASSIVEGRAB:
    619         pGrab = (GrabPtr) value;
    620         pCursorRef = &pGrab->cursor;
    621         pCursor = *pCursorRef;
    622         break;
    623     case RT_CURSOR:
    624         pCursorRef = 0;
    625         pCursor = (CursorPtr) value;
    626         cursor = id;
    627         break;
    628     }
    629     if (pCursor && pCursor != rcl->pNew) {
    630         if ((*rcl->testCursor) (pCursor, rcl->closure)) {
    631             CursorPtr curs = RefCursor(rcl->pNew);
    632             /* either redirect reference or update resource database */
    633             if (pCursorRef)
    634                 *pCursorRef = curs;
    635             else
    636                 ChangeResourceValue(id, RT_CURSOR, curs);
    637             FreeCursor(pCursor, cursor);
    638         }
    639     }
    640     return FALSE;               /* keep walking */
    641 }
    642 
    643 static void
    644 ReplaceCursor(CursorPtr pCursor, TestCursorFunc testCursor, void *closure)
    645 {
    646     int clientIndex;
    647     int resIndex;
    648     ReplaceCursorLookupRec rcl;
    649 
    650     /*
    651      * Cursors exist only in the resource database, windows and grabs.
    652      * All of these are always pointed at by the resource database.  Walk
    653      * the whole thing looking for cursors
    654      */
    655     rcl.testCursor = testCursor;
    656     rcl.pNew = pCursor;
    657     rcl.closure = closure;
    658 
    659     /* for each client */
    660     for (clientIndex = 0; clientIndex < currentMaxClients; clientIndex++) {
    661         if (!clients[clientIndex])
    662             continue;
    663         for (resIndex = 0; resIndex < ARRAY_SIZE(CursorRestypes); resIndex++) {
    664             rcl.type = CursorRestypes[resIndex];
    665             /*
    666              * This function walks the entire client resource database
    667              */
    668             LookupClientResourceComplex(clients[clientIndex],
    669                                         rcl.type,
    670                                         ReplaceCursorLookup, (void *) &rcl);
    671         }
    672     }
    673     /* this "knows" that WindowHasNewCursor doesn't depend on its argument */
    674     WindowHasNewCursor(screenInfo.screens[0]->root);
    675 }
    676 
    677 static Bool
    678 TestForCursor(CursorPtr pCursor, void *closure)
    679 {
    680     return (pCursor == (CursorPtr) closure);
    681 }
    682 
    683 int
    684 ProcXFixesChangeCursor(ClientPtr client)
    685 {
    686     CursorPtr pSource, pDestination;
    687 
    688     REQUEST(xXFixesChangeCursorReq);
    689 
    690     REQUEST_SIZE_MATCH(xXFixesChangeCursorReq);
    691     VERIFY_CURSOR(pSource, stuff->source, client,
    692                   DixReadAccess | DixGetAttrAccess);
    693     VERIFY_CURSOR(pDestination, stuff->destination, client,
    694                   DixWriteAccess | DixSetAttrAccess);
    695 
    696     ReplaceCursor(pSource, TestForCursor, (void *) pDestination);
    697     return Success;
    698 }
    699 
    700 int _X_COLD
    701 SProcXFixesChangeCursor(ClientPtr client)
    702 {
    703     REQUEST(xXFixesChangeCursorReq);
    704 
    705     swaps(&stuff->length);
    706     REQUEST_SIZE_MATCH(xXFixesChangeCursorReq);
    707     swapl(&stuff->source);
    708     swapl(&stuff->destination);
    709     return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
    710 }
    711 
    712 static Bool
    713 TestForCursorName(CursorPtr pCursor, void *closure)
    714 {
    715     Atom *pName = closure;
    716 
    717     return pCursor->name == *pName;
    718 }
    719 
    720 int
    721 ProcXFixesChangeCursorByName(ClientPtr client)
    722 {
    723     CursorPtr pSource;
    724     Atom name;
    725     char *tchar;
    726 
    727     REQUEST(xXFixesChangeCursorByNameReq);
    728 
    729     REQUEST_FIXED_SIZE(xXFixesChangeCursorByNameReq, stuff->nbytes);
    730     VERIFY_CURSOR(pSource, stuff->source, client,
    731                   DixReadAccess | DixGetAttrAccess);
    732     tchar = (char *) &stuff[1];
    733     name = MakeAtom(tchar, stuff->nbytes, FALSE);
    734     if (name)
    735         ReplaceCursor(pSource, TestForCursorName, &name);
    736     return Success;
    737 }
    738 
    739 int _X_COLD
    740 SProcXFixesChangeCursorByName(ClientPtr client)
    741 {
    742     REQUEST(xXFixesChangeCursorByNameReq);
    743 
    744     swaps(&stuff->length);
    745     REQUEST_AT_LEAST_SIZE(xXFixesChangeCursorByNameReq);
    746     swapl(&stuff->source);
    747     swaps(&stuff->nbytes);
    748     return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
    749 }
    750 
    751 /*
    752  * Routines for manipulating the per-screen hide counts list.
    753  * This list indicates which clients have requested cursor hiding
    754  * for that screen.
    755  */
    756 
    757 /* Return the screen's hide-counts list element for the given client */
    758 static CursorHideCountPtr
    759 findCursorHideCount(ClientPtr pClient, ScreenPtr pScreen)
    760 {
    761     CursorScreenPtr cs = GetCursorScreen(pScreen);
    762     CursorHideCountPtr pChc;
    763 
    764     for (pChc = cs->pCursorHideCounts; pChc != NULL; pChc = pChc->pNext) {
    765         if (pChc->pClient == pClient) {
    766             return pChc;
    767         }
    768     }
    769 
    770     return NULL;
    771 }
    772 
    773 static int
    774 createCursorHideCount(ClientPtr pClient, ScreenPtr pScreen)
    775 {
    776     CursorScreenPtr cs = GetCursorScreen(pScreen);
    777     CursorHideCountPtr pChc;
    778 
    779     pChc = (CursorHideCountPtr) malloc(sizeof(CursorHideCountRec));
    780     if (pChc == NULL) {
    781         return BadAlloc;
    782     }
    783     pChc->pClient = pClient;
    784     pChc->pScreen = pScreen;
    785     pChc->hideCount = 1;
    786     pChc->resource = FakeClientID(pClient->index);
    787     pChc->pNext = cs->pCursorHideCounts;
    788     cs->pCursorHideCounts = pChc;
    789 
    790     /*
    791      * Create a resource for this element so it can be deleted
    792      * when the client goes away.
    793      */
    794     if (!AddResource(pChc->resource, CursorHideCountType, (void *) pChc))
    795         return BadAlloc;
    796 
    797     return Success;
    798 }
    799 
    800 /*
    801  * Delete the given hide-counts list element from its screen list.
    802  */
    803 static void
    804 deleteCursorHideCount(CursorHideCountPtr pChcToDel, ScreenPtr pScreen)
    805 {
    806     CursorScreenPtr cs = GetCursorScreen(pScreen);
    807     CursorHideCountPtr pChc, pNext;
    808     CursorHideCountPtr pChcLast = NULL;
    809 
    810     pChc = cs->pCursorHideCounts;
    811     while (pChc != NULL) {
    812         pNext = pChc->pNext;
    813         if (pChc == pChcToDel) {
    814             free(pChc);
    815             if (pChcLast == NULL) {
    816                 cs->pCursorHideCounts = pNext;
    817             }
    818             else {
    819                 pChcLast->pNext = pNext;
    820             }
    821             return;
    822         }
    823         pChcLast = pChc;
    824         pChc = pNext;
    825     }
    826 }
    827 
    828 /*
    829  * Delete all the hide-counts list elements for this screen.
    830  */
    831 static void
    832 deleteCursorHideCountsForScreen(ScreenPtr pScreen)
    833 {
    834     CursorScreenPtr cs = GetCursorScreen(pScreen);
    835     CursorHideCountPtr pChc, pTmp;
    836 
    837     pChc = cs->pCursorHideCounts;
    838     while (pChc != NULL) {
    839         pTmp = pChc->pNext;
    840         FreeResource(pChc->resource, 0);
    841         pChc = pTmp;
    842     }
    843     cs->pCursorHideCounts = NULL;
    844 }
    845 
    846 int
    847 ProcXFixesHideCursor(ClientPtr client)
    848 {
    849     WindowPtr pWin;
    850     CursorHideCountPtr pChc;
    851 
    852     REQUEST(xXFixesHideCursorReq);
    853     int ret;
    854 
    855     REQUEST_SIZE_MATCH(xXFixesHideCursorReq);
    856 
    857     ret = dixLookupResourceByType((void **) &pWin, stuff->window, RT_WINDOW,
    858                                   client, DixGetAttrAccess);
    859     if (ret != Success) {
    860         client->errorValue = stuff->window;
    861         return ret;
    862     }
    863 
    864     /*
    865      * Has client hidden the cursor before on this screen?
    866      * If so, just increment the count.
    867      */
    868 
    869     pChc = findCursorHideCount(client, pWin->drawable.pScreen);
    870     if (pChc != NULL) {
    871         pChc->hideCount++;
    872         return Success;
    873     }
    874 
    875     /*
    876      * This is the first time this client has hid the cursor
    877      * for this screen.
    878      */
    879     ret = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen,
    880                    DixHideAccess);
    881     if (ret != Success)
    882         return ret;
    883 
    884     ret = createCursorHideCount(client, pWin->drawable.pScreen);
    885 
    886     if (ret == Success) {
    887         DeviceIntPtr dev;
    888 
    889         for (dev = inputInfo.devices; dev; dev = dev->next) {
    890             if (IsMaster(dev) && IsPointerDevice(dev))
    891                 CursorDisplayCursor(dev, pWin->drawable.pScreen,
    892                                     CursorForDevice(dev));
    893         }
    894     }
    895 
    896     return ret;
    897 }
    898 
    899 int _X_COLD
    900 SProcXFixesHideCursor(ClientPtr client)
    901 {
    902     REQUEST(xXFixesHideCursorReq);
    903 
    904     swaps(&stuff->length);
    905     REQUEST_SIZE_MATCH(xXFixesHideCursorReq);
    906     swapl(&stuff->window);
    907     return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
    908 }
    909 
    910 int
    911 ProcXFixesShowCursor(ClientPtr client)
    912 {
    913     WindowPtr pWin;
    914     CursorHideCountPtr pChc;
    915     int rc;
    916 
    917     REQUEST(xXFixesShowCursorReq);
    918 
    919     REQUEST_SIZE_MATCH(xXFixesShowCursorReq);
    920 
    921     rc = dixLookupResourceByType((void **) &pWin, stuff->window, RT_WINDOW,
    922                                  client, DixGetAttrAccess);
    923     if (rc != Success) {
    924         client->errorValue = stuff->window;
    925         return rc;
    926     }
    927 
    928     /*
    929      * Has client hidden the cursor on this screen?
    930      * If not, generate an error.
    931      */
    932     pChc = findCursorHideCount(client, pWin->drawable.pScreen);
    933     if (pChc == NULL) {
    934         return BadMatch;
    935     }
    936 
    937     rc = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen,
    938                   DixShowAccess);
    939     if (rc != Success)
    940         return rc;
    941 
    942     pChc->hideCount--;
    943     if (pChc->hideCount <= 0) {
    944         FreeResource(pChc->resource, 0);
    945     }
    946 
    947     return Success;
    948 }
    949 
    950 int _X_COLD
    951 SProcXFixesShowCursor(ClientPtr client)
    952 {
    953     REQUEST(xXFixesShowCursorReq);
    954 
    955     swaps(&stuff->length);
    956     REQUEST_SIZE_MATCH(xXFixesShowCursorReq);
    957     swapl(&stuff->window);
    958     return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
    959 }
    960 
    961 static int
    962 CursorFreeClient(void *data, XID id)
    963 {
    964     CursorEventPtr old = (CursorEventPtr) data;
    965     CursorEventPtr *prev, e;
    966 
    967     for (prev = &cursorEvents; (e = *prev); prev = &e->next) {
    968         if (e == old) {
    969             *prev = e->next;
    970             free(e);
    971             break;
    972         }
    973     }
    974     return 1;
    975 }
    976 
    977 static int
    978 CursorFreeHideCount(void *data, XID id)
    979 {
    980     CursorHideCountPtr pChc = (CursorHideCountPtr) data;
    981     ScreenPtr pScreen = pChc->pScreen;
    982     DeviceIntPtr dev;
    983 
    984     deleteCursorHideCount(pChc, pChc->pScreen);
    985     for (dev = inputInfo.devices; dev; dev = dev->next) {
    986         if (IsMaster(dev) && IsPointerDevice(dev))
    987             CursorDisplayCursor(dev, pScreen, CursorForDevice(dev));
    988     }
    989 
    990     return 1;
    991 }
    992 
    993 static int
    994 CursorFreeWindow(void *data, XID id)
    995 {
    996     WindowPtr pWindow = (WindowPtr) data;
    997     CursorEventPtr e, next;
    998 
    999     for (e = cursorEvents; e; e = next) {
   1000         next = e->next;
   1001         if (e->pWindow == pWindow) {
   1002             FreeResource(e->clientResource, 0);
   1003         }
   1004     }
   1005     return 1;
   1006 }
   1007 
   1008 int
   1009 ProcXFixesCreatePointerBarrier(ClientPtr client)
   1010 {
   1011     REQUEST(xXFixesCreatePointerBarrierReq);
   1012 
   1013     REQUEST_FIXED_SIZE(xXFixesCreatePointerBarrierReq,
   1014                        pad_to_int32(stuff->num_devices * sizeof(CARD16)));
   1015     LEGAL_NEW_RESOURCE(stuff->barrier, client);
   1016 
   1017     return XICreatePointerBarrier(client, stuff);
   1018 }
   1019 
   1020 int _X_COLD
   1021 SProcXFixesCreatePointerBarrier(ClientPtr client)
   1022 {
   1023     REQUEST(xXFixesCreatePointerBarrierReq);
   1024     int i;
   1025     CARD16 *in_devices = (CARD16 *) &stuff[1];
   1026 
   1027     REQUEST_AT_LEAST_SIZE(xXFixesCreatePointerBarrierReq);
   1028 
   1029     swaps(&stuff->length);
   1030     swaps(&stuff->num_devices);
   1031     REQUEST_FIXED_SIZE(xXFixesCreatePointerBarrierReq,
   1032                        pad_to_int32(stuff->num_devices * sizeof(CARD16)));
   1033 
   1034     swapl(&stuff->barrier);
   1035     swapl(&stuff->window);
   1036     swaps(&stuff->x1);
   1037     swaps(&stuff->y1);
   1038     swaps(&stuff->x2);
   1039     swaps(&stuff->y2);
   1040     swapl(&stuff->directions);
   1041     for (i = 0; i < stuff->num_devices; i++) {
   1042         swaps(in_devices + i);
   1043     }
   1044 
   1045     return ProcXFixesVector[stuff->xfixesReqType] (client);
   1046 }
   1047 
   1048 int
   1049 ProcXFixesDestroyPointerBarrier(ClientPtr client)
   1050 {
   1051     REQUEST(xXFixesDestroyPointerBarrierReq);
   1052 
   1053     REQUEST_SIZE_MATCH(xXFixesDestroyPointerBarrierReq);
   1054 
   1055     return XIDestroyPointerBarrier(client, stuff);
   1056 }
   1057 
   1058 int _X_COLD
   1059 SProcXFixesDestroyPointerBarrier(ClientPtr client)
   1060 {
   1061     REQUEST(xXFixesDestroyPointerBarrierReq);
   1062 
   1063     swaps(&stuff->length);
   1064     REQUEST_SIZE_MATCH(xXFixesDestroyPointerBarrierReq);
   1065     swapl(&stuff->barrier);
   1066     return ProcXFixesVector[stuff->xfixesReqType] (client);
   1067 }
   1068 
   1069 Bool
   1070 XFixesCursorInit(void)
   1071 {
   1072     int i;
   1073 
   1074     if (party_like_its_1989)
   1075         CursorVisible = EnableCursor;
   1076     else
   1077         CursorVisible = FALSE;
   1078 
   1079     if (!dixRegisterPrivateKey(&CursorScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
   1080         return FALSE;
   1081 
   1082     for (i = 0; i < screenInfo.numScreens; i++) {
   1083         ScreenPtr pScreen = screenInfo.screens[i];
   1084         CursorScreenPtr cs;
   1085 
   1086         cs = (CursorScreenPtr) calloc(1, sizeof(CursorScreenRec));
   1087         if (!cs)
   1088             return FALSE;
   1089         Wrap(cs, pScreen, CloseScreen, CursorCloseScreen);
   1090         Wrap(cs, pScreen, DisplayCursor, CursorDisplayCursor);
   1091         cs->pCursorHideCounts = NULL;
   1092         SetCursorScreen(pScreen, cs);
   1093     }
   1094     CursorClientType = CreateNewResourceType(CursorFreeClient,
   1095                                              "XFixesCursorClient");
   1096     CursorHideCountType = CreateNewResourceType(CursorFreeHideCount,
   1097                                                 "XFixesCursorHideCount");
   1098     CursorWindowType = CreateNewResourceType(CursorFreeWindow,
   1099                                              "XFixesCursorWindow");
   1100 
   1101     return CursorClientType && CursorHideCountType && CursorWindowType;
   1102 }