2 * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
3 * Copyright 2010 Red Hat, Inc.
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:
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
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.
24 * Copyright © 2002 Keith Packard
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.
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.
45 #ifdef HAVE_DIX_CONFIG_H
46 #include <dix-config.h>
49 #include "xfixesint.h"
50 #include "scrnintstr.h"
51 #include "cursorstr.h"
52 #include "dixevents.h"
54 #include "mipointer.h"
56 #include "windowstr.h"
59 #include "xibarriers.h"
61 static RESTYPE CursorClientType
;
62 static RESTYPE CursorHideCountType
;
63 static RESTYPE CursorWindowType
;
64 static CursorPtr CursorCurrent
[MAXDEVICES
];
66 static DevPrivateKeyRec CursorScreenPrivateKeyRec
;
68 #define CursorScreenPrivateKey (&CursorScreenPrivateKeyRec)
70 static void deleteCursorHideCountsForScreen(ScreenPtr pScreen
);
72 #define VERIFY_CURSOR(pCursor, cursor, client, access) \
75 err = dixLookupResourceByType((pointer *) &pCursor, cursor, \
76 RT_CURSOR, client, access); \
77 if (err != Success) { \
78 client->errorValue = cursor; \
84 * There is a global list of windows selecting for cursor events
87 typedef struct _CursorEvent
*CursorEventPtr
;
89 typedef struct _CursorEvent
{
97 static CursorEventPtr cursorEvents
;
100 * Each screen has a list of clients which have requested
101 * that the cursor be hid, and the number of times each
102 * client has requested.
105 typedef struct _CursorHideCountRec
*CursorHideCountPtr
;
107 typedef struct _CursorHideCountRec
{
108 CursorHideCountPtr pNext
;
113 } CursorHideCountRec
;
116 * Wrap DisplayCursor to catch cursor change events
119 typedef struct _CursorScreen
{
120 DisplayCursorProcPtr DisplayCursor
;
121 CloseScreenProcPtr CloseScreen
;
122 CursorHideCountPtr pCursorHideCounts
;
123 } CursorScreenRec
, *CursorScreenPtr
;
125 #define GetCursorScreen(s) ((CursorScreenPtr)dixLookupPrivate(&(s)->devPrivates, CursorScreenPrivateKey))
126 #define GetCursorScreenIfSet(s) GetCursorScreen(s)
127 #define SetCursorScreen(s,p) dixSetPrivate(&(s)->devPrivates, CursorScreenPrivateKey, p)
128 #define Wrap(as,s,elt,func) (((as)->elt = (s)->elt), (s)->elt = func)
129 #define Unwrap(as,s,elt,backup) (((backup) = (s)->elt), (s)->elt = (as)->elt)
131 /* The cursor doesn't show up until the first XDefineCursor() */
132 Bool CursorVisible
= FALSE
;
133 Bool EnableCursor
= TRUE
;
136 CursorDisplayCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
, CursorPtr pCursor
)
138 CursorScreenPtr cs
= GetCursorScreen(pScreen
);
140 DisplayCursorProcPtr backupProc
;
142 Unwrap(cs
, pScreen
, DisplayCursor
, backupProc
);
144 CursorVisible
= CursorVisible
&& EnableCursor
;
146 if (cs
->pCursorHideCounts
!= NULL
|| !CursorVisible
) {
147 ret
= (*pScreen
->DisplayCursor
) (pDev
, pScreen
, NullCursor
);
150 ret
= (*pScreen
->DisplayCursor
) (pDev
, pScreen
, pCursor
);
153 if (pCursor
!= CursorCurrent
[pDev
->id
]) {
156 CursorCurrent
[pDev
->id
] = pCursor
;
157 for (e
= cursorEvents
; e
; e
= e
->next
) {
158 if ((e
->eventMask
& XFixesDisplayCursorNotifyMask
)) {
159 xXFixesCursorNotifyEvent ev
= {
160 .type
= XFixesEventBase
+ XFixesCursorNotify
,
161 .subtype
= XFixesDisplayCursorNotify
,
162 .window
= e
->pWindow
->drawable
.id
,
163 .cursorSerial
= pCursor
? pCursor
->serialNumber
: 0,
164 .timestamp
= currentTime
.milliseconds
,
165 .name
= pCursor
? pCursor
->name
: None
167 WriteEventsToClient(e
->pClient
, 1, (xEvent
*) &ev
);
171 Wrap(cs
, pScreen
, DisplayCursor
, backupProc
);
177 CursorCloseScreen(ScreenPtr pScreen
)
179 CursorScreenPtr cs
= GetCursorScreen(pScreen
);
181 _X_UNUSED CloseScreenProcPtr close_proc
;
182 _X_UNUSED DisplayCursorProcPtr display_proc
;
184 Unwrap(cs
, pScreen
, CloseScreen
, close_proc
);
185 Unwrap(cs
, pScreen
, DisplayCursor
, display_proc
);
186 deleteCursorHideCountsForScreen(pScreen
);
187 ret
= (*pScreen
->CloseScreen
) (pScreen
);
192 #define CursorAllEvents (XFixesDisplayCursorNotifyMask)
195 XFixesSelectCursorInput(ClientPtr pClient
, WindowPtr pWindow
, CARD32 eventMask
)
197 CursorEventPtr
*prev
, e
;
201 for (prev
= &cursorEvents
; (e
= *prev
); prev
= &e
->next
) {
202 if (e
->pClient
== pClient
&& e
->pWindow
== pWindow
) {
208 FreeResource(e
->clientResource
, 0);
213 e
= (CursorEventPtr
) malloc(sizeof(CursorEventRec
));
218 e
->pClient
= pClient
;
219 e
->pWindow
= pWindow
;
220 e
->clientResource
= FakeClientID(pClient
->index
);
223 * Add a resource hanging from the window to
224 * catch window destroy
226 rc
= dixLookupResourceByType(&val
, pWindow
->drawable
.id
,
227 CursorWindowType
, serverClient
,
230 if (!AddResource(pWindow
->drawable
.id
, CursorWindowType
,
231 (pointer
) pWindow
)) {
236 if (!AddResource(e
->clientResource
, CursorClientType
, (pointer
) e
))
241 e
->eventMask
= eventMask
;
246 ProcXFixesSelectCursorInput(ClientPtr client
)
248 REQUEST(xXFixesSelectCursorInputReq
);
252 REQUEST_SIZE_MATCH(xXFixesSelectCursorInputReq
);
253 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixGetAttrAccess
);
256 if (stuff
->eventMask
& ~CursorAllEvents
) {
257 client
->errorValue
= stuff
->eventMask
;
260 return XFixesSelectCursorInput(client
, pWin
, stuff
->eventMask
);
264 GetBit(unsigned char *line
, int x
)
268 if (screenInfo
.bitmapBitOrder
== LSBFirst
)
269 mask
= (1 << (x
& 7));
271 mask
= (0x80 >> (x
& 7));
272 /* XXX assumes byte order is host byte order */
280 SProcXFixesSelectCursorInput(ClientPtr client
)
282 REQUEST(xXFixesSelectCursorInputReq
);
284 swaps(&stuff
->length
);
285 swapl(&stuff
->window
);
286 swapl(&stuff
->eventMask
);
287 return (*ProcXFixesVector
[stuff
->xfixesReqType
]) (client
);
291 SXFixesCursorNotifyEvent(xXFixesCursorNotifyEvent
* from
,
292 xXFixesCursorNotifyEvent
* to
)
294 to
->type
= from
->type
;
295 cpswaps(from
->sequenceNumber
, to
->sequenceNumber
);
296 cpswapl(from
->window
, to
->window
);
297 cpswapl(from
->cursorSerial
, to
->cursorSerial
);
298 cpswapl(from
->timestamp
, to
->timestamp
);
299 cpswapl(from
->name
, to
->name
);
303 CopyCursorToImage(CursorPtr pCursor
, CARD32
*image
)
305 int width
= pCursor
->bits
->width
;
306 int height
= pCursor
->bits
->height
;
307 int npixels
= width
* height
;
310 if (pCursor
->bits
->argb
)
311 memcpy(image
, pCursor
->bits
->argb
, npixels
* sizeof(CARD32
));
315 unsigned char *srcLine
= pCursor
->bits
->source
;
316 unsigned char *mskLine
= pCursor
->bits
->mask
;
317 int stride
= BitmapBytePad(width
);
322 ((pCursor
->foreRed
& 0xff00) << 8) |
323 (pCursor
->foreGreen
& 0xff00) | (pCursor
->foreBlue
>> 8));
325 ((pCursor
->backRed
& 0xff00) << 8) |
326 (pCursor
->backGreen
& 0xff00) | (pCursor
->backBlue
>> 8));
327 for (y
= 0; y
< height
; y
++) {
328 for (x
= 0; x
< width
; x
++) {
329 if (GetBit(mskLine
, x
)) {
330 if (GetBit(srcLine
, x
))
345 ProcXFixesGetCursorImage(ClientPtr client
)
347 /* REQUEST(xXFixesGetCursorImageReq); */
348 xXFixesGetCursorImageReply
*rep
;
351 int npixels
, width
, height
, rc
, x
, y
;
353 REQUEST_SIZE_MATCH(xXFixesGetCursorImageReq
);
354 pCursor
= CursorCurrent
[PickPointer(client
)->id
];
357 rc
= XaceHook(XACE_RESOURCE_ACCESS
, client
, pCursor
->id
, RT_CURSOR
,
358 pCursor
, RT_NONE
, NULL
, DixReadAccess
);
361 GetSpritePosition(PickPointer(client
), &x
, &y
);
362 width
= pCursor
->bits
->width
;
363 height
= pCursor
->bits
->height
;
364 npixels
= width
* height
;
365 rep
= calloc(sizeof(xXFixesGetCursorImageReply
) + npixels
* sizeof(CARD32
),
371 rep
->sequenceNumber
= client
->sequence
;
372 rep
->length
= npixels
;
374 rep
->height
= height
;
377 rep
->xhot
= pCursor
->bits
->xhot
;
378 rep
->yhot
= pCursor
->bits
->yhot
;
379 rep
->cursorSerial
= pCursor
->serialNumber
;
381 image
= (CARD32
*) (rep
+ 1);
382 CopyCursorToImage(pCursor
, image
);
383 if (client
->swapped
) {
384 swaps(&rep
->sequenceNumber
);
392 swapl(&rep
->cursorSerial
);
393 SwapLongs(image
, npixels
);
395 WriteToClient(client
,
396 sizeof(xXFixesGetCursorImageReply
) + (npixels
<< 2), rep
);
402 SProcXFixesGetCursorImage(ClientPtr client
)
404 REQUEST(xXFixesGetCursorImageReq
);
405 swaps(&stuff
->length
);
406 return (*ProcXFixesVector
[stuff
->xfixesReqType
]) (client
);
410 ProcXFixesSetCursorName(ClientPtr client
)
415 REQUEST(xXFixesSetCursorNameReq
);
418 REQUEST_AT_LEAST_SIZE(xXFixesSetCursorNameReq
);
419 VERIFY_CURSOR(pCursor
, stuff
->cursor
, client
, DixSetAttrAccess
);
420 tchar
= (char *) &stuff
[1];
421 atom
= MakeAtom(tchar
, stuff
->nbytes
, TRUE
);
422 if (atom
== BAD_RESOURCE
)
425 pCursor
->name
= atom
;
430 SProcXFixesSetCursorName(ClientPtr client
)
432 REQUEST(xXFixesSetCursorNameReq
);
434 swaps(&stuff
->length
);
435 REQUEST_AT_LEAST_SIZE(xXFixesSetCursorNameReq
);
436 swapl(&stuff
->cursor
);
437 swaps(&stuff
->nbytes
);
438 return (*ProcXFixesVector
[stuff
->xfixesReqType
]) (client
);
442 ProcXFixesGetCursorName(ClientPtr client
)
445 xXFixesGetCursorNameReply reply
;
447 REQUEST(xXFixesGetCursorNameReq
);
451 REQUEST_SIZE_MATCH(xXFixesGetCursorNameReq
);
452 VERIFY_CURSOR(pCursor
, stuff
->cursor
, client
, DixGetAttrAccess
);
454 str
= NameForAtom(pCursor
->name
);
459 reply
= (xXFixesGetCursorNameReply
) {
461 .sequenceNumber
= client
->sequence
,
462 .length
= bytes_to_int32(len
),
463 .atom
= pCursor
->name
,
466 if (client
->swapped
) {
467 swaps(&reply
.sequenceNumber
);
468 swapl(&reply
.length
);
470 swaps(&reply
.nbytes
);
472 WriteReplyToClient(client
, sizeof(xXFixesGetCursorNameReply
), &reply
);
473 WriteToClient(client
, len
, str
);
479 SProcXFixesGetCursorName(ClientPtr client
)
481 REQUEST(xXFixesGetCursorNameReq
);
483 swaps(&stuff
->length
);
484 REQUEST_SIZE_MATCH(xXFixesGetCursorNameReq
);
485 swapl(&stuff
->cursor
);
486 return (*ProcXFixesVector
[stuff
->xfixesReqType
]) (client
);
490 ProcXFixesGetCursorImageAndName(ClientPtr client
)
492 /* REQUEST(xXFixesGetCursorImageAndNameReq); */
493 xXFixesGetCursorImageAndNameReply
*rep
;
498 int nbytes
, nbytesRound
;
502 REQUEST_SIZE_MATCH(xXFixesGetCursorImageAndNameReq
);
503 pCursor
= CursorCurrent
[PickPointer(client
)->id
];
506 rc
= XaceHook(XACE_RESOURCE_ACCESS
, client
, pCursor
->id
, RT_CURSOR
,
507 pCursor
, RT_NONE
, NULL
, DixReadAccess
| DixGetAttrAccess
);
510 GetSpritePosition(PickPointer(client
), &x
, &y
);
511 width
= pCursor
->bits
->width
;
512 height
= pCursor
->bits
->height
;
513 npixels
= width
* height
;
514 name
= pCursor
->name
? NameForAtom(pCursor
->name
) : "";
515 nbytes
= strlen(name
);
516 nbytesRound
= pad_to_int32(nbytes
);
517 rep
= calloc(sizeof(xXFixesGetCursorImageAndNameReply
) +
518 npixels
* sizeof(CARD32
) + nbytesRound
, 1);
523 rep
->sequenceNumber
= client
->sequence
;
524 rep
->length
= npixels
+ bytes_to_int32(nbytesRound
);
526 rep
->height
= height
;
529 rep
->xhot
= pCursor
->bits
->xhot
;
530 rep
->yhot
= pCursor
->bits
->yhot
;
531 rep
->cursorSerial
= pCursor
->serialNumber
;
532 rep
->cursorName
= pCursor
->name
;
533 rep
->nbytes
= nbytes
;
535 image
= (CARD32
*) (rep
+ 1);
536 CopyCursorToImage(pCursor
, image
);
537 memcpy((image
+ npixels
), name
, nbytes
);
538 if (client
->swapped
) {
539 swaps(&rep
->sequenceNumber
);
547 swapl(&rep
->cursorSerial
);
548 swapl(&rep
->cursorName
);
550 SwapLongs(image
, npixels
);
552 WriteToClient(client
, sizeof(xXFixesGetCursorImageAndNameReply
) +
553 (npixels
<< 2) + nbytesRound
, rep
);
559 SProcXFixesGetCursorImageAndName(ClientPtr client
)
561 REQUEST(xXFixesGetCursorImageAndNameReq
);
562 swaps(&stuff
->length
);
563 return (*ProcXFixesVector
[stuff
->xfixesReqType
]) (client
);
567 * Find every cursor reference in the system, ask testCursor
568 * whether it should be replaced with a reference to pCursor.
571 typedef Bool (*TestCursorFunc
) (CursorPtr pOld
, pointer closure
);
575 TestCursorFunc testCursor
;
578 } ReplaceCursorLookupRec
, *ReplaceCursorLookupPtr
;
580 static const RESTYPE CursorRestypes
[] = {
581 RT_WINDOW
, RT_PASSIVEGRAB
, RT_CURSOR
584 #define NUM_CURSOR_RESTYPES (sizeof (CursorRestypes) / sizeof (CursorRestypes[0]))
587 ReplaceCursorLookup(pointer value
, XID id
, pointer closure
)
589 ReplaceCursorLookupPtr rcl
= (ReplaceCursorLookupPtr
) closure
;
592 CursorPtr pCursor
= 0, *pCursorRef
= 0;
597 pWin
= (WindowPtr
) value
;
598 if (pWin
->optional
) {
599 pCursorRef
= &pWin
->optional
->cursor
;
600 pCursor
= *pCursorRef
;
604 pGrab
= (GrabPtr
) value
;
605 pCursorRef
= &pGrab
->cursor
;
606 pCursor
= *pCursorRef
;
610 pCursor
= (CursorPtr
) value
;
614 if (pCursor
&& pCursor
!= rcl
->pNew
) {
615 if ((*rcl
->testCursor
) (pCursor
, rcl
->closure
)) {
616 CursorPtr curs
= RefCursor(rcl
->pNew
);
617 /* either redirect reference or update resource database */
621 ChangeResourceValue(id
, RT_CURSOR
, curs
);
622 FreeCursor(pCursor
, cursor
);
625 return FALSE
; /* keep walking */
629 ReplaceCursor(CursorPtr pCursor
, TestCursorFunc testCursor
, pointer closure
)
633 ReplaceCursorLookupRec rcl
;
636 * Cursors exist only in the resource database, windows and grabs.
637 * All of these are always pointed at by the resource database. Walk
638 * the whole thing looking for cursors
640 rcl
.testCursor
= testCursor
;
642 rcl
.closure
= closure
;
644 /* for each client */
645 for (clientIndex
= 0; clientIndex
< currentMaxClients
; clientIndex
++) {
646 if (!clients
[clientIndex
])
648 for (resIndex
= 0; resIndex
< NUM_CURSOR_RESTYPES
; resIndex
++) {
649 rcl
.type
= CursorRestypes
[resIndex
];
651 * This function walks the entire client resource database
653 LookupClientResourceComplex(clients
[clientIndex
],
655 ReplaceCursorLookup
, (pointer
) &rcl
);
658 /* this "knows" that WindowHasNewCursor doesn't depend on it's argument */
659 WindowHasNewCursor(screenInfo
.screens
[0]->root
);
663 TestForCursor(CursorPtr pCursor
, pointer closure
)
665 return (pCursor
== (CursorPtr
) closure
);
669 ProcXFixesChangeCursor(ClientPtr client
)
671 CursorPtr pSource
, pDestination
;
673 REQUEST(xXFixesChangeCursorReq
);
675 REQUEST_SIZE_MATCH(xXFixesChangeCursorReq
);
676 VERIFY_CURSOR(pSource
, stuff
->source
, client
,
677 DixReadAccess
| DixGetAttrAccess
);
678 VERIFY_CURSOR(pDestination
, stuff
->destination
, client
,
679 DixWriteAccess
| DixSetAttrAccess
);
681 ReplaceCursor(pSource
, TestForCursor
, (pointer
) pDestination
);
686 SProcXFixesChangeCursor(ClientPtr client
)
688 REQUEST(xXFixesChangeCursorReq
);
690 swaps(&stuff
->length
);
691 REQUEST_SIZE_MATCH(xXFixesChangeCursorReq
);
692 swapl(&stuff
->source
);
693 swapl(&stuff
->destination
);
694 return (*ProcXFixesVector
[stuff
->xfixesReqType
]) (client
);
698 TestForCursorName(CursorPtr pCursor
, pointer closure
)
700 Atom
*pName
= closure
;
702 return pCursor
->name
== *pName
;
706 ProcXFixesChangeCursorByName(ClientPtr client
)
712 REQUEST(xXFixesChangeCursorByNameReq
);
714 REQUEST_FIXED_SIZE(xXFixesChangeCursorByNameReq
, stuff
->nbytes
);
715 VERIFY_CURSOR(pSource
, stuff
->source
, client
,
716 DixReadAccess
| DixGetAttrAccess
);
717 tchar
= (char *) &stuff
[1];
718 name
= MakeAtom(tchar
, stuff
->nbytes
, FALSE
);
720 ReplaceCursor(pSource
, TestForCursorName
, &name
);
725 SProcXFixesChangeCursorByName(ClientPtr client
)
727 REQUEST(xXFixesChangeCursorByNameReq
);
729 swaps(&stuff
->length
);
730 REQUEST_AT_LEAST_SIZE(xXFixesChangeCursorByNameReq
);
731 swapl(&stuff
->source
);
732 swaps(&stuff
->nbytes
);
733 return (*ProcXFixesVector
[stuff
->xfixesReqType
]) (client
);
737 * Routines for manipulating the per-screen hide counts list.
738 * This list indicates which clients have requested cursor hiding
742 /* Return the screen's hide-counts list element for the given client */
743 static CursorHideCountPtr
744 findCursorHideCount(ClientPtr pClient
, ScreenPtr pScreen
)
746 CursorScreenPtr cs
= GetCursorScreen(pScreen
);
747 CursorHideCountPtr pChc
;
749 for (pChc
= cs
->pCursorHideCounts
; pChc
!= NULL
; pChc
= pChc
->pNext
) {
750 if (pChc
->pClient
== pClient
) {
759 createCursorHideCount(ClientPtr pClient
, ScreenPtr pScreen
)
761 CursorScreenPtr cs
= GetCursorScreen(pScreen
);
762 CursorHideCountPtr pChc
;
764 pChc
= (CursorHideCountPtr
) malloc(sizeof(CursorHideCountRec
));
768 pChc
->pClient
= pClient
;
769 pChc
->pScreen
= pScreen
;
771 pChc
->resource
= FakeClientID(pClient
->index
);
772 pChc
->pNext
= cs
->pCursorHideCounts
;
773 cs
->pCursorHideCounts
= pChc
;
776 * Create a resource for this element so it can be deleted
777 * when the client goes away.
779 if (!AddResource(pChc
->resource
, CursorHideCountType
, (pointer
) pChc
)) {
788 * Delete the given hide-counts list element from its screen list.
791 deleteCursorHideCount(CursorHideCountPtr pChcToDel
, ScreenPtr pScreen
)
793 CursorScreenPtr cs
= GetCursorScreen(pScreen
);
794 CursorHideCountPtr pChc
, pNext
;
795 CursorHideCountPtr pChcLast
= NULL
;
797 pChc
= cs
->pCursorHideCounts
;
798 while (pChc
!= NULL
) {
800 if (pChc
== pChcToDel
) {
802 if (pChcLast
== NULL
) {
803 cs
->pCursorHideCounts
= pNext
;
806 pChcLast
->pNext
= pNext
;
816 * Delete all the hide-counts list elements for this screen.
819 deleteCursorHideCountsForScreen(ScreenPtr pScreen
)
821 CursorScreenPtr cs
= GetCursorScreen(pScreen
);
822 CursorHideCountPtr pChc
, pTmp
;
824 pChc
= cs
->pCursorHideCounts
;
825 while (pChc
!= NULL
) {
827 FreeResource(pChc
->resource
, 0);
830 cs
->pCursorHideCounts
= NULL
;
834 ProcXFixesHideCursor(ClientPtr client
)
837 CursorHideCountPtr pChc
;
839 REQUEST(xXFixesHideCursorReq
);
842 REQUEST_SIZE_MATCH(xXFixesHideCursorReq
);
844 ret
= dixLookupResourceByType((pointer
*) &pWin
, stuff
->window
, RT_WINDOW
,
845 client
, DixGetAttrAccess
);
846 if (ret
!= Success
) {
847 client
->errorValue
= stuff
->window
;
852 * Has client hidden the cursor before on this screen?
853 * If so, just increment the count.
856 pChc
= findCursorHideCount(client
, pWin
->drawable
.pScreen
);
863 * This is the first time this client has hid the cursor
866 ret
= XaceHook(XACE_SCREEN_ACCESS
, client
, pWin
->drawable
.pScreen
,
871 ret
= createCursorHideCount(client
, pWin
->drawable
.pScreen
);
873 if (ret
== Success
) {
876 for (dev
= inputInfo
.devices
; dev
; dev
= dev
->next
) {
877 if (IsMaster(dev
) && IsPointerDevice(dev
))
878 CursorDisplayCursor(dev
, pWin
->drawable
.pScreen
,
879 CursorCurrent
[dev
->id
]);
887 SProcXFixesHideCursor(ClientPtr client
)
889 REQUEST(xXFixesHideCursorReq
);
891 swaps(&stuff
->length
);
892 REQUEST_SIZE_MATCH(xXFixesHideCursorReq
);
893 swapl(&stuff
->window
);
894 return (*ProcXFixesVector
[stuff
->xfixesReqType
]) (client
);
898 ProcXFixesShowCursor(ClientPtr client
)
901 CursorHideCountPtr pChc
;
904 REQUEST(xXFixesShowCursorReq
);
906 REQUEST_SIZE_MATCH(xXFixesShowCursorReq
);
908 rc
= dixLookupResourceByType((pointer
*) &pWin
, stuff
->window
, RT_WINDOW
,
909 client
, DixGetAttrAccess
);
911 client
->errorValue
= stuff
->window
;
916 * Has client hidden the cursor on this screen?
917 * If not, generate an error.
919 pChc
= findCursorHideCount(client
, pWin
->drawable
.pScreen
);
924 rc
= XaceHook(XACE_SCREEN_ACCESS
, client
, pWin
->drawable
.pScreen
,
930 if (pChc
->hideCount
<= 0) {
931 FreeResource(pChc
->resource
, 0);
938 SProcXFixesShowCursor(ClientPtr client
)
940 REQUEST(xXFixesShowCursorReq
);
942 swaps(&stuff
->length
);
943 REQUEST_SIZE_MATCH(xXFixesShowCursorReq
);
944 swapl(&stuff
->window
);
945 return (*ProcXFixesVector
[stuff
->xfixesReqType
]) (client
);
949 CursorFreeClient(pointer data
, XID id
)
951 CursorEventPtr old
= (CursorEventPtr
) data
;
952 CursorEventPtr
*prev
, e
;
954 for (prev
= &cursorEvents
; (e
= *prev
); prev
= &e
->next
) {
965 CursorFreeHideCount(pointer data
, XID id
)
967 CursorHideCountPtr pChc
= (CursorHideCountPtr
) data
;
968 ScreenPtr pScreen
= pChc
->pScreen
;
971 deleteCursorHideCount(pChc
, pChc
->pScreen
);
972 for (dev
= inputInfo
.devices
; dev
; dev
= dev
->next
) {
973 if (IsMaster(dev
) && IsPointerDevice(dev
))
974 CursorDisplayCursor(dev
, pScreen
, CursorCurrent
[dev
->id
]);
981 CursorFreeWindow(pointer data
, XID id
)
983 WindowPtr pWindow
= (WindowPtr
) data
;
984 CursorEventPtr e
, next
;
986 for (e
= cursorEvents
; e
; e
= next
) {
988 if (e
->pWindow
== pWindow
) {
989 FreeResource(e
->clientResource
, 0);
996 ProcXFixesCreatePointerBarrier(ClientPtr client
)
998 REQUEST(xXFixesCreatePointerBarrierReq
);
1000 REQUEST_FIXED_SIZE(xXFixesCreatePointerBarrierReq
, pad_to_int32(stuff
->num_devices
));
1001 LEGAL_NEW_RESOURCE(stuff
->barrier
, client
);
1003 return XICreatePointerBarrier(client
, stuff
);
1007 SProcXFixesCreatePointerBarrier(ClientPtr client
)
1009 REQUEST(xXFixesCreatePointerBarrierReq
);
1011 CARD16
*in_devices
= (CARD16
*) &stuff
[1];
1013 swaps(&stuff
->length
);
1014 swaps(&stuff
->num_devices
);
1015 REQUEST_FIXED_SIZE(xXFixesCreatePointerBarrierReq
, pad_to_int32(stuff
->num_devices
));
1017 swapl(&stuff
->barrier
);
1018 swapl(&stuff
->window
);
1023 swapl(&stuff
->directions
);
1024 for (i
= 0; i
< stuff
->num_devices
; i
++) {
1025 swaps(in_devices
+ i
);
1028 return ProcXFixesVector
[stuff
->xfixesReqType
] (client
);
1032 ProcXFixesDestroyPointerBarrier(ClientPtr client
)
1034 REQUEST(xXFixesDestroyPointerBarrierReq
);
1036 REQUEST_SIZE_MATCH(xXFixesDestroyPointerBarrierReq
);
1038 return XIDestroyPointerBarrier(client
, stuff
);
1042 SProcXFixesDestroyPointerBarrier(ClientPtr client
)
1044 REQUEST(xXFixesDestroyPointerBarrierReq
);
1046 swaps(&stuff
->length
);
1047 REQUEST_SIZE_MATCH(xXFixesDestroyPointerBarrierReq
);
1048 swapl(&stuff
->barrier
);
1049 return ProcXFixesVector
[stuff
->xfixesReqType
] (client
);
1053 XFixesCursorInit(void)
1057 if (party_like_its_1989
)
1058 CursorVisible
= EnableCursor
;
1060 if (!dixRegisterPrivateKey(&CursorScreenPrivateKeyRec
, PRIVATE_SCREEN
, 0))
1063 for (i
= 0; i
< screenInfo
.numScreens
; i
++) {
1064 ScreenPtr pScreen
= screenInfo
.screens
[i
];
1067 cs
= (CursorScreenPtr
) calloc(1, sizeof(CursorScreenRec
));
1070 Wrap(cs
, pScreen
, CloseScreen
, CursorCloseScreen
);
1071 Wrap(cs
, pScreen
, DisplayCursor
, CursorDisplayCursor
);
1072 cs
->pCursorHideCounts
= NULL
;
1073 SetCursorScreen(pScreen
, cs
);
1075 CursorClientType
= CreateNewResourceType(CursorFreeClient
,
1076 "XFixesCursorClient");
1077 CursorHideCountType
= CreateNewResourceType(CursorFreeHideCount
,
1078 "XFixesCursorHideCount");
1079 CursorWindowType
= CreateNewResourceType(CursorFreeWindow
,
1080 "XFixesCursorWindow");
1082 return CursorClientType
&& CursorHideCountType
&& CursorWindowType
;