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