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