xref: /OK3568_Linux_fs/external/xserver/render/animcur.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  *
3*4882a593Smuzhiyun  * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Permission to use, copy, modify, distribute, and sell this software and its
6*4882a593Smuzhiyun  * documentation for any purpose is hereby granted without fee, provided that
7*4882a593Smuzhiyun  * the above copyright notice appear in all copies and that both that
8*4882a593Smuzhiyun  * copyright notice and this permission notice appear in supporting
9*4882a593Smuzhiyun  * documentation, and that the name of Keith Packard not be used in
10*4882a593Smuzhiyun  * advertising or publicity pertaining to distribution of the software without
11*4882a593Smuzhiyun  * specific, written prior permission.  Keith Packard makes no
12*4882a593Smuzhiyun  * representations about the suitability of this software for any purpose.  It
13*4882a593Smuzhiyun  * is provided "as is" without express or implied warranty.
14*4882a593Smuzhiyun  *
15*4882a593Smuzhiyun  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16*4882a593Smuzhiyun  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17*4882a593Smuzhiyun  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18*4882a593Smuzhiyun  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19*4882a593Smuzhiyun  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20*4882a593Smuzhiyun  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21*4882a593Smuzhiyun  * PERFORMANCE OF THIS SOFTWARE.
22*4882a593Smuzhiyun  */
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun /*
25*4882a593Smuzhiyun  * Animated cursors for X.  Not specific to Render in any way, but
26*4882a593Smuzhiyun  * stuck there because Render has the other cool cursor extension.
27*4882a593Smuzhiyun  * Besides, everyone has Render.
28*4882a593Smuzhiyun  *
29*4882a593Smuzhiyun  * Implemented as a simple layer over the core cursor code; it
30*4882a593Smuzhiyun  * creates composite cursors out of a set of static cursors and
31*4882a593Smuzhiyun  * delta times between each image.
32*4882a593Smuzhiyun  */
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
35*4882a593Smuzhiyun #include <dix-config.h>
36*4882a593Smuzhiyun #endif
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun #include <X11/X.h>
39*4882a593Smuzhiyun #include <X11/Xmd.h>
40*4882a593Smuzhiyun #include "servermd.h"
41*4882a593Smuzhiyun #include "scrnintstr.h"
42*4882a593Smuzhiyun #include "dixstruct.h"
43*4882a593Smuzhiyun #include "cursorstr.h"
44*4882a593Smuzhiyun #include "dixfontstr.h"
45*4882a593Smuzhiyun #include "opaque.h"
46*4882a593Smuzhiyun #include "picturestr.h"
47*4882a593Smuzhiyun #include "inputstr.h"
48*4882a593Smuzhiyun #include "xace.h"
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun typedef struct _AnimCurElt {
51*4882a593Smuzhiyun     CursorPtr pCursor;          /* cursor to show */
52*4882a593Smuzhiyun     CARD32 delay;               /* in ms */
53*4882a593Smuzhiyun } AnimCurElt;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun typedef struct _AnimCur {
56*4882a593Smuzhiyun     int nelt;                   /* number of elements in the elts array */
57*4882a593Smuzhiyun     AnimCurElt *elts;           /* actually allocated right after the structure */
58*4882a593Smuzhiyun     OsTimerPtr timer;
59*4882a593Smuzhiyun } AnimCurRec, *AnimCurPtr;
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun typedef struct _AnimScrPriv {
62*4882a593Smuzhiyun     CloseScreenProcPtr CloseScreen;
63*4882a593Smuzhiyun     CursorLimitsProcPtr CursorLimits;
64*4882a593Smuzhiyun     DisplayCursorProcPtr DisplayCursor;
65*4882a593Smuzhiyun     SetCursorPositionProcPtr SetCursorPosition;
66*4882a593Smuzhiyun     RealizeCursorProcPtr RealizeCursor;
67*4882a593Smuzhiyun     UnrealizeCursorProcPtr UnrealizeCursor;
68*4882a593Smuzhiyun     RecolorCursorProcPtr RecolorCursor;
69*4882a593Smuzhiyun } AnimCurScreenRec, *AnimCurScreenPtr;
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun static unsigned char empty[4];
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun static CursorBits animCursorBits = {
74*4882a593Smuzhiyun     empty, empty, 2, 1, 1, 0, 0, 1
75*4882a593Smuzhiyun };
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun static DevPrivateKeyRec AnimCurScreenPrivateKeyRec;
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun #define IsAnimCur(c)	    ((c) && ((c)->bits == &animCursorBits))
80*4882a593Smuzhiyun #define GetAnimCur(c)	    ((AnimCurPtr) ((((char *)(c) + CURSOR_REC_SIZE))))
81*4882a593Smuzhiyun #define GetAnimCurScreen(s) ((AnimCurScreenPtr)dixLookupPrivate(&(s)->devPrivates, &AnimCurScreenPrivateKeyRec))
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun #define Wrap(as,s,elt,func) (((as)->elt = (s)->elt), (s)->elt = func)
84*4882a593Smuzhiyun #define Unwrap(as,s,elt)    ((s)->elt = (as)->elt)
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun static Bool
AnimCurCloseScreen(ScreenPtr pScreen)87*4882a593Smuzhiyun AnimCurCloseScreen(ScreenPtr pScreen)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun     AnimCurScreenPtr as = GetAnimCurScreen(pScreen);
90*4882a593Smuzhiyun     Bool ret;
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun     Unwrap(as, pScreen, CloseScreen);
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun     Unwrap(as, pScreen, CursorLimits);
95*4882a593Smuzhiyun     Unwrap(as, pScreen, DisplayCursor);
96*4882a593Smuzhiyun     Unwrap(as, pScreen, SetCursorPosition);
97*4882a593Smuzhiyun     Unwrap(as, pScreen, RealizeCursor);
98*4882a593Smuzhiyun     Unwrap(as, pScreen, UnrealizeCursor);
99*4882a593Smuzhiyun     Unwrap(as, pScreen, RecolorCursor);
100*4882a593Smuzhiyun     ret = (*pScreen->CloseScreen) (pScreen);
101*4882a593Smuzhiyun     return ret;
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun static void
AnimCurCursorLimits(DeviceIntPtr pDev,ScreenPtr pScreen,CursorPtr pCursor,BoxPtr pHotBox,BoxPtr pTopLeftBox)105*4882a593Smuzhiyun AnimCurCursorLimits(DeviceIntPtr pDev,
106*4882a593Smuzhiyun                     ScreenPtr pScreen,
107*4882a593Smuzhiyun                     CursorPtr pCursor, BoxPtr pHotBox, BoxPtr pTopLeftBox)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun     AnimCurScreenPtr as = GetAnimCurScreen(pScreen);
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun     Unwrap(as, pScreen, CursorLimits);
112*4882a593Smuzhiyun     if (IsAnimCur(pCursor)) {
113*4882a593Smuzhiyun         AnimCurPtr ac = GetAnimCur(pCursor);
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun         (*pScreen->CursorLimits) (pDev, pScreen, ac->elts[0].pCursor,
116*4882a593Smuzhiyun                                   pHotBox, pTopLeftBox);
117*4882a593Smuzhiyun     }
118*4882a593Smuzhiyun     else {
119*4882a593Smuzhiyun         (*pScreen->CursorLimits) (pDev, pScreen, pCursor, pHotBox, pTopLeftBox);
120*4882a593Smuzhiyun     }
121*4882a593Smuzhiyun     Wrap(as, pScreen, CursorLimits, AnimCurCursorLimits);
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun /*
125*4882a593Smuzhiyun  * The cursor animation timer has expired, go display any relevant cursor changes
126*4882a593Smuzhiyun  * and compute a new timeout value
127*4882a593Smuzhiyun  */
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun static CARD32
AnimCurTimerNotify(OsTimerPtr timer,CARD32 now,void * arg)130*4882a593Smuzhiyun AnimCurTimerNotify(OsTimerPtr timer, CARD32 now, void *arg)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun     DeviceIntPtr dev = arg;
133*4882a593Smuzhiyun     ScreenPtr pScreen = dev->spriteInfo->anim.pScreen;
134*4882a593Smuzhiyun     AnimCurScreenPtr as = GetAnimCurScreen(pScreen);
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun     AnimCurPtr ac = GetAnimCur(dev->spriteInfo->sprite->current);
137*4882a593Smuzhiyun     int elt = (dev->spriteInfo->anim.elt + 1) % ac->nelt;
138*4882a593Smuzhiyun     DisplayCursorProcPtr DisplayCursor = pScreen->DisplayCursor;
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun     /*
141*4882a593Smuzhiyun      * Not a simple Unwrap/Wrap as this isn't called along the DisplayCursor
142*4882a593Smuzhiyun      * wrapper chain.
143*4882a593Smuzhiyun      */
144*4882a593Smuzhiyun     pScreen->DisplayCursor = as->DisplayCursor;
145*4882a593Smuzhiyun     (void) (*pScreen->DisplayCursor) (dev, pScreen, ac->elts[elt].pCursor);
146*4882a593Smuzhiyun     as->DisplayCursor = pScreen->DisplayCursor;
147*4882a593Smuzhiyun     pScreen->DisplayCursor = DisplayCursor;
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun     dev->spriteInfo->anim.elt = elt;
150*4882a593Smuzhiyun     dev->spriteInfo->anim.pCursor = ac->elts[elt].pCursor;
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun     return ac->elts[elt].delay;
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun static void
AnimCurCancelTimer(DeviceIntPtr pDev)156*4882a593Smuzhiyun AnimCurCancelTimer(DeviceIntPtr pDev)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun     CursorPtr cur = pDev->spriteInfo->sprite ?
159*4882a593Smuzhiyun                     pDev->spriteInfo->sprite->current : NULL;
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun     if (IsAnimCur(cur))
162*4882a593Smuzhiyun         TimerCancel(GetAnimCur(cur)->timer);
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun static Bool
AnimCurDisplayCursor(DeviceIntPtr pDev,ScreenPtr pScreen,CursorPtr pCursor)166*4882a593Smuzhiyun AnimCurDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun     AnimCurScreenPtr as = GetAnimCurScreen(pScreen);
169*4882a593Smuzhiyun     Bool ret = TRUE;
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun     if (IsFloating(pDev))
172*4882a593Smuzhiyun         return FALSE;
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun     Unwrap(as, pScreen, DisplayCursor);
175*4882a593Smuzhiyun     if (IsAnimCur(pCursor)) {
176*4882a593Smuzhiyun         if (pCursor != pDev->spriteInfo->sprite->current) {
177*4882a593Smuzhiyun             AnimCurPtr ac = GetAnimCur(pCursor);
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun             AnimCurCancelTimer(pDev);
180*4882a593Smuzhiyun             ret = (*pScreen->DisplayCursor) (pDev, pScreen,
181*4882a593Smuzhiyun                                              ac->elts[0].pCursor);
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun             if (ret) {
184*4882a593Smuzhiyun                 pDev->spriteInfo->anim.elt = 0;
185*4882a593Smuzhiyun                 pDev->spriteInfo->anim.pCursor = pCursor;
186*4882a593Smuzhiyun                 pDev->spriteInfo->anim.pScreen = pScreen;
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun                 ac->timer = TimerSet(ac->timer, 0, ac->elts[0].delay,
189*4882a593Smuzhiyun                                      AnimCurTimerNotify, pDev);
190*4882a593Smuzhiyun             }
191*4882a593Smuzhiyun         }
192*4882a593Smuzhiyun     }
193*4882a593Smuzhiyun     else {
194*4882a593Smuzhiyun         AnimCurCancelTimer(pDev);
195*4882a593Smuzhiyun         pDev->spriteInfo->anim.pCursor = 0;
196*4882a593Smuzhiyun         pDev->spriteInfo->anim.pScreen = 0;
197*4882a593Smuzhiyun         ret = (*pScreen->DisplayCursor) (pDev, pScreen, pCursor);
198*4882a593Smuzhiyun     }
199*4882a593Smuzhiyun     Wrap(as, pScreen, DisplayCursor, AnimCurDisplayCursor);
200*4882a593Smuzhiyun     return ret;
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun static Bool
AnimCurSetCursorPosition(DeviceIntPtr pDev,ScreenPtr pScreen,int x,int y,Bool generateEvent)204*4882a593Smuzhiyun AnimCurSetCursorPosition(DeviceIntPtr pDev,
205*4882a593Smuzhiyun                          ScreenPtr pScreen, int x, int y, Bool generateEvent)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun     AnimCurScreenPtr as = GetAnimCurScreen(pScreen);
208*4882a593Smuzhiyun     Bool ret;
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun     Unwrap(as, pScreen, SetCursorPosition);
211*4882a593Smuzhiyun     if (pDev->spriteInfo->anim.pCursor) {
212*4882a593Smuzhiyun         pDev->spriteInfo->anim.pScreen = pScreen;
213*4882a593Smuzhiyun     }
214*4882a593Smuzhiyun     ret = (*pScreen->SetCursorPosition) (pDev, pScreen, x, y, generateEvent);
215*4882a593Smuzhiyun     Wrap(as, pScreen, SetCursorPosition, AnimCurSetCursorPosition);
216*4882a593Smuzhiyun     return ret;
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun static Bool
AnimCurRealizeCursor(DeviceIntPtr pDev,ScreenPtr pScreen,CursorPtr pCursor)220*4882a593Smuzhiyun AnimCurRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun     AnimCurScreenPtr as = GetAnimCurScreen(pScreen);
223*4882a593Smuzhiyun     Bool ret;
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun     Unwrap(as, pScreen, RealizeCursor);
226*4882a593Smuzhiyun     if (IsAnimCur(pCursor))
227*4882a593Smuzhiyun         ret = TRUE;
228*4882a593Smuzhiyun     else
229*4882a593Smuzhiyun         ret = (*pScreen->RealizeCursor) (pDev, pScreen, pCursor);
230*4882a593Smuzhiyun     Wrap(as, pScreen, RealizeCursor, AnimCurRealizeCursor);
231*4882a593Smuzhiyun     return ret;
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun static Bool
AnimCurUnrealizeCursor(DeviceIntPtr pDev,ScreenPtr pScreen,CursorPtr pCursor)235*4882a593Smuzhiyun AnimCurUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun     AnimCurScreenPtr as = GetAnimCurScreen(pScreen);
238*4882a593Smuzhiyun     Bool ret;
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun     Unwrap(as, pScreen, UnrealizeCursor);
241*4882a593Smuzhiyun     if (IsAnimCur(pCursor)) {
242*4882a593Smuzhiyun         AnimCurPtr ac = GetAnimCur(pCursor);
243*4882a593Smuzhiyun         int i;
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun         if (pScreen->myNum == 0)
246*4882a593Smuzhiyun             for (i = 0; i < ac->nelt; i++)
247*4882a593Smuzhiyun                 FreeCursor(ac->elts[i].pCursor, 0);
248*4882a593Smuzhiyun         ret = TRUE;
249*4882a593Smuzhiyun     }
250*4882a593Smuzhiyun     else
251*4882a593Smuzhiyun         ret = (*pScreen->UnrealizeCursor) (pDev, pScreen, pCursor);
252*4882a593Smuzhiyun     Wrap(as, pScreen, UnrealizeCursor, AnimCurUnrealizeCursor);
253*4882a593Smuzhiyun     return ret;
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun static void
AnimCurRecolorCursor(DeviceIntPtr pDev,ScreenPtr pScreen,CursorPtr pCursor,Bool displayed)257*4882a593Smuzhiyun AnimCurRecolorCursor(DeviceIntPtr pDev,
258*4882a593Smuzhiyun                      ScreenPtr pScreen, CursorPtr pCursor, Bool displayed)
259*4882a593Smuzhiyun {
260*4882a593Smuzhiyun     AnimCurScreenPtr as = GetAnimCurScreen(pScreen);
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun     Unwrap(as, pScreen, RecolorCursor);
263*4882a593Smuzhiyun     if (IsAnimCur(pCursor)) {
264*4882a593Smuzhiyun         AnimCurPtr ac = GetAnimCur(pCursor);
265*4882a593Smuzhiyun         int i;
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun         for (i = 0; i < ac->nelt; i++)
268*4882a593Smuzhiyun             (*pScreen->RecolorCursor) (pDev, pScreen, ac->elts[i].pCursor,
269*4882a593Smuzhiyun                                        displayed &&
270*4882a593Smuzhiyun                                        pDev->spriteInfo->anim.elt == i);
271*4882a593Smuzhiyun     }
272*4882a593Smuzhiyun     else
273*4882a593Smuzhiyun         (*pScreen->RecolorCursor) (pDev, pScreen, pCursor, displayed);
274*4882a593Smuzhiyun     Wrap(as, pScreen, RecolorCursor, AnimCurRecolorCursor);
275*4882a593Smuzhiyun }
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun Bool
AnimCurInit(ScreenPtr pScreen)278*4882a593Smuzhiyun AnimCurInit(ScreenPtr pScreen)
279*4882a593Smuzhiyun {
280*4882a593Smuzhiyun     AnimCurScreenPtr as;
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun     if (!dixRegisterPrivateKey(&AnimCurScreenPrivateKeyRec, PRIVATE_SCREEN,
283*4882a593Smuzhiyun                                sizeof(AnimCurScreenRec)))
284*4882a593Smuzhiyun         return FALSE;
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun     as = GetAnimCurScreen(pScreen);
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun     Wrap(as, pScreen, CloseScreen, AnimCurCloseScreen);
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun     Wrap(as, pScreen, CursorLimits, AnimCurCursorLimits);
291*4882a593Smuzhiyun     Wrap(as, pScreen, DisplayCursor, AnimCurDisplayCursor);
292*4882a593Smuzhiyun     Wrap(as, pScreen, SetCursorPosition, AnimCurSetCursorPosition);
293*4882a593Smuzhiyun     Wrap(as, pScreen, RealizeCursor, AnimCurRealizeCursor);
294*4882a593Smuzhiyun     Wrap(as, pScreen, UnrealizeCursor, AnimCurUnrealizeCursor);
295*4882a593Smuzhiyun     Wrap(as, pScreen, RecolorCursor, AnimCurRecolorCursor);
296*4882a593Smuzhiyun     return TRUE;
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun int
AnimCursorCreate(CursorPtr * cursors,CARD32 * deltas,int ncursor,CursorPtr * ppCursor,ClientPtr client,XID cid)300*4882a593Smuzhiyun AnimCursorCreate(CursorPtr *cursors, CARD32 *deltas, int ncursor,
301*4882a593Smuzhiyun                  CursorPtr *ppCursor, ClientPtr client, XID cid)
302*4882a593Smuzhiyun {
303*4882a593Smuzhiyun     CursorPtr pCursor;
304*4882a593Smuzhiyun     int rc = BadAlloc, i;
305*4882a593Smuzhiyun     AnimCurPtr ac;
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun     for (i = 0; i < screenInfo.numScreens; i++)
308*4882a593Smuzhiyun         if (!GetAnimCurScreen(screenInfo.screens[i]))
309*4882a593Smuzhiyun             return BadImplementation;
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun     for (i = 0; i < ncursor; i++)
312*4882a593Smuzhiyun         if (IsAnimCur(cursors[i]))
313*4882a593Smuzhiyun             return BadMatch;
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun     pCursor = (CursorPtr) calloc(CURSOR_REC_SIZE +
316*4882a593Smuzhiyun                                  sizeof(AnimCurRec) +
317*4882a593Smuzhiyun                                  ncursor * sizeof(AnimCurElt), 1);
318*4882a593Smuzhiyun     if (!pCursor)
319*4882a593Smuzhiyun         return rc;
320*4882a593Smuzhiyun     dixInitPrivates(pCursor, pCursor + 1, PRIVATE_CURSOR);
321*4882a593Smuzhiyun     pCursor->bits = &animCursorBits;
322*4882a593Smuzhiyun     pCursor->refcnt = 1;
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun     pCursor->foreRed = cursors[0]->foreRed;
325*4882a593Smuzhiyun     pCursor->foreGreen = cursors[0]->foreGreen;
326*4882a593Smuzhiyun     pCursor->foreBlue = cursors[0]->foreBlue;
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun     pCursor->backRed = cursors[0]->backRed;
329*4882a593Smuzhiyun     pCursor->backGreen = cursors[0]->backGreen;
330*4882a593Smuzhiyun     pCursor->backBlue = cursors[0]->backBlue;
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun     pCursor->id = cid;
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun     ac = GetAnimCur(pCursor);
335*4882a593Smuzhiyun     ac->timer = TimerSet(NULL, 0, 0, AnimCurTimerNotify, NULL);
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun     /* security creation/labeling check */
338*4882a593Smuzhiyun     if (ac->timer)
339*4882a593Smuzhiyun         rc = XaceHook(XACE_RESOURCE_ACCESS, client, cid, RT_CURSOR, pCursor,
340*4882a593Smuzhiyun                       RT_NONE, NULL, DixCreateAccess);
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun     if (rc != Success) {
343*4882a593Smuzhiyun         TimerFree(ac->timer);
344*4882a593Smuzhiyun         dixFiniPrivates(pCursor, PRIVATE_CURSOR);
345*4882a593Smuzhiyun         free(pCursor);
346*4882a593Smuzhiyun         return rc;
347*4882a593Smuzhiyun     }
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun     /*
350*4882a593Smuzhiyun      * Fill in the AnimCurRec
351*4882a593Smuzhiyun      */
352*4882a593Smuzhiyun     animCursorBits.refcnt++;
353*4882a593Smuzhiyun     ac->nelt = ncursor;
354*4882a593Smuzhiyun     ac->elts = (AnimCurElt *) (ac + 1);
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun     for (i = 0; i < ncursor; i++) {
357*4882a593Smuzhiyun         ac->elts[i].pCursor = RefCursor(cursors[i]);
358*4882a593Smuzhiyun         ac->elts[i].delay = deltas[i];
359*4882a593Smuzhiyun     }
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun     *ppCursor = pCursor;
362*4882a593Smuzhiyun     return Success;
363*4882a593Smuzhiyun }
364