3 * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of Keith Packard not be used in
10 * advertising or publicity pertaining to distribution of the software without
11 * specific, written prior permission. Keith Packard makes no
12 * representations about the suitability of this software for any purpose. It
13 * is provided "as is" without express or implied warranty.
15 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21 * PERFORMANCE OF THIS SOFTWARE.
25 * Animated cursors for X. Not specific to Render in any way, but
26 * stuck there because Render has the other cool cursor extension.
27 * Besides, everyone has Render.
29 * Implemented as a simple layer over the core cursor code; it
30 * creates composite cursors out of a set of static cursors and
31 * delta times between each image.
34 #ifdef HAVE_DIX_CONFIG_H
35 #include <dix-config.h>
41 #include "scrnintstr.h"
42 #include "dixstruct.h"
43 #include "cursorstr.h"
44 #include "dixfontstr.h"
46 #include "picturestr.h"
50 typedef struct _AnimCurElt
{
51 CursorPtr pCursor
; /* cursor to show */
52 CARD32 delay
; /* in ms */
55 typedef struct _AnimCur
{
56 int nelt
; /* number of elements in the elts array */
57 AnimCurElt
*elts
; /* actually allocated right after the structure */
58 } AnimCurRec
, *AnimCurPtr
;
60 typedef struct _AnimScrPriv
{
61 CloseScreenProcPtr CloseScreen
;
63 ScreenBlockHandlerProcPtr BlockHandler
;
65 CursorLimitsProcPtr CursorLimits
;
66 DisplayCursorProcPtr DisplayCursor
;
67 SetCursorPositionProcPtr SetCursorPosition
;
68 RealizeCursorProcPtr RealizeCursor
;
69 UnrealizeCursorProcPtr UnrealizeCursor
;
70 RecolorCursorProcPtr RecolorCursor
;
71 } AnimCurScreenRec
, *AnimCurScreenPtr
;
73 static unsigned char empty
[4];
75 static CursorBits animCursorBits
= {
76 empty
, empty
, 2, 1, 1, 0, 0, 1
79 static DevPrivateKeyRec AnimCurScreenPrivateKeyRec
;
81 #define AnimCurScreenPrivateKey (&AnimCurScreenPrivateKeyRec)
83 #define IsAnimCur(c) ((c) && ((c)->bits == &animCursorBits))
84 #define GetAnimCur(c) ((AnimCurPtr) ((((char *)(c) + CURSOR_REC_SIZE))))
85 #define GetAnimCurScreen(s) ((AnimCurScreenPtr)dixLookupPrivate(&(s)->devPrivates, AnimCurScreenPrivateKey))
86 #define SetAnimCurScreen(s,p) dixSetPrivate(&(s)->devPrivates, AnimCurScreenPrivateKey, p)
88 #define Wrap(as,s,elt,func) (((as)->elt = (s)->elt), (s)->elt = func)
89 #define Unwrap(as,s,elt) ((s)->elt = (as)->elt)
92 AnimCurCloseScreen(ScreenPtr pScreen
)
94 AnimCurScreenPtr as
= GetAnimCurScreen(pScreen
);
97 Unwrap(as
, pScreen
, CloseScreen
);
99 Unwrap(as
, pScreen
, CursorLimits
);
100 Unwrap(as
, pScreen
, DisplayCursor
);
101 Unwrap(as
, pScreen
, SetCursorPosition
);
102 Unwrap(as
, pScreen
, RealizeCursor
);
103 Unwrap(as
, pScreen
, UnrealizeCursor
);
104 Unwrap(as
, pScreen
, RecolorCursor
);
105 SetAnimCurScreen(pScreen
, 0);
106 ret
= (*pScreen
->CloseScreen
) (pScreen
);
112 AnimCurCursorLimits(DeviceIntPtr pDev
,
114 CursorPtr pCursor
, BoxPtr pHotBox
, BoxPtr pTopLeftBox
)
116 AnimCurScreenPtr as
= GetAnimCurScreen(pScreen
);
118 Unwrap(as
, pScreen
, CursorLimits
);
119 if (IsAnimCur(pCursor
)) {
120 AnimCurPtr ac
= GetAnimCur(pCursor
);
122 (*pScreen
->CursorLimits
) (pDev
, pScreen
, ac
->elts
[0].pCursor
,
123 pHotBox
, pTopLeftBox
);
126 (*pScreen
->CursorLimits
) (pDev
, pScreen
, pCursor
, pHotBox
, pTopLeftBox
);
128 Wrap(as
, pScreen
, CursorLimits
, AnimCurCursorLimits
);
132 * This has to be a screen block handler instead of a generic
133 * block handler so that it is well ordered with respect to the DRI
134 * block handler responsible for releasing the hardware to DRI clients
138 AnimCurScreenBlockHandler(ScreenPtr pScreen
,
139 pointer pTimeout
, pointer pReadmask
)
141 AnimCurScreenPtr as
= GetAnimCurScreen(pScreen
);
143 Bool activeDevice
= FALSE
;
144 CARD32 now
= 0, soonest
= ~0; /* earliest time to wakeup again */
146 Unwrap(as
, pScreen
, BlockHandler
);
148 for (dev
= inputInfo
.devices
; dev
; dev
= dev
->next
) {
149 if (IsPointerDevice(dev
) && pScreen
== dev
->spriteInfo
->anim
.pScreen
) {
151 now
= GetTimeInMillis();
155 if ((INT32
) (now
- dev
->spriteInfo
->anim
.time
) >= 0) {
156 AnimCurPtr ac
= GetAnimCur(dev
->spriteInfo
->anim
.pCursor
);
157 int elt
= (dev
->spriteInfo
->anim
.elt
+ 1) % ac
->nelt
;
158 DisplayCursorProcPtr DisplayCursor
;
161 * Not a simple Unwrap/Wrap as this
162 * isn't called along the DisplayCursor
165 DisplayCursor
= pScreen
->DisplayCursor
;
166 pScreen
->DisplayCursor
= as
->DisplayCursor
;
167 (void) (*pScreen
->DisplayCursor
) (dev
,
169 ac
->elts
[elt
].pCursor
);
170 as
->DisplayCursor
= pScreen
->DisplayCursor
;
171 pScreen
->DisplayCursor
= DisplayCursor
;
173 dev
->spriteInfo
->anim
.elt
= elt
;
174 dev
->spriteInfo
->anim
.time
= now
+ ac
->elts
[elt
].delay
;
177 if (soonest
> dev
->spriteInfo
->anim
.time
)
178 soonest
= dev
->spriteInfo
->anim
.time
;
183 AdjustWaitForDelay(pTimeout
, soonest
- now
);
185 (*pScreen
->BlockHandler
) (pScreen
, pTimeout
, pReadmask
);
187 Wrap(as
, pScreen
, BlockHandler
, AnimCurScreenBlockHandler
);
189 as
->BlockHandler
= NULL
;
193 AnimCurDisplayCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
, CursorPtr pCursor
)
195 AnimCurScreenPtr as
= GetAnimCurScreen(pScreen
);
198 if (IsFloating(pDev
))
201 Unwrap(as
, pScreen
, DisplayCursor
);
202 if (IsAnimCur(pCursor
)) {
203 if (pCursor
!= pDev
->spriteInfo
->anim
.pCursor
) {
204 AnimCurPtr ac
= GetAnimCur(pCursor
);
206 ret
= (*pScreen
->DisplayCursor
)
207 (pDev
, pScreen
, ac
->elts
[0].pCursor
);
209 pDev
->spriteInfo
->anim
.elt
= 0;
210 pDev
->spriteInfo
->anim
.time
=
211 GetTimeInMillis() + ac
->elts
[0].delay
;
212 pDev
->spriteInfo
->anim
.pCursor
= pCursor
;
213 pDev
->spriteInfo
->anim
.pScreen
= pScreen
;
215 if (!as
->BlockHandler
)
216 Wrap(as
, pScreen
, BlockHandler
, AnimCurScreenBlockHandler
);
223 pDev
->spriteInfo
->anim
.pCursor
= 0;
224 pDev
->spriteInfo
->anim
.pScreen
= 0;
225 ret
= (*pScreen
->DisplayCursor
) (pDev
, pScreen
, pCursor
);
227 Wrap(as
, pScreen
, DisplayCursor
, AnimCurDisplayCursor
);
232 AnimCurSetCursorPosition(DeviceIntPtr pDev
,
233 ScreenPtr pScreen
, int x
, int y
, Bool generateEvent
)
235 AnimCurScreenPtr as
= GetAnimCurScreen(pScreen
);
238 Unwrap(as
, pScreen
, SetCursorPosition
);
239 if (pDev
->spriteInfo
->anim
.pCursor
) {
240 pDev
->spriteInfo
->anim
.pScreen
= pScreen
;
242 if (!as
->BlockHandler
)
243 Wrap(as
, pScreen
, BlockHandler
, AnimCurScreenBlockHandler
);
245 ret
= (*pScreen
->SetCursorPosition
) (pDev
, pScreen
, x
, y
, generateEvent
);
246 Wrap(as
, pScreen
, SetCursorPosition
, AnimCurSetCursorPosition
);
251 AnimCurRealizeCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
, CursorPtr pCursor
)
253 AnimCurScreenPtr as
= GetAnimCurScreen(pScreen
);
256 Unwrap(as
, pScreen
, RealizeCursor
);
257 if (IsAnimCur(pCursor
))
260 ret
= (*pScreen
->RealizeCursor
) (pDev
, pScreen
, pCursor
);
261 Wrap(as
, pScreen
, RealizeCursor
, AnimCurRealizeCursor
);
266 AnimCurUnrealizeCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
, CursorPtr pCursor
)
268 AnimCurScreenPtr as
= GetAnimCurScreen(pScreen
);
271 Unwrap(as
, pScreen
, UnrealizeCursor
);
272 if (IsAnimCur(pCursor
)) {
273 AnimCurPtr ac
= GetAnimCur(pCursor
);
276 if (pScreen
->myNum
== 0)
277 for (i
= 0; i
< ac
->nelt
; i
++)
278 FreeCursor(ac
->elts
[i
].pCursor
, 0);
282 ret
= (*pScreen
->UnrealizeCursor
) (pDev
, pScreen
, pCursor
);
283 Wrap(as
, pScreen
, UnrealizeCursor
, AnimCurUnrealizeCursor
);
288 AnimCurRecolorCursor(DeviceIntPtr pDev
,
289 ScreenPtr pScreen
, CursorPtr pCursor
, Bool displayed
)
291 AnimCurScreenPtr as
= GetAnimCurScreen(pScreen
);
293 Unwrap(as
, pScreen
, RecolorCursor
);
294 if (IsAnimCur(pCursor
)) {
295 AnimCurPtr ac
= GetAnimCur(pCursor
);
298 for (i
= 0; i
< ac
->nelt
; i
++)
299 (*pScreen
->RecolorCursor
) (pDev
, pScreen
, ac
->elts
[i
].pCursor
,
301 pDev
->spriteInfo
->anim
.elt
== i
);
304 (*pScreen
->RecolorCursor
) (pDev
, pScreen
, pCursor
, displayed
);
305 Wrap(as
, pScreen
, RecolorCursor
, AnimCurRecolorCursor
);
309 AnimCurInit(ScreenPtr pScreen
)
313 if (!dixRegisterPrivateKey(&AnimCurScreenPrivateKeyRec
, PRIVATE_SCREEN
, 0))
316 as
= (AnimCurScreenPtr
) malloc(sizeof(AnimCurScreenRec
));
319 Wrap(as
, pScreen
, CloseScreen
, AnimCurCloseScreen
);
321 as
->BlockHandler
= NULL
;
323 Wrap(as
, pScreen
, CursorLimits
, AnimCurCursorLimits
);
324 Wrap(as
, pScreen
, DisplayCursor
, AnimCurDisplayCursor
);
325 Wrap(as
, pScreen
, SetCursorPosition
, AnimCurSetCursorPosition
);
326 Wrap(as
, pScreen
, RealizeCursor
, AnimCurRealizeCursor
);
327 Wrap(as
, pScreen
, UnrealizeCursor
, AnimCurUnrealizeCursor
);
328 Wrap(as
, pScreen
, RecolorCursor
, AnimCurRecolorCursor
);
329 SetAnimCurScreen(pScreen
, as
);
334 AnimCursorCreate(CursorPtr
*cursors
, CARD32
*deltas
, int ncursor
,
335 CursorPtr
*ppCursor
, ClientPtr client
, XID cid
)
341 for (i
= 0; i
< screenInfo
.numScreens
; i
++)
342 if (!GetAnimCurScreen(screenInfo
.screens
[i
]))
343 return BadImplementation
;
345 for (i
= 0; i
< ncursor
; i
++)
346 if (IsAnimCur(cursors
[i
]))
349 pCursor
= (CursorPtr
) calloc(CURSOR_REC_SIZE
+
351 ncursor
* sizeof(AnimCurElt
), 1);
354 dixInitPrivates(pCursor
, pCursor
+ 1, PRIVATE_CURSOR
);
355 pCursor
->bits
= &animCursorBits
;
358 pCursor
->foreRed
= cursors
[0]->foreRed
;
359 pCursor
->foreGreen
= cursors
[0]->foreGreen
;
360 pCursor
->foreBlue
= cursors
[0]->foreBlue
;
362 pCursor
->backRed
= cursors
[0]->backRed
;
363 pCursor
->backGreen
= cursors
[0]->backGreen
;
364 pCursor
->backBlue
= cursors
[0]->backBlue
;
368 /* security creation/labeling check */
369 rc
= XaceHook(XACE_RESOURCE_ACCESS
, client
, cid
, RT_CURSOR
, pCursor
,
370 RT_NONE
, NULL
, DixCreateAccess
);
372 dixFiniPrivates(pCursor
, PRIVATE_CURSOR
);
378 * Fill in the AnimCurRec
380 animCursorBits
.refcnt
++;
381 ac
= GetAnimCur(pCursor
);
383 ac
->elts
= (AnimCurElt
*) (ac
+ 1);
385 for (i
= 0; i
< ncursor
; i
++) {
386 ac
->elts
[i
].pCursor
= RefCursor(cursors
[i
]);
387 ac
->elts
[i
].delay
= deltas
[i
];