cursor.c revision 6e78d31f
105b261ecSmrg/* 29ace9065Smrg * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. 335c4bbdfSmrg * Copyright 2010 Red Hat, Inc. 405b261ecSmrg * 56747b715Smrg * Permission is hereby granted, free of charge, to any person obtaining a 66747b715Smrg * copy of this software and associated documentation files (the "Software"), 76747b715Smrg * to deal in the Software without restriction, including without limitation 86747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 96747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the 106747b715Smrg * Software is furnished to do so, subject to the following conditions: 1105b261ecSmrg * 126747b715Smrg * The above copyright notice and this permission notice (including the next 136747b715Smrg * paragraph) shall be included in all copies or substantial portions of the 146747b715Smrg * Software. 156747b715Smrg * 166747b715Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 176747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 186747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 196747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 206747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 216747b715Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 226747b715Smrg * DEALINGS IN THE SOFTWARE. 2305b261ecSmrg * 2405b261ecSmrg * Copyright © 2002 Keith Packard 2505b261ecSmrg * 2605b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its 2705b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that 2805b261ecSmrg * the above copyright notice appear in all copies and that both that 2905b261ecSmrg * copyright notice and this permission notice appear in supporting 3005b261ecSmrg * documentation, and that the name of Keith Packard not be used in 3105b261ecSmrg * advertising or publicity pertaining to distribution of the software without 3205b261ecSmrg * specific, written prior permission. Keith Packard makes no 3305b261ecSmrg * representations about the suitability of this software for any purpose. It 3405b261ecSmrg * is provided "as is" without express or implied warranty. 3505b261ecSmrg * 3605b261ecSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 3705b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 3805b261ecSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 3905b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 4005b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 4105b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 4205b261ecSmrg * PERFORMANCE OF THIS SOFTWARE. 4305b261ecSmrg */ 4405b261ecSmrg 4505b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 4605b261ecSmrg#include <dix-config.h> 4705b261ecSmrg#endif 4805b261ecSmrg 4905b261ecSmrg#include "xfixesint.h" 5005b261ecSmrg#include "scrnintstr.h" 5105b261ecSmrg#include "cursorstr.h" 5205b261ecSmrg#include "dixevents.h" 5305b261ecSmrg#include "servermd.h" 5435c4bbdfSmrg#include "mipointer.h" 5505b261ecSmrg#include "inputstr.h" 5605b261ecSmrg#include "windowstr.h" 574642e01fSmrg#include "xace.h" 5835c4bbdfSmrg#include "list.h" 5935c4bbdfSmrg#include "xibarriers.h" 6005b261ecSmrg 6135c4bbdfSmrgstatic RESTYPE CursorClientType; 6235c4bbdfSmrgstatic RESTYPE CursorHideCountType; 6335c4bbdfSmrgstatic RESTYPE CursorWindowType; 6435c4bbdfSmrgstatic CursorPtr CursorCurrent[MAXDEVICES]; 6505b261ecSmrg 666747b715Smrgstatic DevPrivateKeyRec CursorScreenPrivateKeyRec; 6735c4bbdfSmrg 686747b715Smrg#define CursorScreenPrivateKey (&CursorScreenPrivateKeyRec) 694642e01fSmrg 7035c4bbdfSmrgstatic void deleteCursorHideCountsForScreen(ScreenPtr pScreen); 7105b261ecSmrg 726747b715Smrg#define VERIFY_CURSOR(pCursor, cursor, client, access) \ 736747b715Smrg do { \ 746747b715Smrg int err; \ 7535c4bbdfSmrg err = dixLookupResourceByType((void **) &pCursor, cursor, \ 766747b715Smrg RT_CURSOR, client, access); \ 776747b715Smrg if (err != Success) { \ 786747b715Smrg client->errorValue = cursor; \ 796747b715Smrg return err; \ 806747b715Smrg } \ 816747b715Smrg } while (0) 824642e01fSmrg 8305b261ecSmrg/* 8405b261ecSmrg * There is a global list of windows selecting for cursor events 8505b261ecSmrg */ 8605b261ecSmrg 8705b261ecSmrgtypedef struct _CursorEvent *CursorEventPtr; 8805b261ecSmrg 8905b261ecSmrgtypedef struct _CursorEvent { 9035c4bbdfSmrg CursorEventPtr next; 9135c4bbdfSmrg CARD32 eventMask; 9235c4bbdfSmrg ClientPtr pClient; 9335c4bbdfSmrg WindowPtr pWindow; 9435c4bbdfSmrg XID clientResource; 9505b261ecSmrg} CursorEventRec; 9605b261ecSmrg 9735c4bbdfSmrgstatic CursorEventPtr cursorEvents; 9805b261ecSmrg 9905b261ecSmrg/* 10005b261ecSmrg * Each screen has a list of clients which have requested 10105b261ecSmrg * that the cursor be hid, and the number of times each 10205b261ecSmrg * client has requested. 10305b261ecSmrg*/ 10405b261ecSmrg 10505b261ecSmrgtypedef struct _CursorHideCountRec *CursorHideCountPtr; 10605b261ecSmrg 10705b261ecSmrgtypedef struct _CursorHideCountRec { 10835c4bbdfSmrg CursorHideCountPtr pNext; 10935c4bbdfSmrg ClientPtr pClient; 11035c4bbdfSmrg ScreenPtr pScreen; 11135c4bbdfSmrg int hideCount; 11235c4bbdfSmrg XID resource; 11305b261ecSmrg} CursorHideCountRec; 11405b261ecSmrg 11505b261ecSmrg/* 11605b261ecSmrg * Wrap DisplayCursor to catch cursor change events 11705b261ecSmrg */ 11805b261ecSmrg 11905b261ecSmrgtypedef struct _CursorScreen { 12035c4bbdfSmrg DisplayCursorProcPtr DisplayCursor; 12135c4bbdfSmrg CloseScreenProcPtr CloseScreen; 12235c4bbdfSmrg CursorHideCountPtr pCursorHideCounts; 12305b261ecSmrg} CursorScreenRec, *CursorScreenPtr; 12405b261ecSmrg 1254642e01fSmrg#define GetCursorScreen(s) ((CursorScreenPtr)dixLookupPrivate(&(s)->devPrivates, CursorScreenPrivateKey)) 1264642e01fSmrg#define GetCursorScreenIfSet(s) GetCursorScreen(s) 1274642e01fSmrg#define SetCursorScreen(s,p) dixSetPrivate(&(s)->devPrivates, CursorScreenPrivateKey, p) 12805b261ecSmrg#define Wrap(as,s,elt,func) (((as)->elt = (s)->elt), (s)->elt = func) 1296747b715Smrg#define Unwrap(as,s,elt,backup) (((backup) = (s)->elt), (s)->elt = (as)->elt) 13005b261ecSmrg 1314642e01fSmrg/* The cursor doesn't show up until the first XDefineCursor() */ 13235c4bbdfSmrgBool CursorVisible = FALSE; 1336747b715SmrgBool EnableCursor = TRUE; 1346747b715Smrg 13505b261ecSmrgstatic Bool 13635c4bbdfSmrgCursorDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) 13705b261ecSmrg{ 13835c4bbdfSmrg CursorScreenPtr cs = GetCursorScreen(pScreen); 13935c4bbdfSmrg Bool ret; 1406747b715Smrg DisplayCursorProcPtr backupProc; 14105b261ecSmrg 14235c4bbdfSmrg Unwrap(cs, pScreen, DisplayCursor, backupProc); 14305b261ecSmrg 14435c4bbdfSmrg CursorVisible = CursorVisible && EnableCursor; 1454642e01fSmrg 1464642e01fSmrg if (cs->pCursorHideCounts != NULL || !CursorVisible) { 14735c4bbdfSmrg ret = (*pScreen->DisplayCursor) (pDev, pScreen, NullCursor); 14835c4bbdfSmrg } 14935c4bbdfSmrg else { 15035c4bbdfSmrg ret = (*pScreen->DisplayCursor) (pDev, pScreen, pCursor); 15105b261ecSmrg } 15205b261ecSmrg 15335c4bbdfSmrg if (pCursor != CursorCurrent[pDev->id]) { 15435c4bbdfSmrg CursorEventPtr e; 15535c4bbdfSmrg 15635c4bbdfSmrg CursorCurrent[pDev->id] = pCursor; 15735c4bbdfSmrg for (e = cursorEvents; e; e = e->next) { 15835c4bbdfSmrg if ((e->eventMask & XFixesDisplayCursorNotifyMask)) { 15935c4bbdfSmrg xXFixesCursorNotifyEvent ev = { 16035c4bbdfSmrg .type = XFixesEventBase + XFixesCursorNotify, 16135c4bbdfSmrg .subtype = XFixesDisplayCursorNotify, 16235c4bbdfSmrg .window = e->pWindow->drawable.id, 16335c4bbdfSmrg .cursorSerial = pCursor ? pCursor->serialNumber : 0, 16435c4bbdfSmrg .timestamp = currentTime.milliseconds, 16535c4bbdfSmrg .name = pCursor ? pCursor->name : None 16635c4bbdfSmrg }; 16735c4bbdfSmrg WriteEventsToClient(e->pClient, 1, (xEvent *) &ev); 16835c4bbdfSmrg } 16935c4bbdfSmrg } 17005b261ecSmrg } 17135c4bbdfSmrg Wrap(cs, pScreen, DisplayCursor, backupProc); 1726747b715Smrg 17305b261ecSmrg return ret; 17405b261ecSmrg} 17505b261ecSmrg 17605b261ecSmrgstatic Bool 17735c4bbdfSmrgCursorCloseScreen(ScreenPtr pScreen) 17805b261ecSmrg{ 17935c4bbdfSmrg CursorScreenPtr cs = GetCursorScreen(pScreen); 18035c4bbdfSmrg Bool ret; 18135c4bbdfSmrg _X_UNUSED CloseScreenProcPtr close_proc; 18235c4bbdfSmrg _X_UNUSED DisplayCursorProcPtr display_proc; 18305b261ecSmrg 18435c4bbdfSmrg Unwrap(cs, pScreen, CloseScreen, close_proc); 18535c4bbdfSmrg Unwrap(cs, pScreen, DisplayCursor, display_proc); 18605b261ecSmrg deleteCursorHideCountsForScreen(pScreen); 18735c4bbdfSmrg ret = (*pScreen->CloseScreen) (pScreen); 1886747b715Smrg free(cs); 18905b261ecSmrg return ret; 19005b261ecSmrg} 19105b261ecSmrg 19205b261ecSmrg#define CursorAllEvents (XFixesDisplayCursorNotifyMask) 19305b261ecSmrg 19405b261ecSmrgstatic int 19535c4bbdfSmrgXFixesSelectCursorInput(ClientPtr pClient, WindowPtr pWindow, CARD32 eventMask) 19605b261ecSmrg{ 19735c4bbdfSmrg CursorEventPtr *prev, e; 19835c4bbdfSmrg void *val; 1996747b715Smrg int rc; 20005b261ecSmrg 20135c4bbdfSmrg for (prev = &cursorEvents; (e = *prev); prev = &e->next) { 20235c4bbdfSmrg if (e->pClient == pClient && e->pWindow == pWindow) { 20335c4bbdfSmrg break; 20435c4bbdfSmrg } 20505b261ecSmrg } 20635c4bbdfSmrg if (!eventMask) { 20735c4bbdfSmrg if (e) { 20835c4bbdfSmrg FreeResource(e->clientResource, 0); 20935c4bbdfSmrg } 21035c4bbdfSmrg return Success; 21105b261ecSmrg } 21235c4bbdfSmrg if (!e) { 21335c4bbdfSmrg e = (CursorEventPtr) malloc(sizeof(CursorEventRec)); 21435c4bbdfSmrg if (!e) 21535c4bbdfSmrg return BadAlloc; 21635c4bbdfSmrg 21735c4bbdfSmrg e->next = 0; 21835c4bbdfSmrg e->pClient = pClient; 21935c4bbdfSmrg e->pWindow = pWindow; 22035c4bbdfSmrg e->clientResource = FakeClientID(pClient->index); 22135c4bbdfSmrg 22235c4bbdfSmrg /* 22335c4bbdfSmrg * Add a resource hanging from the window to 22435c4bbdfSmrg * catch window destroy 22535c4bbdfSmrg */ 22635c4bbdfSmrg rc = dixLookupResourceByType(&val, pWindow->drawable.id, 22735c4bbdfSmrg CursorWindowType, serverClient, 22835c4bbdfSmrg DixGetAttrAccess); 22935c4bbdfSmrg if (rc != Success) 23035c4bbdfSmrg if (!AddResource(pWindow->drawable.id, CursorWindowType, 23135c4bbdfSmrg (void *) pWindow)) { 23235c4bbdfSmrg free(e); 23335c4bbdfSmrg return BadAlloc; 23435c4bbdfSmrg } 23535c4bbdfSmrg 23635c4bbdfSmrg if (!AddResource(e->clientResource, CursorClientType, (void *) e)) 23735c4bbdfSmrg return BadAlloc; 23835c4bbdfSmrg 23935c4bbdfSmrg *prev = e; 24005b261ecSmrg } 24105b261ecSmrg e->eventMask = eventMask; 24205b261ecSmrg return Success; 24305b261ecSmrg} 24405b261ecSmrg 24505b261ecSmrgint 24635c4bbdfSmrgProcXFixesSelectCursorInput(ClientPtr client) 24705b261ecSmrg{ 24835c4bbdfSmrg REQUEST(xXFixesSelectCursorInputReq); 24935c4bbdfSmrg WindowPtr pWin; 25035c4bbdfSmrg int rc; 25105b261ecSmrg 25235c4bbdfSmrg REQUEST_SIZE_MATCH(xXFixesSelectCursorInputReq); 2534642e01fSmrg rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 25405b261ecSmrg if (rc != Success) 25505b261ecSmrg return rc; 25635c4bbdfSmrg if (stuff->eventMask & ~CursorAllEvents) { 25735c4bbdfSmrg client->errorValue = stuff->eventMask; 25835c4bbdfSmrg return BadValue; 25905b261ecSmrg } 26035c4bbdfSmrg return XFixesSelectCursorInput(client, pWin, stuff->eventMask); 26105b261ecSmrg} 26205b261ecSmrg 26305b261ecSmrgstatic int 26435c4bbdfSmrgGetBit(unsigned char *line, int x) 26505b261ecSmrg{ 26635c4bbdfSmrg unsigned char mask; 26735c4bbdfSmrg 26805b261ecSmrg if (screenInfo.bitmapBitOrder == LSBFirst) 26935c4bbdfSmrg mask = (1 << (x & 7)); 27005b261ecSmrg else 27135c4bbdfSmrg mask = (0x80 >> (x & 7)); 27205b261ecSmrg /* XXX assumes byte order is host byte order */ 27305b261ecSmrg line += (x >> 3); 27405b261ecSmrg if (*line & mask) 27535c4bbdfSmrg return 1; 27605b261ecSmrg return 0; 27705b261ecSmrg} 27805b261ecSmrg 27905b261ecSmrgint 28035c4bbdfSmrgSProcXFixesSelectCursorInput(ClientPtr client) 28105b261ecSmrg{ 28205b261ecSmrg REQUEST(xXFixesSelectCursorInputReq); 2836e78d31fSmrg REQUEST_SIZE_MATCH(xXFixesSelectCursorInputReq); 28405b261ecSmrg 28535c4bbdfSmrg swaps(&stuff->length); 28635c4bbdfSmrg swapl(&stuff->window); 28735c4bbdfSmrg swapl(&stuff->eventMask); 28805b261ecSmrg return (*ProcXFixesVector[stuff->xfixesReqType]) (client); 28905b261ecSmrg} 29035c4bbdfSmrg 29105b261ecSmrgvoid 29235c4bbdfSmrgSXFixesCursorNotifyEvent(xXFixesCursorNotifyEvent * from, 29335c4bbdfSmrg xXFixesCursorNotifyEvent * to) 29405b261ecSmrg{ 29505b261ecSmrg to->type = from->type; 29635c4bbdfSmrg cpswaps(from->sequenceNumber, to->sequenceNumber); 29735c4bbdfSmrg cpswapl(from->window, to->window); 29835c4bbdfSmrg cpswapl(from->cursorSerial, to->cursorSerial); 29935c4bbdfSmrg cpswapl(from->timestamp, to->timestamp); 30035c4bbdfSmrg cpswapl(from->name, to->name); 30105b261ecSmrg} 30205b261ecSmrg 30305b261ecSmrgstatic void 30435c4bbdfSmrgCopyCursorToImage(CursorPtr pCursor, CARD32 *image) 30505b261ecSmrg{ 30605b261ecSmrg int width = pCursor->bits->width; 30705b261ecSmrg int height = pCursor->bits->height; 30805b261ecSmrg int npixels = width * height; 30935c4bbdfSmrg 31005b261ecSmrg if (pCursor->bits->argb) 31135c4bbdfSmrg memcpy(image, pCursor->bits->argb, npixels * sizeof(CARD32)); 31205b261ecSmrg else 31305b261ecSmrg { 31435c4bbdfSmrg unsigned char *srcLine = pCursor->bits->source; 31535c4bbdfSmrg unsigned char *mskLine = pCursor->bits->mask; 31635c4bbdfSmrg int stride = BitmapBytePad(width); 31735c4bbdfSmrg int x, y; 31835c4bbdfSmrg CARD32 fg, bg; 31935c4bbdfSmrg 32035c4bbdfSmrg fg = (0xff000000 | 32135c4bbdfSmrg ((pCursor->foreRed & 0xff00) << 8) | 32235c4bbdfSmrg (pCursor->foreGreen & 0xff00) | (pCursor->foreBlue >> 8)); 32335c4bbdfSmrg bg = (0xff000000 | 32435c4bbdfSmrg ((pCursor->backRed & 0xff00) << 8) | 32535c4bbdfSmrg (pCursor->backGreen & 0xff00) | (pCursor->backBlue >> 8)); 32635c4bbdfSmrg for (y = 0; y < height; y++) { 32735c4bbdfSmrg for (x = 0; x < width; x++) { 32835c4bbdfSmrg if (GetBit(mskLine, x)) { 32935c4bbdfSmrg if (GetBit(srcLine, x)) 33035c4bbdfSmrg *image++ = fg; 33135c4bbdfSmrg else 33235c4bbdfSmrg *image++ = bg; 33335c4bbdfSmrg } 33435c4bbdfSmrg else 33535c4bbdfSmrg *image++ = 0; 33635c4bbdfSmrg } 33735c4bbdfSmrg srcLine += stride; 33835c4bbdfSmrg mskLine += stride; 33935c4bbdfSmrg } 34005b261ecSmrg } 34105b261ecSmrg} 34205b261ecSmrg 34305b261ecSmrgint 34435c4bbdfSmrgProcXFixesGetCursorImage(ClientPtr client) 34505b261ecSmrg{ 34605b261ecSmrg/* REQUEST(xXFixesGetCursorImageReq); */ 34735c4bbdfSmrg xXFixesGetCursorImageReply *rep; 34835c4bbdfSmrg CursorPtr pCursor; 34935c4bbdfSmrg CARD32 *image; 35035c4bbdfSmrg int npixels, width, height, rc, x, y; 35105b261ecSmrg 35205b261ecSmrg REQUEST_SIZE_MATCH(xXFixesGetCursorImageReq); 3536747b715Smrg pCursor = CursorCurrent[PickPointer(client)->id]; 35405b261ecSmrg if (!pCursor) 35535c4bbdfSmrg return BadCursor; 3564642e01fSmrg rc = XaceHook(XACE_RESOURCE_ACCESS, client, pCursor->id, RT_CURSOR, 35735c4bbdfSmrg pCursor, RT_NONE, NULL, DixReadAccess); 3584642e01fSmrg if (rc != Success) 35935c4bbdfSmrg return rc; 36035c4bbdfSmrg GetSpritePosition(PickPointer(client), &x, &y); 36105b261ecSmrg width = pCursor->bits->width; 36205b261ecSmrg height = pCursor->bits->height; 36305b261ecSmrg npixels = width * height; 36435c4bbdfSmrg rep = calloc(sizeof(xXFixesGetCursorImageReply) + npixels * sizeof(CARD32), 36535c4bbdfSmrg 1); 36605b261ecSmrg if (!rep) 36735c4bbdfSmrg return BadAlloc; 36805b261ecSmrg 36905b261ecSmrg rep->type = X_Reply; 37005b261ecSmrg rep->sequenceNumber = client->sequence; 37105b261ecSmrg rep->length = npixels; 37205b261ecSmrg rep->width = width; 37305b261ecSmrg rep->height = height; 37405b261ecSmrg rep->x = x; 37505b261ecSmrg rep->y = y; 37605b261ecSmrg rep->xhot = pCursor->bits->xhot; 37735c4bbdfSmrg rep->yhot = pCursor->bits->yhot; 37805b261ecSmrg rep->cursorSerial = pCursor->serialNumber; 37905b261ecSmrg 38005b261ecSmrg image = (CARD32 *) (rep + 1); 38135c4bbdfSmrg CopyCursorToImage(pCursor, image); 38235c4bbdfSmrg if (client->swapped) { 38335c4bbdfSmrg swaps(&rep->sequenceNumber); 38435c4bbdfSmrg swapl(&rep->length); 38535c4bbdfSmrg swaps(&rep->x); 38635c4bbdfSmrg swaps(&rep->y); 38735c4bbdfSmrg swaps(&rep->width); 38835c4bbdfSmrg swaps(&rep->height); 38935c4bbdfSmrg swaps(&rep->xhot); 39035c4bbdfSmrg swaps(&rep->yhot); 39135c4bbdfSmrg swapl(&rep->cursorSerial); 39235c4bbdfSmrg SwapLongs(image, npixels); 39305b261ecSmrg } 39435c4bbdfSmrg WriteToClient(client, 39535c4bbdfSmrg sizeof(xXFixesGetCursorImageReply) + (npixels << 2), rep); 3966747b715Smrg free(rep); 3976747b715Smrg return Success; 39805b261ecSmrg} 39905b261ecSmrg 40005b261ecSmrgint 40135c4bbdfSmrgSProcXFixesGetCursorImage(ClientPtr client) 40205b261ecSmrg{ 40305b261ecSmrg REQUEST(xXFixesGetCursorImageReq); 40435c4bbdfSmrg swaps(&stuff->length); 40505b261ecSmrg return (*ProcXFixesVector[stuff->xfixesReqType]) (client); 40605b261ecSmrg} 40705b261ecSmrg 40805b261ecSmrgint 40935c4bbdfSmrgProcXFixesSetCursorName(ClientPtr client) 41005b261ecSmrg{ 41105b261ecSmrg CursorPtr pCursor; 41205b261ecSmrg char *tchar; 41335c4bbdfSmrg 41405b261ecSmrg REQUEST(xXFixesSetCursorNameReq); 41505b261ecSmrg Atom atom; 41605b261ecSmrg 4176e78d31fSmrg REQUEST_FIXED_SIZE(xXFixesSetCursorNameReq, stuff->nbytes); 4184642e01fSmrg VERIFY_CURSOR(pCursor, stuff->cursor, client, DixSetAttrAccess); 41905b261ecSmrg tchar = (char *) &stuff[1]; 42035c4bbdfSmrg atom = MakeAtom(tchar, stuff->nbytes, TRUE); 42105b261ecSmrg if (atom == BAD_RESOURCE) 42235c4bbdfSmrg return BadAlloc; 42335c4bbdfSmrg 42405b261ecSmrg pCursor->name = atom; 4256747b715Smrg return Success; 42605b261ecSmrg} 42705b261ecSmrg 42805b261ecSmrgint 42935c4bbdfSmrgSProcXFixesSetCursorName(ClientPtr client) 43005b261ecSmrg{ 43105b261ecSmrg REQUEST(xXFixesSetCursorNameReq); 43205b261ecSmrg 43335c4bbdfSmrg swaps(&stuff->length); 43405b261ecSmrg REQUEST_AT_LEAST_SIZE(xXFixesSetCursorNameReq); 43535c4bbdfSmrg swapl(&stuff->cursor); 43635c4bbdfSmrg swaps(&stuff->nbytes); 43705b261ecSmrg return (*ProcXFixesVector[stuff->xfixesReqType]) (client); 43805b261ecSmrg} 43905b261ecSmrg 44005b261ecSmrgint 44135c4bbdfSmrgProcXFixesGetCursorName(ClientPtr client) 44205b261ecSmrg{ 44335c4bbdfSmrg CursorPtr pCursor; 44435c4bbdfSmrg xXFixesGetCursorNameReply reply; 44535c4bbdfSmrg 44605b261ecSmrg REQUEST(xXFixesGetCursorNameReq); 4476747b715Smrg const char *str; 44805b261ecSmrg int len; 44905b261ecSmrg 45005b261ecSmrg REQUEST_SIZE_MATCH(xXFixesGetCursorNameReq); 4514642e01fSmrg VERIFY_CURSOR(pCursor, stuff->cursor, client, DixGetAttrAccess); 45205b261ecSmrg if (pCursor->name) 45335c4bbdfSmrg str = NameForAtom(pCursor->name); 45405b261ecSmrg else 45535c4bbdfSmrg str = ""; 45635c4bbdfSmrg len = strlen(str); 45735c4bbdfSmrg 45835c4bbdfSmrg reply = (xXFixesGetCursorNameReply) { 45935c4bbdfSmrg .type = X_Reply, 46035c4bbdfSmrg .sequenceNumber = client->sequence, 46135c4bbdfSmrg .length = bytes_to_int32(len), 46235c4bbdfSmrg .atom = pCursor->name, 46335c4bbdfSmrg .nbytes = len 46435c4bbdfSmrg }; 46535c4bbdfSmrg if (client->swapped) { 46635c4bbdfSmrg swaps(&reply.sequenceNumber); 46735c4bbdfSmrg swapl(&reply.length); 46835c4bbdfSmrg swapl(&reply.atom); 46935c4bbdfSmrg swaps(&reply.nbytes); 47005b261ecSmrg } 47105b261ecSmrg WriteReplyToClient(client, sizeof(xXFixesGetCursorNameReply), &reply); 4726747b715Smrg WriteToClient(client, len, str); 47335c4bbdfSmrg 4746747b715Smrg return Success; 47505b261ecSmrg} 47605b261ecSmrg 47705b261ecSmrgint 47835c4bbdfSmrgSProcXFixesGetCursorName(ClientPtr client) 47905b261ecSmrg{ 48005b261ecSmrg REQUEST(xXFixesGetCursorNameReq); 48105b261ecSmrg 48235c4bbdfSmrg swaps(&stuff->length); 48305b261ecSmrg REQUEST_SIZE_MATCH(xXFixesGetCursorNameReq); 48435c4bbdfSmrg swapl(&stuff->cursor); 48505b261ecSmrg return (*ProcXFixesVector[stuff->xfixesReqType]) (client); 48605b261ecSmrg} 48705b261ecSmrg 48805b261ecSmrgint 48935c4bbdfSmrgProcXFixesGetCursorImageAndName(ClientPtr client) 49005b261ecSmrg{ 49105b261ecSmrg/* REQUEST(xXFixesGetCursorImageAndNameReq); */ 49235c4bbdfSmrg xXFixesGetCursorImageAndNameReply *rep; 49335c4bbdfSmrg CursorPtr pCursor; 49435c4bbdfSmrg CARD32 *image; 49535c4bbdfSmrg int npixels; 49635c4bbdfSmrg const char *name; 49735c4bbdfSmrg int nbytes, nbytesRound; 49835c4bbdfSmrg int width, height; 49935c4bbdfSmrg int rc, x, y; 50005b261ecSmrg 50105b261ecSmrg REQUEST_SIZE_MATCH(xXFixesGetCursorImageAndNameReq); 5026747b715Smrg pCursor = CursorCurrent[PickPointer(client)->id]; 50305b261ecSmrg if (!pCursor) 50435c4bbdfSmrg return BadCursor; 5054642e01fSmrg rc = XaceHook(XACE_RESOURCE_ACCESS, client, pCursor->id, RT_CURSOR, 50635c4bbdfSmrg pCursor, RT_NONE, NULL, DixReadAccess | DixGetAttrAccess); 5074642e01fSmrg if (rc != Success) 50835c4bbdfSmrg return rc; 50935c4bbdfSmrg GetSpritePosition(PickPointer(client), &x, &y); 51005b261ecSmrg width = pCursor->bits->width; 51105b261ecSmrg height = pCursor->bits->height; 51205b261ecSmrg npixels = width * height; 51335c4bbdfSmrg name = pCursor->name ? NameForAtom(pCursor->name) : ""; 51435c4bbdfSmrg nbytes = strlen(name); 5156747b715Smrg nbytesRound = pad_to_int32(nbytes); 51635c4bbdfSmrg rep = calloc(sizeof(xXFixesGetCursorImageAndNameReply) + 51735c4bbdfSmrg npixels * sizeof(CARD32) + nbytesRound, 1); 51805b261ecSmrg if (!rep) 51935c4bbdfSmrg return BadAlloc; 52005b261ecSmrg 52105b261ecSmrg rep->type = X_Reply; 52205b261ecSmrg rep->sequenceNumber = client->sequence; 5236747b715Smrg rep->length = npixels + bytes_to_int32(nbytesRound); 52405b261ecSmrg rep->width = width; 52505b261ecSmrg rep->height = height; 52605b261ecSmrg rep->x = x; 52705b261ecSmrg rep->y = y; 52805b261ecSmrg rep->xhot = pCursor->bits->xhot; 52935c4bbdfSmrg rep->yhot = pCursor->bits->yhot; 53005b261ecSmrg rep->cursorSerial = pCursor->serialNumber; 53105b261ecSmrg rep->cursorName = pCursor->name; 53205b261ecSmrg rep->nbytes = nbytes; 53305b261ecSmrg 53405b261ecSmrg image = (CARD32 *) (rep + 1); 53535c4bbdfSmrg CopyCursorToImage(pCursor, image); 53635c4bbdfSmrg memcpy((image + npixels), name, nbytes); 53735c4bbdfSmrg if (client->swapped) { 53835c4bbdfSmrg swaps(&rep->sequenceNumber); 53935c4bbdfSmrg swapl(&rep->length); 54035c4bbdfSmrg swaps(&rep->x); 54135c4bbdfSmrg swaps(&rep->y); 54235c4bbdfSmrg swaps(&rep->width); 54335c4bbdfSmrg swaps(&rep->height); 54435c4bbdfSmrg swaps(&rep->xhot); 54535c4bbdfSmrg swaps(&rep->yhot); 54635c4bbdfSmrg swapl(&rep->cursorSerial); 54735c4bbdfSmrg swapl(&rep->cursorName); 54835c4bbdfSmrg swaps(&rep->nbytes); 54935c4bbdfSmrg SwapLongs(image, npixels); 55005b261ecSmrg } 55135c4bbdfSmrg WriteToClient(client, sizeof(xXFixesGetCursorImageAndNameReply) + 55235c4bbdfSmrg (npixels << 2) + nbytesRound, rep); 5536747b715Smrg free(rep); 5546747b715Smrg return Success; 55505b261ecSmrg} 55605b261ecSmrg 55705b261ecSmrgint 55835c4bbdfSmrgSProcXFixesGetCursorImageAndName(ClientPtr client) 55905b261ecSmrg{ 56005b261ecSmrg REQUEST(xXFixesGetCursorImageAndNameReq); 56135c4bbdfSmrg swaps(&stuff->length); 56205b261ecSmrg return (*ProcXFixesVector[stuff->xfixesReqType]) (client); 56305b261ecSmrg} 56405b261ecSmrg 56505b261ecSmrg/* 56605b261ecSmrg * Find every cursor reference in the system, ask testCursor 56705b261ecSmrg * whether it should be replaced with a reference to pCursor. 56805b261ecSmrg */ 56905b261ecSmrg 57035c4bbdfSmrgtypedef Bool (*TestCursorFunc) (CursorPtr pOld, void *closure); 57105b261ecSmrg 57205b261ecSmrgtypedef struct { 57305b261ecSmrg RESTYPE type; 57405b261ecSmrg TestCursorFunc testCursor; 57505b261ecSmrg CursorPtr pNew; 57635c4bbdfSmrg void *closure; 57705b261ecSmrg} ReplaceCursorLookupRec, *ReplaceCursorLookupPtr; 57805b261ecSmrg 57935c4bbdfSmrgstatic const RESTYPE CursorRestypes[] = { 58005b261ecSmrg RT_WINDOW, RT_PASSIVEGRAB, RT_CURSOR 58105b261ecSmrg}; 58205b261ecSmrg 58305b261ecSmrg#define NUM_CURSOR_RESTYPES (sizeof (CursorRestypes) / sizeof (CursorRestypes[0])) 58405b261ecSmrg 58505b261ecSmrgstatic Bool 58635c4bbdfSmrgReplaceCursorLookup(void *value, XID id, void *closure) 58705b261ecSmrg{ 58835c4bbdfSmrg ReplaceCursorLookupPtr rcl = (ReplaceCursorLookupPtr) closure; 58935c4bbdfSmrg WindowPtr pWin; 59035c4bbdfSmrg GrabPtr pGrab; 59135c4bbdfSmrg CursorPtr pCursor = 0, *pCursorRef = 0; 59235c4bbdfSmrg XID cursor = 0; 59305b261ecSmrg 59405b261ecSmrg switch (rcl->type) { 59505b261ecSmrg case RT_WINDOW: 59635c4bbdfSmrg pWin = (WindowPtr) value; 59735c4bbdfSmrg if (pWin->optional) { 59835c4bbdfSmrg pCursorRef = &pWin->optional->cursor; 59935c4bbdfSmrg pCursor = *pCursorRef; 60035c4bbdfSmrg } 60135c4bbdfSmrg break; 60205b261ecSmrg case RT_PASSIVEGRAB: 60335c4bbdfSmrg pGrab = (GrabPtr) value; 60435c4bbdfSmrg pCursorRef = &pGrab->cursor; 60535c4bbdfSmrg pCursor = *pCursorRef; 60635c4bbdfSmrg break; 60705b261ecSmrg case RT_CURSOR: 60835c4bbdfSmrg pCursorRef = 0; 60935c4bbdfSmrg pCursor = (CursorPtr) value; 61035c4bbdfSmrg cursor = id; 61135c4bbdfSmrg break; 61205b261ecSmrg } 61335c4bbdfSmrg if (pCursor && pCursor != rcl->pNew) { 61435c4bbdfSmrg if ((*rcl->testCursor) (pCursor, rcl->closure)) { 61535c4bbdfSmrg CursorPtr curs = RefCursor(rcl->pNew); 61635c4bbdfSmrg /* either redirect reference or update resource database */ 61735c4bbdfSmrg if (pCursorRef) 61835c4bbdfSmrg *pCursorRef = curs; 61935c4bbdfSmrg else 62035c4bbdfSmrg ChangeResourceValue(id, RT_CURSOR, curs); 62135c4bbdfSmrg FreeCursor(pCursor, cursor); 62235c4bbdfSmrg } 62305b261ecSmrg } 62435c4bbdfSmrg return FALSE; /* keep walking */ 62505b261ecSmrg} 62605b261ecSmrg 62705b261ecSmrgstatic void 62835c4bbdfSmrgReplaceCursor(CursorPtr pCursor, TestCursorFunc testCursor, void *closure) 62905b261ecSmrg{ 63035c4bbdfSmrg int clientIndex; 63105b261ecSmrg int resIndex; 63235c4bbdfSmrg ReplaceCursorLookupRec rcl; 63335c4bbdfSmrg 63435c4bbdfSmrg /* 63505b261ecSmrg * Cursors exist only in the resource database, windows and grabs. 63605b261ecSmrg * All of these are always pointed at by the resource database. Walk 63705b261ecSmrg * the whole thing looking for cursors 63805b261ecSmrg */ 63905b261ecSmrg rcl.testCursor = testCursor; 64005b261ecSmrg rcl.pNew = pCursor; 64105b261ecSmrg rcl.closure = closure; 64205b261ecSmrg 64305b261ecSmrg /* for each client */ 64435c4bbdfSmrg for (clientIndex = 0; clientIndex < currentMaxClients; clientIndex++) { 64535c4bbdfSmrg if (!clients[clientIndex]) 64635c4bbdfSmrg continue; 64735c4bbdfSmrg for (resIndex = 0; resIndex < NUM_CURSOR_RESTYPES; resIndex++) { 64835c4bbdfSmrg rcl.type = CursorRestypes[resIndex]; 64935c4bbdfSmrg /* 65035c4bbdfSmrg * This function walks the entire client resource database 65135c4bbdfSmrg */ 65235c4bbdfSmrg LookupClientResourceComplex(clients[clientIndex], 65335c4bbdfSmrg rcl.type, 65435c4bbdfSmrg ReplaceCursorLookup, (void *) &rcl); 65535c4bbdfSmrg } 65605b261ecSmrg } 65705b261ecSmrg /* this "knows" that WindowHasNewCursor doesn't depend on it's argument */ 65835c4bbdfSmrg WindowHasNewCursor(screenInfo.screens[0]->root); 65905b261ecSmrg} 66005b261ecSmrg 66135c4bbdfSmrgstatic Bool 66235c4bbdfSmrgTestForCursor(CursorPtr pCursor, void *closure) 66305b261ecSmrg{ 66405b261ecSmrg return (pCursor == (CursorPtr) closure); 66505b261ecSmrg} 66605b261ecSmrg 66705b261ecSmrgint 66835c4bbdfSmrgProcXFixesChangeCursor(ClientPtr client) 66905b261ecSmrg{ 67035c4bbdfSmrg CursorPtr pSource, pDestination; 67135c4bbdfSmrg 67205b261ecSmrg REQUEST(xXFixesChangeCursorReq); 67305b261ecSmrg 67405b261ecSmrg REQUEST_SIZE_MATCH(xXFixesChangeCursorReq); 67535c4bbdfSmrg VERIFY_CURSOR(pSource, stuff->source, client, 67635c4bbdfSmrg DixReadAccess | DixGetAttrAccess); 67735c4bbdfSmrg VERIFY_CURSOR(pDestination, stuff->destination, client, 67835c4bbdfSmrg DixWriteAccess | DixSetAttrAccess); 67905b261ecSmrg 68035c4bbdfSmrg ReplaceCursor(pSource, TestForCursor, (void *) pDestination); 6816747b715Smrg return Success; 68205b261ecSmrg} 68305b261ecSmrg 68405b261ecSmrgint 68535c4bbdfSmrgSProcXFixesChangeCursor(ClientPtr client) 68605b261ecSmrg{ 68705b261ecSmrg REQUEST(xXFixesChangeCursorReq); 68805b261ecSmrg 68935c4bbdfSmrg swaps(&stuff->length); 69005b261ecSmrg REQUEST_SIZE_MATCH(xXFixesChangeCursorReq); 69135c4bbdfSmrg swapl(&stuff->source); 69235c4bbdfSmrg swapl(&stuff->destination); 69305b261ecSmrg return (*ProcXFixesVector[stuff->xfixesReqType]) (client); 69405b261ecSmrg} 69505b261ecSmrg 69605b261ecSmrgstatic Bool 69735c4bbdfSmrgTestForCursorName(CursorPtr pCursor, void *closure) 69805b261ecSmrg{ 6994642e01fSmrg Atom *pName = closure; 70035c4bbdfSmrg 7016747b715Smrg return pCursor->name == *pName; 70205b261ecSmrg} 70305b261ecSmrg 70405b261ecSmrgint 70535c4bbdfSmrgProcXFixesChangeCursorByName(ClientPtr client) 70605b261ecSmrg{ 70735c4bbdfSmrg CursorPtr pSource; 70835c4bbdfSmrg Atom name; 70935c4bbdfSmrg char *tchar; 71035c4bbdfSmrg 71105b261ecSmrg REQUEST(xXFixesChangeCursorByNameReq); 71205b261ecSmrg 71305b261ecSmrg REQUEST_FIXED_SIZE(xXFixesChangeCursorByNameReq, stuff->nbytes); 7144642e01fSmrg VERIFY_CURSOR(pSource, stuff->source, client, 71535c4bbdfSmrg DixReadAccess | DixGetAttrAccess); 71605b261ecSmrg tchar = (char *) &stuff[1]; 71735c4bbdfSmrg name = MakeAtom(tchar, stuff->nbytes, FALSE); 71805b261ecSmrg if (name) 71935c4bbdfSmrg ReplaceCursor(pSource, TestForCursorName, &name); 7206747b715Smrg return Success; 72105b261ecSmrg} 72205b261ecSmrg 72305b261ecSmrgint 72435c4bbdfSmrgSProcXFixesChangeCursorByName(ClientPtr client) 72505b261ecSmrg{ 72605b261ecSmrg REQUEST(xXFixesChangeCursorByNameReq); 72705b261ecSmrg 72835c4bbdfSmrg swaps(&stuff->length); 72935c4bbdfSmrg REQUEST_AT_LEAST_SIZE(xXFixesChangeCursorByNameReq); 73035c4bbdfSmrg swapl(&stuff->source); 73135c4bbdfSmrg swaps(&stuff->nbytes); 73205b261ecSmrg return (*ProcXFixesVector[stuff->xfixesReqType]) (client); 73305b261ecSmrg} 73405b261ecSmrg 73505b261ecSmrg/* 73605b261ecSmrg * Routines for manipulating the per-screen hide counts list. 73735c4bbdfSmrg * This list indicates which clients have requested cursor hiding 73805b261ecSmrg * for that screen. 73905b261ecSmrg */ 74005b261ecSmrg 74105b261ecSmrg/* Return the screen's hide-counts list element for the given client */ 74205b261ecSmrgstatic CursorHideCountPtr 74335c4bbdfSmrgfindCursorHideCount(ClientPtr pClient, ScreenPtr pScreen) 74405b261ecSmrg{ 74535c4bbdfSmrg CursorScreenPtr cs = GetCursorScreen(pScreen); 74605b261ecSmrg CursorHideCountPtr pChc; 74705b261ecSmrg 74805b261ecSmrg for (pChc = cs->pCursorHideCounts; pChc != NULL; pChc = pChc->pNext) { 74935c4bbdfSmrg if (pChc->pClient == pClient) { 75035c4bbdfSmrg return pChc; 75135c4bbdfSmrg } 75205b261ecSmrg } 75305b261ecSmrg 75435c4bbdfSmrg return NULL; 75505b261ecSmrg} 75605b261ecSmrg 75705b261ecSmrgstatic int 75835c4bbdfSmrgcreateCursorHideCount(ClientPtr pClient, ScreenPtr pScreen) 75905b261ecSmrg{ 76035c4bbdfSmrg CursorScreenPtr cs = GetCursorScreen(pScreen); 76105b261ecSmrg CursorHideCountPtr pChc; 76205b261ecSmrg 7636747b715Smrg pChc = (CursorHideCountPtr) malloc(sizeof(CursorHideCountRec)); 76405b261ecSmrg if (pChc == NULL) { 76535c4bbdfSmrg return BadAlloc; 76605b261ecSmrg } 76705b261ecSmrg pChc->pClient = pClient; 76805b261ecSmrg pChc->pScreen = pScreen; 76905b261ecSmrg pChc->hideCount = 1; 77005b261ecSmrg pChc->resource = FakeClientID(pClient->index); 77105b261ecSmrg pChc->pNext = cs->pCursorHideCounts; 77205b261ecSmrg cs->pCursorHideCounts = pChc; 77335c4bbdfSmrg 77435c4bbdfSmrg /* 77505b261ecSmrg * Create a resource for this element so it can be deleted 77605b261ecSmrg * when the client goes away. 77705b261ecSmrg */ 77835c4bbdfSmrg if (!AddResource(pChc->resource, CursorHideCountType, (void *) pChc)) 77935c4bbdfSmrg return BadAlloc; 78005b261ecSmrg 78105b261ecSmrg return Success; 78205b261ecSmrg} 78305b261ecSmrg 78435c4bbdfSmrg/* 78505b261ecSmrg * Delete the given hide-counts list element from its screen list. 78605b261ecSmrg */ 78705b261ecSmrgstatic void 78835c4bbdfSmrgdeleteCursorHideCount(CursorHideCountPtr pChcToDel, ScreenPtr pScreen) 78905b261ecSmrg{ 79035c4bbdfSmrg CursorScreenPtr cs = GetCursorScreen(pScreen); 79105b261ecSmrg CursorHideCountPtr pChc, pNext; 79205b261ecSmrg CursorHideCountPtr pChcLast = NULL; 79305b261ecSmrg 79405b261ecSmrg pChc = cs->pCursorHideCounts; 79505b261ecSmrg while (pChc != NULL) { 79635c4bbdfSmrg pNext = pChc->pNext; 79735c4bbdfSmrg if (pChc == pChcToDel) { 79835c4bbdfSmrg free(pChc); 79935c4bbdfSmrg if (pChcLast == NULL) { 80035c4bbdfSmrg cs->pCursorHideCounts = pNext; 80135c4bbdfSmrg } 80235c4bbdfSmrg else { 80335c4bbdfSmrg pChcLast->pNext = pNext; 80435c4bbdfSmrg } 80535c4bbdfSmrg return; 80635c4bbdfSmrg } 80735c4bbdfSmrg pChcLast = pChc; 80835c4bbdfSmrg pChc = pNext; 80905b261ecSmrg } 81005b261ecSmrg} 81105b261ecSmrg 81235c4bbdfSmrg/* 81305b261ecSmrg * Delete all the hide-counts list elements for this screen. 81405b261ecSmrg */ 81505b261ecSmrgstatic void 81635c4bbdfSmrgdeleteCursorHideCountsForScreen(ScreenPtr pScreen) 81705b261ecSmrg{ 81835c4bbdfSmrg CursorScreenPtr cs = GetCursorScreen(pScreen); 81905b261ecSmrg CursorHideCountPtr pChc, pTmp; 82005b261ecSmrg 82105b261ecSmrg pChc = cs->pCursorHideCounts; 82205b261ecSmrg while (pChc != NULL) { 82335c4bbdfSmrg pTmp = pChc->pNext; 82435c4bbdfSmrg FreeResource(pChc->resource, 0); 82535c4bbdfSmrg pChc = pTmp; 82605b261ecSmrg } 82735c4bbdfSmrg cs->pCursorHideCounts = NULL; 82805b261ecSmrg} 82905b261ecSmrg 83035c4bbdfSmrgint 83135c4bbdfSmrgProcXFixesHideCursor(ClientPtr client) 83205b261ecSmrg{ 83305b261ecSmrg WindowPtr pWin; 83405b261ecSmrg CursorHideCountPtr pChc; 83535c4bbdfSmrg 83605b261ecSmrg REQUEST(xXFixesHideCursorReq); 83705b261ecSmrg int ret; 83805b261ecSmrg 83935c4bbdfSmrg REQUEST_SIZE_MATCH(xXFixesHideCursorReq); 84005b261ecSmrg 84135c4bbdfSmrg ret = dixLookupResourceByType((void **) &pWin, stuff->window, RT_WINDOW, 84235c4bbdfSmrg client, DixGetAttrAccess); 8434642e01fSmrg if (ret != Success) { 84435c4bbdfSmrg client->errorValue = stuff->window; 84535c4bbdfSmrg return ret; 84605b261ecSmrg } 84705b261ecSmrg 84835c4bbdfSmrg /* 84935c4bbdfSmrg * Has client hidden the cursor before on this screen? 85035c4bbdfSmrg * If so, just increment the count. 85105b261ecSmrg */ 85205b261ecSmrg 85305b261ecSmrg pChc = findCursorHideCount(client, pWin->drawable.pScreen); 85405b261ecSmrg if (pChc != NULL) { 85535c4bbdfSmrg pChc->hideCount++; 85635c4bbdfSmrg return Success; 85705b261ecSmrg } 85805b261ecSmrg 85935c4bbdfSmrg /* 86035c4bbdfSmrg * This is the first time this client has hid the cursor 86105b261ecSmrg * for this screen. 86205b261ecSmrg */ 8634642e01fSmrg ret = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen, 86435c4bbdfSmrg DixHideAccess); 8654642e01fSmrg if (ret != Success) 86635c4bbdfSmrg return ret; 8674642e01fSmrg 86805b261ecSmrg ret = createCursorHideCount(client, pWin->drawable.pScreen); 86905b261ecSmrg 87005b261ecSmrg if (ret == Success) { 87135c4bbdfSmrg DeviceIntPtr dev; 87235c4bbdfSmrg 87335c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 87435c4bbdfSmrg if (IsMaster(dev) && IsPointerDevice(dev)) 87535c4bbdfSmrg CursorDisplayCursor(dev, pWin->drawable.pScreen, 87635c4bbdfSmrg CursorCurrent[dev->id]); 87735c4bbdfSmrg } 87805b261ecSmrg } 87905b261ecSmrg 88005b261ecSmrg return ret; 88105b261ecSmrg} 88205b261ecSmrg 88335c4bbdfSmrgint 88435c4bbdfSmrgSProcXFixesHideCursor(ClientPtr client) 88505b261ecSmrg{ 88605b261ecSmrg REQUEST(xXFixesHideCursorReq); 88705b261ecSmrg 88835c4bbdfSmrg swaps(&stuff->length); 88935c4bbdfSmrg REQUEST_SIZE_MATCH(xXFixesHideCursorReq); 89035c4bbdfSmrg swapl(&stuff->window); 89105b261ecSmrg return (*ProcXFixesVector[stuff->xfixesReqType]) (client); 89205b261ecSmrg} 89305b261ecSmrg 89435c4bbdfSmrgint 89535c4bbdfSmrgProcXFixesShowCursor(ClientPtr client) 89605b261ecSmrg{ 89705b261ecSmrg WindowPtr pWin; 89805b261ecSmrg CursorHideCountPtr pChc; 8994642e01fSmrg int rc; 90035c4bbdfSmrg 90105b261ecSmrg REQUEST(xXFixesShowCursorReq); 90205b261ecSmrg 90335c4bbdfSmrg REQUEST_SIZE_MATCH(xXFixesShowCursorReq); 90405b261ecSmrg 90535c4bbdfSmrg rc = dixLookupResourceByType((void **) &pWin, stuff->window, RT_WINDOW, 90635c4bbdfSmrg client, DixGetAttrAccess); 9074642e01fSmrg if (rc != Success) { 90835c4bbdfSmrg client->errorValue = stuff->window; 90935c4bbdfSmrg return rc; 91005b261ecSmrg } 91105b261ecSmrg 91235c4bbdfSmrg /* 91305b261ecSmrg * Has client hidden the cursor on this screen? 91405b261ecSmrg * If not, generate an error. 91505b261ecSmrg */ 91605b261ecSmrg pChc = findCursorHideCount(client, pWin->drawable.pScreen); 91705b261ecSmrg if (pChc == NULL) { 91835c4bbdfSmrg return BadMatch; 91905b261ecSmrg } 92005b261ecSmrg 9214642e01fSmrg rc = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen, 92235c4bbdfSmrg DixShowAccess); 9234642e01fSmrg if (rc != Success) 92435c4bbdfSmrg return rc; 9254642e01fSmrg 92605b261ecSmrg pChc->hideCount--; 92705b261ecSmrg if (pChc->hideCount <= 0) { 92835c4bbdfSmrg FreeResource(pChc->resource, 0); 92905b261ecSmrg } 93005b261ecSmrg 9316747b715Smrg return Success; 93205b261ecSmrg} 93305b261ecSmrg 93435c4bbdfSmrgint 93535c4bbdfSmrgSProcXFixesShowCursor(ClientPtr client) 93605b261ecSmrg{ 93705b261ecSmrg REQUEST(xXFixesShowCursorReq); 93805b261ecSmrg 93935c4bbdfSmrg swaps(&stuff->length); 94035c4bbdfSmrg REQUEST_SIZE_MATCH(xXFixesShowCursorReq); 94135c4bbdfSmrg swapl(&stuff->window); 94205b261ecSmrg return (*ProcXFixesVector[stuff->xfixesReqType]) (client); 94305b261ecSmrg} 94405b261ecSmrg 94505b261ecSmrgstatic int 94635c4bbdfSmrgCursorFreeClient(void *data, XID id) 94705b261ecSmrg{ 94835c4bbdfSmrg CursorEventPtr old = (CursorEventPtr) data; 94935c4bbdfSmrg CursorEventPtr *prev, e; 95035c4bbdfSmrg 95135c4bbdfSmrg for (prev = &cursorEvents; (e = *prev); prev = &e->next) { 95235c4bbdfSmrg if (e == old) { 95335c4bbdfSmrg *prev = e->next; 95435c4bbdfSmrg free(e); 95535c4bbdfSmrg break; 95635c4bbdfSmrg } 95705b261ecSmrg } 95805b261ecSmrg return 1; 95905b261ecSmrg} 96005b261ecSmrg 96105b261ecSmrgstatic int 96235c4bbdfSmrgCursorFreeHideCount(void *data, XID id) 96305b261ecSmrg{ 96405b261ecSmrg CursorHideCountPtr pChc = (CursorHideCountPtr) data; 96505b261ecSmrg ScreenPtr pScreen = pChc->pScreen; 9666747b715Smrg DeviceIntPtr dev; 96705b261ecSmrg 96805b261ecSmrg deleteCursorHideCount(pChc, pChc->pScreen); 96935c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 9706747b715Smrg if (IsMaster(dev) && IsPointerDevice(dev)) 9716747b715Smrg CursorDisplayCursor(dev, pScreen, CursorCurrent[dev->id]); 9726747b715Smrg } 97305b261ecSmrg 97405b261ecSmrg return 1; 97505b261ecSmrg} 97605b261ecSmrg 97705b261ecSmrgstatic int 97835c4bbdfSmrgCursorFreeWindow(void *data, XID id) 97905b261ecSmrg{ 98035c4bbdfSmrg WindowPtr pWindow = (WindowPtr) data; 98135c4bbdfSmrg CursorEventPtr e, next; 98235c4bbdfSmrg 98335c4bbdfSmrg for (e = cursorEvents; e; e = next) { 98435c4bbdfSmrg next = e->next; 98535c4bbdfSmrg if (e->pWindow == pWindow) { 98635c4bbdfSmrg FreeResource(e->clientResource, 0); 98735c4bbdfSmrg } 98805b261ecSmrg } 98905b261ecSmrg return 1; 99005b261ecSmrg} 99105b261ecSmrg 99235c4bbdfSmrgint 99335c4bbdfSmrgProcXFixesCreatePointerBarrier(ClientPtr client) 99435c4bbdfSmrg{ 99535c4bbdfSmrg REQUEST(xXFixesCreatePointerBarrierReq); 99635c4bbdfSmrg 99735c4bbdfSmrg REQUEST_FIXED_SIZE(xXFixesCreatePointerBarrierReq, pad_to_int32(stuff->num_devices)); 99835c4bbdfSmrg LEGAL_NEW_RESOURCE(stuff->barrier, client); 99935c4bbdfSmrg 100035c4bbdfSmrg return XICreatePointerBarrier(client, stuff); 100135c4bbdfSmrg} 100235c4bbdfSmrg 100335c4bbdfSmrgint 100435c4bbdfSmrgSProcXFixesCreatePointerBarrier(ClientPtr client) 100535c4bbdfSmrg{ 100635c4bbdfSmrg REQUEST(xXFixesCreatePointerBarrierReq); 100735c4bbdfSmrg int i; 100835c4bbdfSmrg CARD16 *in_devices = (CARD16 *) &stuff[1]; 100935c4bbdfSmrg 10106e78d31fSmrg REQUEST_AT_LEAST_SIZE(xXFixesCreatePointerBarrierReq); 10116e78d31fSmrg 101235c4bbdfSmrg swaps(&stuff->length); 101335c4bbdfSmrg swaps(&stuff->num_devices); 101435c4bbdfSmrg REQUEST_FIXED_SIZE(xXFixesCreatePointerBarrierReq, pad_to_int32(stuff->num_devices)); 101535c4bbdfSmrg 101635c4bbdfSmrg swapl(&stuff->barrier); 101735c4bbdfSmrg swapl(&stuff->window); 101835c4bbdfSmrg swaps(&stuff->x1); 101935c4bbdfSmrg swaps(&stuff->y1); 102035c4bbdfSmrg swaps(&stuff->x2); 102135c4bbdfSmrg swaps(&stuff->y2); 102235c4bbdfSmrg swapl(&stuff->directions); 102335c4bbdfSmrg for (i = 0; i < stuff->num_devices; i++) { 102435c4bbdfSmrg swaps(in_devices + i); 102535c4bbdfSmrg } 102635c4bbdfSmrg 102735c4bbdfSmrg return ProcXFixesVector[stuff->xfixesReqType] (client); 102835c4bbdfSmrg} 102935c4bbdfSmrg 103035c4bbdfSmrgint 103135c4bbdfSmrgProcXFixesDestroyPointerBarrier(ClientPtr client) 103235c4bbdfSmrg{ 103335c4bbdfSmrg REQUEST(xXFixesDestroyPointerBarrierReq); 103435c4bbdfSmrg 103535c4bbdfSmrg REQUEST_SIZE_MATCH(xXFixesDestroyPointerBarrierReq); 103635c4bbdfSmrg 103735c4bbdfSmrg return XIDestroyPointerBarrier(client, stuff); 103835c4bbdfSmrg} 103935c4bbdfSmrg 104035c4bbdfSmrgint 104135c4bbdfSmrgSProcXFixesDestroyPointerBarrier(ClientPtr client) 104235c4bbdfSmrg{ 104335c4bbdfSmrg REQUEST(xXFixesDestroyPointerBarrierReq); 104435c4bbdfSmrg 104535c4bbdfSmrg swaps(&stuff->length); 104635c4bbdfSmrg REQUEST_SIZE_MATCH(xXFixesDestroyPointerBarrierReq); 104735c4bbdfSmrg swapl(&stuff->barrier); 104835c4bbdfSmrg return ProcXFixesVector[stuff->xfixesReqType] (client); 104935c4bbdfSmrg} 105035c4bbdfSmrg 105105b261ecSmrgBool 105235c4bbdfSmrgXFixesCursorInit(void) 105305b261ecSmrg{ 105435c4bbdfSmrg int i; 10554642e01fSmrg 10564642e01fSmrg if (party_like_its_1989) 105735c4bbdfSmrg CursorVisible = EnableCursor; 105835c4bbdfSmrg else 105935c4bbdfSmrg CursorVisible = FALSE; 10606747b715Smrg 106135c4bbdfSmrg if (!dixRegisterPrivateKey(&CursorScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) 106235c4bbdfSmrg return FALSE; 106335c4bbdfSmrg 106435c4bbdfSmrg for (i = 0; i < screenInfo.numScreens; i++) { 106535c4bbdfSmrg ScreenPtr pScreen = screenInfo.screens[i]; 106635c4bbdfSmrg CursorScreenPtr cs; 106735c4bbdfSmrg 106835c4bbdfSmrg cs = (CursorScreenPtr) calloc(1, sizeof(CursorScreenRec)); 106935c4bbdfSmrg if (!cs) 107035c4bbdfSmrg return FALSE; 107135c4bbdfSmrg Wrap(cs, pScreen, CloseScreen, CursorCloseScreen); 107235c4bbdfSmrg Wrap(cs, pScreen, DisplayCursor, CursorDisplayCursor); 107335c4bbdfSmrg cs->pCursorHideCounts = NULL; 107435c4bbdfSmrg SetCursorScreen(pScreen, cs); 107505b261ecSmrg } 10766747b715Smrg CursorClientType = CreateNewResourceType(CursorFreeClient, 107735c4bbdfSmrg "XFixesCursorClient"); 10786747b715Smrg CursorHideCountType = CreateNewResourceType(CursorFreeHideCount, 107935c4bbdfSmrg "XFixesCursorHideCount"); 10806747b715Smrg CursorWindowType = CreateNewResourceType(CursorFreeWindow, 108135c4bbdfSmrg "XFixesCursorWindow"); 10826747b715Smrg 10836747b715Smrg return CursorClientType && CursorHideCountType && CursorWindowType; 108405b261ecSmrg} 1085