cursor.c 27 KB

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